十四、Vue数据监测原理————温开水的复习笔记

本来写了很多,还有很多图解,可就按了一次撤销后就全没了(╬◣д◢),自己在写的过程中已经慢慢构建了体系,也就不想再重写了,想深入理解就看看下面这篇吧。回头再写个Vue深入源码系列叭。

图解 Vue 响应式原理 - 知乎 (zhihu.com)https://zhuanlan.zhihu.com/p/168768245

一、前言——问题引出

当按如下代码修改时并不会在页面自动修改显示,但数据的的确确是被修改了的。

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8" />
		<title>列表过滤</title>
		<script type="text/javascript" src="../vuejs/vue.js"></script>
	</head>
	<body>
		<!-- 准备好一个容器-->
		<div id="root">
			<h2>人员列表</h2>
            <button @click="updataMei">更新马冬梅</button>
            <input type="text" placeholder="请输入姓名" v-model="keyWord"></input>
            <ul>
                <li v-for="(p, index) in Persons" :key="p.id">{{p.name}}-{{p.age}}-{{p.sex}}</li>
            </ul>
		</div>

		<script type="text/javascript">
			Vue.config.productionTip = false
			new Vue({
				el:'#root',
				data:{
					persons:[
						{id:'001',name:'马冬梅',age:19,sex:'女'},
						{id:'002',name:'周冬雨',age:20,sex:'女'},
						{id:'003',name:'周杰伦',age:21,sex:'男'},
						{id:'004',name:'温兆伦',age:22,sex:'男'}
					]
				},
                methods: {
                    updataMei(){
                        this.persons[0] = {id:'001',name:'马老师',age:55,sex:'男'};
                        //结果时Vue监测不到
                    }
                },
			})
		</script>
</html>

二、问题解决

(一)Vue如何实现"追踪数据变化"

        响应式的实现......

(二)Vue监测变化的注意事项

        # 对于对象......

        # 对于数组......

        # 规避方法(使用特定方法触发响应式)

                Vue.set(target,propertyName/index,value)

                vm.$set(target,propertyName/index,value)

深入响应式原理 — Vue.js (vuejs.org)https://cn.vuejs.org/v2/guide/reactivity.html

三、文字总结

vue.js是通过数据劫持的方式实现数据的双向绑定的,其中过程如下:

当把一个JavaScript对象传给Vue实例的data选项时,Vue会遍历此对象的所有属性并使用 Object.defineProperty(),把这些属性全部转化为 getter/setter 。每个组件实例都有相应的 watcher 实例对象,它会在组件渲染的时候把属性记录为依赖,之后当依赖的setter被调用时,会通知watcher重新计算,从而致使它关联的组件得以更新。因此,每当数据变化的时候会引起视图的变化,更新view。

因为Vue在初始化实例时会对属性进行 getter/setter 转化,这样,被转化的属性就是 响应式的,而只有在data中声明的属性会执行这个过程。所以,后续通过JavaScript传过来的对象属性因为没有在 data 中声明,并且通过这种方式传对象并不会执行这个转化响应式过程,因此这些属性全都不是响应式的。

也是因为这个原因,现在的 Vue.js 无法监听到对象属性的添加和删除,也无法检测到数组的变动。

Vue监视数据的原理:
    1. vue会监视data中所有层次的数据。

    2. 如何监测对象中的数据?
                    通过setter实现监视,且要在new Vue时就传入要监测的数据。
                        (1).对象中后追加的属性,Vue默认不做响应式处理
                        (2).如需给后添加的属性做响应式,请使用如下API:
                                        Vue.set(target,propertyName/index,value) 或 
                                        vm.$set(target,propertyName/index,value)

    3. 如何监测数组中的数据?
                        通过包裹数组更新元素的方法实现,本质就是做了两件事:
                            (1).调用原生对应的方法对数组进行更新。
                            (2).重新解析模板,进而更新页面。

    4.在Vue修改数组中的某个元素一定要用如下方法:
                1.使用这些API:push()、pop()、shift()、unshift()、splice()、sort()、reverse()
                2.Vue.set() 或 vm.$set()
    
    特别注意:Vue.set() 和 vm.$set() 不能给vm 或 vm的根数据对象 添加属性!!!


四、Vue响应式简单实现

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>模拟一个数据监测</title>
</head>
<body>
    <div>
        <h2 id="h2"></h2>
    </div>
    <script>
        const data = {
            name:'温开水',
            age:21
        };
// --------------------------------------------方法一------------------------------------------------//

        // 可以用于创建一个监视的实例对象,用于监视data中的属性变化。数据代理
        function Observer(obj){
            // 汇总对象中的所有属性形成一个[数组]
            const keys = Object.keys(obj);
            console.log(keys);
            // 遍历
            keys.forEach((k)=>{
                Object.defineProperty(this,k,{
                    get(){
                        return obj[k];
                    },
                    set(val){
                        console.log(`${k}被修改了,马上进行解析模板,生成虚拟DOM,diff算法比较...`);
                        obj[k] = val;
                    }
                })
            })
        }
        // 创建一个监视的实例对象,用于监视data中的属性变化
        const obs = new Observer(data);

//---------------------------------------方法二----------------------------------------------------//
//其实和方法一一样,不过是我自己思考出来的,好理解一点
        const data2 = {};
        Object.defineProperty(data2,'age',{
            get(){
                return data.age;
            },
            set(val){
                console.log(`age被修改了,马上进行解析模板,生成虚拟DOM,diff算法比较...`);
                data.age = val;
            }
        })
    </script>
</body>
</html>

一句话:创建一个新的对象data2,让data2对象数据(属性)可以获取(get)与修改(set)原对象data中的数据(属性)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值