公司年初开始从jquery转型到vue开发,思想上从jquery的操做DOM到vue的操做数据,刚开始还不太习惯,但用了一段时间发现确实比较方便。在刚开始用vue的时候,也踩了一些坑,如今分享出来,供刚入门上手开发vue的朋友参考,都是一些刚接触vue开发遇到的比较常见的问题,vue老手可越过。css
vue中的props是单向绑定的,父组件的属性变化时会传递给子组件,子组件内部不该改变props的值,不然控制台会给出警告。
但若是props的类型为数组或者对象时,在子组件内部改变props的值控制台不会警告。由于数组或对象是地址引用,vue不会检测到props发生改变。因此有的状况须要在子组件内部改变父组件的值,能够将属性定义为数组或者对象类型传入。
但官方不建议在子组件内改变父组件的值,由于这违反了vue中props单向绑定的思想。vue
由1能够引伸出,地址引用类型的数据,例如对象obj ={a:1},若是想要修改obj中的a属性,经过obj.a = 2这样赋值,页面不会更新,需使用vue.set方法更改才会起做用, Vue.set(this,obj,a,2)
;
一样,若是要给obj增长一个新属性,若是该属性未在data中声明,页面也不会刷新。也就是vue文档中声明的“Vue 不能检测到对象属性的添加或删除”,一样须要使用vue.set方法进行赋值才好使。node
对象或数组的简单赋值,修改新值也会改变原值。这时咱们须要获取原值的深拷贝对象。
对于对象,能够经过newObj = JSON.parse(JSON.stringfy(obj))
实现。
对于数组,能够经过 newArr = […arr]
或者newArr = arr.slice(0)
来实现。jquery
vue中每个组件均可以自定各自的css样式,若是但愿组件内的样式只对当前组件起做用,能够在style标签中增长scoped便可。
该写法会让vue在渲染组件的时候给每一个元素都增长一个data-v-/版本号/的属性,能够保证只针对有一样data-v-data-v-/版本号/的元素应用该样式。webpack
vue中的v-for循环最好加上key属性,不然在高版本(2.2.0+)的vue中控制台会报错。
key属性须要惟一,理想的 key 值是每项都有惟一 id,全局不需惟一,但在一个循环中须要惟一。ios
图片引用问题。直接把本地图片地址放在src里没问题。但若是把地址提取出来写在data里或者经过method动态给src赋值则引用不到。
由于放在template模板里会被webpack打包因此能够,而放在data或者动态赋值,图片路径只是一个字符串webpack不会处理因此引用不到。
解决办法:经过import或者required引入。import src from ‘../../img.png’
或者data:{img:require(‘../../img.png’)}
nginx
在子组件使用父组件传入的值时,最好复制出一份props
的值,经过data
或者computed
进行赋值。data
赋值与computed
赋值的区别:data
赋值:data:{return {aaa: this.aaa}
若是是在data
中进行赋值,当父组件的aaa
值发生改变时,不会在从新赋给子组件中的aaa
。computed
赋值:若是想让子组件跟着父组件修改,须要将赋值操做写在computed
中。computed:{aaa(){return this.aaa}
web
后端传过来的数组是一个数组对象,页面中绑定对象中某一具体的属性,当该值变化时调用某个函数,天然想到就是watch
方法。但如何watch
数组对象中某一个具体的属性,显然不可能一个个属性写watch
。
解决办法:
1.watch
整个对象,设置deep
为true
,当该对象发生改变时,调用处理函数。
2.将页面中绑定的属性写在computed
函数中,watch
这个computed
中的函数,当对象值改变时会进入computed
函数中,进而进入watch
函数中,再调用处理函数。vue-cli
给元素动态增长class
时,能够在模板中经过:class={‘hasClass’: ifHasClass}
来实现,当ifHasClass
为true
时,该元素会自动加上hasClass
的样式。
动态绑定的class
能够与正常写的一块儿使用<a class=‘aaa’ :class={‘bbb’:isBbb}></a>
,但若是在一个元素中使用了两个class
则会报错<a class="aaa" class="bbb"></a>
。json
若是咱们在页面A中使用了一个定时器,当从页面A跳转到页面B时,若是不手动清除这个定时器,那么它仍旧会执行,这不是咱们所指望的。
一般能想到的常规解决办法就是,在data
属性中定义一个timer
,在代码中启动定时器,而后在组件销毁的时候清除定时器。具体代码以下:
data(){ return{ timer:null } }, methods:{ onStartTimer(){ this.timer = setInterval( () => { // 执行一些操做 }, 1000) } }, beforeDestroy() { clearInterval(this.timer); this.timer = null; }
可是这里有两个潜在的问题:
timer
,若是能够的话最好只有生命周期钩子能够访问到它。这并不算严重的问题,可是它能够被视为杂物。Vue
官方文档给出的解决方案是,在定义timer的时候使用$once
指令监听beforeDestroy
这个钩子函数。具体代码为:
methods:{ onStartTimer(){ const timer = setInterval( () => { // 执行一些操做 }, 1000) this.$once('hook:beforeDestroy', () => { clearInterval(timer); }) } },
这样就解决了上面所列的两个问题。相似的这种在离开页面时须要销毁的组件均可以采用此方法。
在本地开发请求后端服务器接口的时候,都不可避免的会遇到跨域的问题。解决方法能够经过加一个node
中间层或者nginx
作反向代理。可是若是是用vue-cli
搭建的项目,vue-cli
在config
中自带了一个proxyTable
属性,能够配置这个属性解决跨域的问题。
// config/index.js module.exports = { // ... dev: { proxyTable: { '/api': { // 遇到/api的接口都会走此代理,所以在调用接口时,须要在url中增长/api标识 target: 'http://jsonplaceholder.typicode.com', // 真实的地址 changeOrigin: true, // 是否启用跨域 pathRewrite: { '^/api': '' // 将接口中的/api替换成'' } } } } }
以上代码会将 /api/posts/1
请求代理到 http://jsonplaceholder.typicode.com/posts/1
。
若是不想在每个接口中都手动增长/api
标识,能够更改axios
的默认配置axios.defaults.baseURL = '/api'
,这样,axios
会自动帮咱们在url
上加上/api
的前缀。
须要特别注意的是,更改完配置后须要重启server才会生效。