
如果阅读有疑问的话,欢迎评论或私信!!
本人会很热心的阐述自己的想法!谢谢!!!
文章目录
- 响应式基础
- 声明响应式状态(属性)
- 响应式代理 vs 原始值
- 声明方法
- 深层响应性
- DOM 更新时机
- 有状态方法
 
 
响应式基础
在认识vue之前,就可能许多人听说vue的响应式系统的诱人之处。
声明响应式状态(属性)
在vue中,可以通过data选项声明一些带有响应式的数据。data选项中需要return出一个对象,包含你所要在该页面添加的所有响应式数据。Vue会在创建当前实例时对你返回的对象使用响应式系统包装。并且,这些数据可以在当前实例中使用this找到,并进行修改。例如:
<template><img :[orderSrc]="imgSrc" />
</template><script>
export default {data() {var imgSrc = "/src/components/icons/newImg.gif";var orderSrc = "src";return {imgSrc,orderSrc,};},mounted(){console.log(this.imgSrc) //控制台输出‘/src/components/icons/newImg.gif’}
};
在vue响应式系统中,vue会在首次创建实例时对data数据进行响应式包装,所以
如果你要响应式的数据,那么需要确保已经在data中声明。至于里面的值可以是null或undefined这些占位符。
data中命名规范:vue中,由于内置API使用了$作为前缀,并且也为内部属性保留了_前缀,所以我们在data中声明数据时,要避免使用这些前缀,防止与内置属性冲突。
响应式代理 vs 原始值
在vue3中,vue使用的是JavaScript中的Proxy代理来实现响应式的。我们先来看一段vue2中的代码:
<script>export default{data(){var obj = {id:1}return {obj}},mounted(){const newObj = {}this.obj = newObj;console.log(this.obj) //{__ob__: Observer}console.log(newObj)   //{__ob__: Observer}console.log(this.obj === newObj) //true}}
</script>
接下来再看一下vue3中的效果:
<script>export default{data(){var obj = {id:1}return {obj}},mounted(){const newObj = {}this.obj = newObj;console.log(this.obj) //Proxy {}console.log(newObj)   //{}console.log(this.obj === newObj) //false}}
</script>
vue3中与vue2不同的是:在vue2中,newObj是响应式数据。而在vue3中,该数据在mouted中定义的newObj就不再是响应式数据。所以,请确保在其他地方使用this访问响应式状态
声明方法
在vue中,所有的方法都应该生声明在methods对象中,因为只有在methods对象中的this才会指向当前组件实例。所以,为了我们的this可以正常指向,所有的方法都应该声明在methods对象中。而且不应该在methods对象中使用ES6中的箭头函数!关于this的更多信息可以点击该链接查询。请注意,这里methods与data和mounted不同的是,methods是一个对象,而不是一个方法!
我们先来看一下正常的this里面包括什么:
<script>
export default {data() {var objAttr = {id: 123,class: "a",};return {objAttr};},methods:{init(){console.log(this)  //Proxy {init: ƒ, …}console.log(this.objAttr) //Proxy {id: 123, class: 'a'}console.log(this.objAttr.id)  //123}},mounted(){this.init();}
};
</script>接下来试一下在箭头函数中的this指向是什么:
<script>
export default {data() {var objAttr = {id: 123,class: "a",};return {objAttr};},methods:{init:()=>{console.log(this)  //undefined}},mounted(){this.init();}
};
</script>
所以尽量不要在methods中使用箭头函数!
深层响应性
vue中的响应式是进行深度处理过的,所以不管某个属性位于哪个对象,只要在data中进行声明,都可以被响应式处理。
DOM 更新时机
在学习这一节时,我们需要知道JavaScript中的异步处理机制以及ES7中的async语法之后,再来深入的理解。这里简单的说一下,JavaScript中异步有事件循环和任务队列,事件循环通常称为宏任务,任务队列通常称为微任务。我们使用setTimeout来解释这两个名词。来看下面这个代码:
setTimeout1(setTimeout2();    
,1000)setTimeout3(setTimeout4();    
,1000)
这里setTimeout1和setTimeout3位于事件循环中,而setTimeout2是和1处在同一个任务队列中,3和4处在同一个任务队列中。
如果可以理解上面这个概念的话,就可以继续学习vue中的DOM更新时机了!
vue中会把每次更新时机设置为一个事件循环,所以我们在需要等待DOM更新之后再进行操作的时候,可以使用vue中的nextTick函数,它会等待当前事件循环结束之后再执行接下来的任务。例如vue官方文档这串代码:
import { nextTick } from 'vue'export default {methods: {async increment() {this.count++await nextTick() // await中文指等待,也就是在上面事件循环结束之后再执行nextTick// 现在 DOM 已经更新了}}
}
有状态方法
有时候我们想要创建一个动态的方法多次复用,但是同时我们vue组件也需要被重用。这个时候就会引起一些问题:我们创建的这个方法内部是有一个自己的状态,比如自己的属性,自己的方法名。如果这些被重用,那么在执行代码的时候会产生不同结果。
比如这个方法中有一个名为timer的定时器,那么我们在进行复用的时候这个timer可能会有多个,之后我们再想销毁timer时,我们不知道哪一个需要被销毁。
vue官方文档中也为我们提供了一种解决方法:在created函数,也就是实例创建的时候将有状态的方法复制在自己的实例中,并且在实例销毁时(unmounted)删除该方法。