Vue中的一些坑
1. 数据改变后视图不刷新
当改变data中绑定的object时,视图有时不会改变,当下次视图更新后才会显现出来。这有两个解决办法:
vm.$forceUpdate()
vm.$delete( target, key )
+vm.$set( target, key, value )
其中第一个方案有一个很大的弊端,就是它只会更新当前组件的视图,并不会影响子组件
第二个方案是使用Vue中定义好的两个方法,先将object上的一个属性删除,然后再另外赋值
以上两种方案能解决大多数改变数据后视图不刷新的情况
2. Vue中使用JSX
有次在项目中用Element UI中的Tree组件,我想要自定义Tree中节点的内容,根据Element的文档,我需要在methods中指定渲染函数:
renderContent(h, { node, data, store }) {
return (
<span>
<span>
<span>{node.label}</span>
</span>
<span style="float: right; margin-right: 20px">
<el-button size="mini" on-click={ () => this.append(store, data) }>Append</el-button>
<el-button size="mini" on-click={ () => this.remove(store, data) }>Delete</el-button>
</span>
</span>);
}
这种在js中混合HTML代码的方式就是JSX,简单的说,JSX只是一种语法糖它首先由React发明,后来也被Vue所引入。
但当我在代码中这么写的时候,却发现eslint报错,貌似并不支持JSX的语法。
查询文档后发现,其实需要先在项目中引入babel-plugin-transform-vue-jsx。
引入JSX
安装
npm install\
babel-plugin-syntax-jsx\
babel-plugin-transform-vue-jsx\
babel-helper-vue-jsx-merge-props\
babel-preset-es2015\
--save-dev
在.babelrc
中配置
{
"presets": ["es2015"],
"plugins": ["transform-vue-jsx"]
}
使用
JSX会将如下代码
<div id="foo">{this.text}</div>
转化为
h('div', {
attrs: {
id: 'foo'
}
}, [this.text])
这个h
函数其实是Vue实力中$createElement
方法的缩写,它必须在JSX所在的作用域中。
在Vue的JSX中将字符串渲染为HTML
在这个项目中,我需要将JSON中的一个字符串渲染为一个<p>
,而且还要使用JSX的语法。而Vue中JSX与React并不完全相同,需要这么写:
<p domPropsInnerHTML={data.description}></p>
3. router中配置mode: 'history'
出现的问题
当router中配置mode: 'history'
时,地址栏中会显示常见的//xxx.xx/aa/bb
这种地址。默认的是hash
模式,这种模式下地址栏的URL就会类似于//xxx.xx/#/aa/bb
。
history模式虽然会好看一些,但是在部署后会出现问题:在非根目录URL时刷新页面会出现404错误
因此,如果没有特殊要求,还是保持默认值就好。
4.使用Vuex时在IE中报错
使用Vue+Vuex时,项目在IE11下报错: [vuex] vuex requires a Promise polyfill in this browser.
原因是Vuex需要用到Promise
功能,而IE除了Edge外的浏览器都不支持该功能:查看浏览器支持情况。
解决方案:
若使用vue-cli生成的项目目录,只需要npm install --save-dev babel-polyfill
,然后在webpack.base.conf.js中将
module.exports = {
entry: {
app: './src/main.js'
},
修改为:
module.exports = {
entry: {
app: ['babel-polyfill', './src/main.js']
},
即可。
如果没有使用webpack,可以在html中添加
<script src='https://cdn.polyfill.io/v2/polyfill.min.js'></script>
5. build后图片相对路径问题
由于vue中webpack的默认配置,静态资源是放在服务根目录的,但是实际场景中通常需要将build后的文件放到相对路径中,所以需要修改config/index.js配置中的assetsPublicPath: './'
。
但是这样带来的问题就是css图片的引用地址就会相对于/static/css目录,因此有两种解决办法:
一种是在webpack中build的配置文件增加拷贝img到css目录的功能。
另一种比较推荐的做法是在 build/utils.js
中的 ExtractTextPlugin.extract
传入参数 publicPath: '../../'
6. 动态加载图片
直接给img的src传入computed结果为字符串形式的图片路径,webpack并不会解析,因为这个路径只会在页面运行时被计算,webpack没有改变它的机会。
解决方案:
<img :src="imagePath(img)">
methods: {
imagePath(imgName) {
return imgName ? require('@/assets/img/' + imgName) : ''
}
}