Vue笔记-Day04-01(数据监控)

4.1 Vue监视数据改变的原理:

Vue监视数据的过程:
1.加工data,使之成为响应式的对象,即如果data的数据被读取或修改,就发出通知,实现对对象中属性的监视;
2.vm._data = data;

Vue如何监测对象中数据的变化(加工data===》 data 变成 Observer)
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>模拟一个数据监控</title>
</head>
<body>
    <div class="root">

    </div>

    <script type="text/javascript">

        let data = {
            name:'Sam',
            age:30,
        }
		//创建一个监视的实例对象,用于监视data中属性的变化
        const obs = new Observer(data)
        console.log(obs)

        let vm = {}
        vm._data = data = obs
		
		//Observer的构造函数,获取的参数是一个对象
        function Observer(obj){
        //	汇总对象中所有属性,形成一个数组
            const keys = Object.keys(obj);
		//遍历
            keys.forEach((k)=>{
            				//this是他的实例对象 Observer,让每一个属性都有自己的getter,setter方法
                Object.defineProperty(this,k,{
                    get(){
                        return obj[k]
                    },
                    set(v) {
                    //利用set检测,当属性改变时调用set方法
                    //vue在set触发时,去重新解析模板,生成虚拟dom
                        console.log(`${k} is changed`)
                        obj[k] = v
                    }
                })
            })
        }

    </script>

</body>
</html>

Vue Set的使用

向响应式对象中添加一个 property,并确保这个新 property 同样是响应式的,且触发视图更新。它必须用于向响应式对象上添加新 property,因为 Vue 无法探测普通的新增 property (比如 this.myObject.newProperty = ‘hi’)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title> Vue Set的使用</title>
    <script type="text/javascript" src="../js/vue.js"></script>
    <style>
        li{
            font-size: 24px;
            line-height: 50px;
        }
    </style>
</head>
<body>

    <div id="root">
        <ul>
            <li>name:{{name}}</li>
            <li>age:{{age}}</li>
            <li>gender:{{gender}}</li>
        </ul>
    </div>

<script type="text/javascript">
    Vue.config.productionTip = false;

    const vm = new Vue({
        el:'#root',
        data:{
            name:'aq',
            age:24,
        }
    })

</script>
</body>
</html>

用Vue.set给data添加一个gender属性,value为男;

参数:

{Object | Array} target
{string | number} propertyName/index
{any} value
返回值:设置的值。

执行:
Vue.set(vm._data,‘gender’,‘男’)

结果:
vue.js:634 [Vue warn]: Avoid adding reactive properties to a Vue instance or its root $data at runtime - declare it upfront in the data option.

报错提示无法给Vue实例或data添加一个响应式的属性。

这就是Vue.set的局限性,也就是说Vue.set只能给data里的对象追加属性,不能给data本身追加属性。也即Vue.set的target不能是vm或vm._data;

修改:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title> Vue Set的使用</title>
    <script type="text/javascript" src="../js/vue.js"></script>
    <style>
        li{
            font-size: 24px;
            line-height: 50px;
        }
    </style>
</head>
<body>

    <div id="root">
        <ul>
            <li>name:{{student.name}}</li>
            <li>age:{{student.age}}</li>
            <li>gender:{{student.gender}}</li>
        </ul>
    </div>

<script type="text/javascript">
    Vue.config.productionTip = false;

    const vm = new Vue({
        el:'#root',
        data:{
            student:{
                name:'aq',
                age:24,
            },
        }
    })

</script>
</body>
</html>

执行:
Vue.set(vm.student,‘gender’,‘男’);

成功!

Vue如何监测数组的数据变化:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title> Vue Set的使用</title>
    <script type="text/javascript" src="../js/vue.js"></script>
    <style>
        li{
            font-size: 24px;
            line-height: 50px;
        }
    </style>
</head>
<body>

    <div id="root">
        <ul>
            <li>name:{{student.name}}</li>
            <li>age:{{student.age}}</li>
            <li>gender:{{student.gender}}</li>
        </ul>
        <br>
        <h2>friends</h2>
        <ul>
            <li v-for="f in student.friends">{{f.name}}--{{f.age}}</li>
        </ul>
        <br>
        <h2>hobbies</h2>
        <ul>
            <li v-for="h in student.hobby">{{h}}</li>
        </ul>
    </div>

