这是我参与更文挑战的第29天,活动详情查看: 更文挑战
1,Vue中,computed 和 watch有什么区别?
计算属性computed
1, 支持缓存, 只有依赖的数据发生变化的时候,才会重新进行计算
2, 不支持异步,当computed内有异步操作时无效,无法监听数据的变化
3, 计算属性的函数中都有一个get, set
如果computed属性属性值是函数,那么默认会走get方法;函数的返回值就是属性的属性值;
在computed中的,属性都有一个get和一个set方法,当数据变化时,调用set方法。
4, computed 属性值会默认走缓存,计算属性是基于它们的响应式依赖进行缓存的,
也就是基于data中声明 过或者父组件传递的props中的数据通过计算得到的值
5, 如果一个属性是由其他属性计算而来的,这个属性依赖其他属性,是一个多对一或者一对一,一般用computed
6, 计算属性是自动监听依赖值的变化,从而动态的返回内容
侦听属性watch
1, 不支持缓存,只要数据发生变化,就会执行侦听函数
2, 支持异步操作
3, 侦听属性的值可以是一个对象,接收handle回调, deep, immediate 三个属性
4, 监听是一个过程,在监听的值发生变化的时候,可以触发一个回调,完成其他操作
5, 监听的函数接收两个参数,第一个参数是最新的值;第二个参数是输入之前的值
6, 当一个属性发生变化时,需要执行对应的操作;一对多;
watch: {
obj: {
handler(newVal, oldVal) {
console.log(newVal)
},
deep: true, // 深度监听,为了发现对象内部值的变化,复杂类型的数据时使用
immediate: true // 加载组件立即触发回调函数执行
}
}
2,为什么需要使用Vue.set ?
Vue.set 向响应式对象中添加响应式属性,及设置数组元素触发视图更新
因为vue中不能检测到数组长度的变化,也不能检测数组通过索引修改值内容,同时也不能检测对象属性的添加和删
除,如果想动态的给数组,对象添加或者修改数据,并更新视图,可以通过:
Vue.$set(target, key, value)
因为:vue在构造函数new Vue()时,就通过Object.defineProperty中的getter和setter这两个方法,完成了
对数据的绑定,所以直接通过 xxx = 'xxx'这种赋值的方法,是无法修改值去触发vue中视图的更新,必须通过
Object.defineProperty的方法去改变,而Vue.$set()就封装了JS底层的Object.defineProperty方法。由于
Vue在初始化实例时对属性执行getter/settter操作,所以属性必须在data对象上存在才能让实现响应式
data () {
return {
form: {
count: 1
}
}
}
// this.form.count是响应式的
// 若直接增加属性,是非响应式的
this.form.flage = true //非响应式的
// 如果想实现响应式
Vue.set(this.form, 'flage', true) // 响应式添加属性
使用Vue.set(object, key, value)方法将响应属性添加到嵌套的对象上
Vue.set(this.form, 'flage', true)
还可以使用vm.$set实例方法,这也是全局Vue.set方法的别名
this.$set(this.form, 'flage', true)
**总结:**Vue.set(target, key/index, value) 向响应式对象中添加一个属性,并确保这个新属性同样是响应式的,且触发视图更新
3,$nextTick是什么,应用的场景?
Vue实现响应式并不是在数据发生后立即更新DOM,使用vm.$nextTick 是在下次DOM更新循环结束之后立即执行延迟回调,在修改数据之后使用,则可以在回调中获取更新后的DOM,
Vue中数据和DOM渲染是异步的,所以,要让DOM结构随数据改变这样的操作都应该放进this.$nextTick()的回调函数中。
简单理解:就是获取更新后的DOM就是$nextTick()方法,
nextTick(),是将回调函数延迟在下一次dom更新数据后调用,简单的理解是:当数据更新了,在dom中渲染后,
自动执行该函数,
再次说明:Vue 实现响应式并不是数据发生变化之后 DOM 立即变化,而是按一定的策略进行 DOM 的更新。$nextTick 是在下次 DOM 更新循环结束之后执行延迟回调,在修改数据之后使用 $nextTick,则可以在回调中获取更新后的 DOM,
什么时候需要用的Vue.nextTick()?
1, Vue生命周期的created()钩子函数进行的DOM操作一定要放在Vue.nextTick()的回调函数中,原因是在created()钩子函数执行的时候DOM 其实并未进行任何渲染,而此时进行DOM操作无异于徒劳,所以此处一定要将DOM操作的js代码放进Vue.nextTick()的回调函数中。与之对应的就是mounted钩子函数,因为该钩子函数执行时所有的DOM挂载已完成。
created(){
let self = this;
that.$nextTick(function(){ //不使用this.$nextTick()方法会报错
that.$refs.aa.innerHTML="xxxxxxxx"; //写入到DOM元素
});
},
2, 当项目中你想在改变DOM元素的数据后基于新的dom做点什么,**对新DOM一系列的js操作都需要放进Vue.nextTick()的回调函数中;**通俗的理解就是:更改数据后当你想立即使用js操作新的视图的时候需要使用它
**总结:**使用Vue.nextTick()是为了可以获取更新后的DOM 。
触发时机:在同一事件循环中的数据变化后,DOM完成更新,立即执行Vue.nextTick()的回调
同一事件循环中的代码执行完毕(nextTicke) -> DOM 更新 -> nextTick回调(callback)触发执行
4,Vue的双向数据绑定原理是什么?
Vue采用数据劫持 + 订阅发布模式实现双向绑定。通过Object.defineProperty() 方法来为组件中data的每个属性添加get和set方法,在数据变动时,触发set里面相应的监听回调函数,将变动信息发布给订阅者。
组件初始化:
1,创建一个dep对象作为观察者(依赖收集,订阅发布的载体)
2,通过Object.defineProperty()方法对data中的属性及子属性对象的属性,添加getter和setter方法,调用
getter时,便去dep里注册函数。调用setter时,便去通知执行刚刚注册的函数。
组件挂载时:
3,compile解析模版指令,将其中的变量替换成数据。然后初始化渲染页面视图,并将每个指令对应的节点绑定上更
新函数,监听函数。后续一旦数据发生变化,便会更新页面。页面发生变化时也会相应发布变动信息
4,组件同时会定义一个watcher类作为订阅者,watcher可以视作dep和组件之间的桥梁。其在实例化时会向dep中
添加自己,同时自身又有一个update方法,待收到dep的变动通知时,便会调用自己的update方法,触发compile中
的相应函数完成更新
5,Vue初始化页面闪动问题如何解决?
出现该现象是因为在Vue代码尚未被解析之前,无法控制页面中DOM的显示,所以会看见模版字符串等等代码。
解决方案: 在CSS代码中添加v-cloak规则,同时在待编译的标签上添加v-cloak属性
[v-cloak] {display: none;}
<div v-cloak>
{{ message }}
</div>
6,Vue 如何清楚浏览器缓存?
1, 项目打包的时候给每个打包文件加上hash值,一般是在文件后面加上时间戳
2,在html文件中加入meta标签,content属性设置为:no-cache
3, 在后端服务器中禁止缓存设置
7,Vue组件中data为什么必须是一个函数?
如果data是一个对象,当复用组件时候,因为data都会指向统一引用类型地址,其中一个组件的data一旦发生修改,则其他重用的组件中的data也会被一并修改。
如果data是一个返回对象的函数,每次重用组件时返回的都是一个新对象,引用地址不同,便不会出现上面问题
8,什么是 mixin ?
Mixin 使我们能够为 Vue 组件编写可插拔和可重用的功能。 如果你希望再多个组件之间重用一组组件选项,例
如生命周期 hook、 方法等,则可以将其编写为 mixin,并在组件中简单的引用它。然后将 mixin 的内容合并
到组件中。如果你要在 mixin 中定义生命周期 hook,那么它在执行时将优化于组件自已的 hook