Vue中数组变动监听

前端开发 作者: 2024-08-21 16:10:01
Vue中数组变动监听 Vue的通过数据劫持的方式实现数据的双向绑定,即使用Object.defineProperty()来实现对属性的劫持,但是Object.defineProperty()中的set

Vue中数组变动监听

var obj = { __x: 1 };
Object.defineProperty(obj,"x",{
    set: function(x){ console.log("watch"); this.__x = x; },get: function(){ return this.__x; }
});
obj.x = 11; // watch
console.log(obj.x); // 11
var obj = { __x: [1,2,3] };
Object.defineProperty(obj,get: function(){ return this.__x; }
});
obj.x[0] = 11;
console.log(obj.x); // [11,3]
obj.x = [1,3,4,5,6]; // watch
console.log(obj.x); // [1,6]
obj.x.push(7);
console.log(obj.x); // [1,6,7]
// 通过下标对每一个值进行劫持
var obj = { __x: [1,get: function(){ return this.__x; }
});
obj.x.forEach((v,i) => {
    Object.defineProperty(obj.x,i,{
        set:function(x) { console.log("watch"); v = x; },get: function(){ return v; }
    })
})
obj.x[0] = 11; // watch
console.log(obj.x); // [11,3]
<!DOCTYPE html>
<html>
<head>
    <title>Vue中数组变动监听</title>
</head>
<body>
    <div id="app"></div>
</body>
<script src="https://cdn.bootcss.com/vue/2.4.2/vue.js"></script>
<script type="text/javascript">
    var vm = new Vue({
        el: '#app',data: {
            msg: [1,3]
        },template:`
            <div>
                <div v-for="item in msg" :key="item">{{item}}</div>
                <button @click="subscript">subscript</button>
                <button @click="push">push</button>
            </div>
        `,methods:{
            subscript: function(){
                this.msg[0] = 11;
                console.log(this.msg); // [11,__ob__: Observer]
            },push: function(){
                this.msg.push(4,6);
                console.log(this.msg); // [1,__ob__: Observer]
            }
        }
    })
</script>
</html>
// dev/src/core/observer/array.js
/*
 * not type checking this file because flow doesn't play well with
 * dynamically accessing methods on Array prototype
 */

import { def } from '../util/index'

const arrayProto = Array.prototype
export const arrayMethods = Object.create(arrayProto)

const methodsToPatch = [
  'push','pop','shift','unshift','splice','sort','reverse'
]

/**
 * Intercept mutating methods and emit events
 */
methodsToPatch.forEach(function (method) {
  // cache original method
  const original = arrayProto[method]
  def(arrayMethods,method,function mutator (...args) {
    const result = original.apply(this,args)
    const ob = this.__ob__
    let inserted
    switch (method) {
      case 'push':
      case 'unshift':
        inserted = args
        break
      case 'splice':
        inserted = args.slice(2)
        break
    }
    if (inserted) ob.observeArray(inserted)
    // notify change
    ob.dep.notify()
    return result
  })
})

重赋值

var obj = { __x: [1,get: function(){ return this.__x; }
});

obj.x[0] = 11;
obj.x = obj.x; // watch
console.log(obj.x); // [11,3]

obj.x[0] = 111;
obj.x = [].concat(obj.x); // watch
console.log(obj.x); // [111,3]

obj.x[0] = 1111;
obj.x = obj.x.slice(); // watch
console.log(obj.x); // [1111,3]

obj.x[0] = 11111;
obj.x = obj.x.splice(0,obj.x.length); // watch
console.log(obj.x); // [11111,3]

Proxy

var target = [1,3];
var proxy = new Proxy(target,{
    set: function(target,key,value,receiver){ 
        console.log("watch");
        return Reflect.set(target,receiver);
    },get: function(target,receiver){ 
        return target[key];
    }
});
proxy[0] = 11; // watch
console.log(target); // [11,3]
https://github.com/WindrunnerMax/EveryDay
https://zhuanlan.zhihu.com/p/50547367
https://juejin.im/post/6844903699425263629
https://juejin.im/post/6844903597591773198
https://segmentfault.com/a/1190000015783546
https://cloud.tencent.com/developer/article/1607061
https://www.cnblogs.com/tugenhua0707/p/11754291.html
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Proxy
原创声明
本站部分文章基于互联网的整理,我们会把真正“有用/优质”的文章整理提供给各位开发者。本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
本文链接:http://www.jiecseo.com/news/show_66178.html
Vue中数组变动监听