<script type="text/javascript">
    Vue.config.productionTip = false;

    const vm = new Vue({
        el:'#root',
        data:{
            student:{
                name:'aq',
                age:24,
                friends:[
                    {name:'jimmy',age:25},
                    {name:'joy',age:30}
                ],
                hobby:[
                    'smoke','drink','eat'
                ]
            },


        }
    })

</script>
</body>
</html>

注:
Vue想要修改student的hobby,是通过包装Array的常用7个方法:push,pop,shift,unshift,splice,sort,reverse;
这7个方法能对数组进行增删改查,Vue通过包装这7个方法来检测数组是否发生改变和作出响应。

vm.student.hobby[0] = ‘抽烟’
‘抽烟’
vm.student.hobby.push(‘学习’)
4
vm.student.hobby.pop()
‘学习’
vm.student.hobby.shift()
‘抽烟’
vm.student.hobby.splice(0,1,‘打台球’)
[‘drink’]
vm.student.hobby.push(‘学习’)
3
//经过Vue包装后的push与Array的原型push并不相同
vm.student.hobby.push === Array.prototype.push
false

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>  Vue如何监测数组的数据变化</title>
    <script type="text/javascript" src="../js/vue.js"></script>
    <style>
        li{
            font-size: 24px;
            line-height: 50px;
        }
    </style>
</head>
<body>

    <div id="root">
        <button @click="ageAddOne">age+1</button><br><br>
        <button @click="addSex">Add Sex,default man</button><br><br>
        <button @click="addFriend">Add Friend in the head</button><br><br>
        <button @click="updataFriend">updata first Friend's name : ZhangSan</button><br><br>
        <button @click="addHobby">add a hobby</button><br><br>
        <button @click="updataHobby">updata the first hobby</button><br><br>

        <ul>
            <li>name:{{student.name}}</li>
            <li>age:{{student.age}}</li>
            <li>gender:{{student.gender}}</li>
        </ul>
        <br>
        <h2>friends</h2>
        <ul>
            <li v-for="f in student.friends">{{f.name}}--{{f.age}}</li>
        </ul>
        <br>
        <h2>hobbies</h2>
        <ul>
            <li v-for="h in student.hobby">{{h}}</li>
        </ul>
    </div>

<script type="text/javascript">
    Vue.config.productionTip = false;

    const vm = new Vue({
        el:'#root',
        data:{
            student:{
                name:'aq',
                age:24,
                friends:[
                    {name:'jimmy',age:25},
                    {name:'joy',age:30}
                ],
                hobby:[
                    'smoke','drink','eat'
                ]
            },
        },
        methods:{
            ageAddOne(){
                this.student.age++;
            },
            addSex(){
                // Vue.set(this.student,'gender','man')
                this.$set(this.student,'gender','man')
            },
            addFriend(){
                this.student.friends.unshift({name:'tom',age:40})
            },
            updataFriend(){
                // this.student.friends.splice(0,1,{name:'ZhangSan',age: 40})
                this.student.friends[0].name='ZhangSan'
            },
            addHobby(){
                this.student.hobby.push('learning')
            },
            updataHobby(){
                this.student.hobby.splice(2,1,'singing')
            }
        }

    })

</script>
</body>
</html>

数据监控总结:

1.Vue会监视data中所有层次的数据;
2.如何监视对象中的数据:
通过Setter实现监视,且要在new Vue时就传入要监测的数据。
(1)对象中后追加的属性,Vue默认不做响应式处理;
(2)如果需要给后追加的属性做响应式的处理,需要用到Vue.set API;

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

4.在Vue中修改数组的某个元素一定要用如下方法:
1.7个API: pop.push.shift.unshift.splice.sort.reverse;
2. Vue.set() 和 vm.$set

特别注意 Vue.set() 和 vm.$set 不能给vm 或 vm的根数据对象添加属性!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值