Greatings

Have a nice day

Vue中的一些坑

1. 数据改变后视图不刷新

当改变data中绑定的object时,视图有时不会改变,当下次视图更新后才会显现出来。这有两个解决办法:

  1. vm.$forceUpdate()
  2. 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) : ''
    }
}