Vue劫持data

  • window上生成Vue

在用Rollup搭建开发环境时,用了format:"umd",的打包模式。
umd的打包模式会在window上添加Vue节点。
例如:在src/index.js中

export default function Vue() {
  console.log('Vue节点');
}

 rollup打完包后在html页面中引入生成的vue.js
然后打印Vue

<body>
    <div id="Vue">首页</div>
    <script src="dist/vue.js"></script>
    <script>
        // umd 打包模式会给window添加Vue
        console.log(Vue);
    </script>
</body>

 页面结果为

  • 操作

1.在页面配置Vue

new Vue({
    el: '#app', // el 挂载元素的位置,也叫编译模版
    data: {
    }
})

2.在js里拿到用户的配置项

export default function Vue(options) {
  console.log(options); // options为用户配置项
}

3.设置初始化方法,新建init.js

export function initMixin(Vue) {
  Vue.prototype._init = function (options) {  
    console.log(options);
  }
}

4.在index.js中注入调用

import { initMixin } from "./init";

function Vue(options) {
  // 初始化
  this._init (options) // _init 初始化方法 使用前先放到Vue原型链上
}
// 初始化,在init.js文件中给Vue原型链添加_init初始化方法
initMixin(Vue)

export default Vue

5.初始化data,新建initData.js

export function initData(vm) {
  let data = vm.$options.data
  data = typeof data === "function"?data.call(vm):data; // 注意 通过call指向vue的实例
  // 对数据进行劫持
  
} 

6.劫持data

import { observe } from "./observe/index";
export function initData(vm) {
  let data = vm.$options.data
  
  // 在vm上添加一个属性 _data
  data = vm._data =  typeof data === "function"?data.call(vm):data; // 注意 通过call指向vue的实例
  // 对数据进行劫持
  // data 有两种类型对象和数组 {a:{b:1}, list:[]}
  observe(data)

} 

判断data是对象还是数组,然后通过创建一个类来劫持对象data

  • 劫持对象
  1. 劫持对象用Object.defineProerty,有个缺点,只能对对象中对一个属性进行劫持
  2. 遍历data进行劫持
  3. 嵌套对data 用递归 进行深度劫持
export function observe(data) {
  console.log(data);
  // 1.判断类型是否是对象
  if (typeof data != 'object' || data == null) {
    return data;
  }
  // 1. 对象,通过一个类来劫持对象data
  return new Observer(data) 
}

// 用来劫持对象的类
class Observer{
  constructor (value){ // constructor 数据观测
    this.walk(value) // 遍历
  }
  walk(data){
    let keys = Object.keys(data) // 获取对象
    for (let i = 0; i < keys.length; i++) {
      // 在这个循环里对每个属性进行劫持
      let key = keys[i];  // 属性
      let value = data[key] // 值
      defineReactive(data, key, value)
    }
  }
}

function defineReactive(data, key, value) { //{a:{b:1}}
  observe(value) // 深度代理,深度劫持
  // 对对象中对属性进行劫持
  Object.defineProperty(data,key,{
    get(){ // 使用获取
      console.log('获取时触发');
      return value
    },
    set(newValue){ // 修改的时候
      console.log('设置时触发');
      if(newValue == value) return ;
      value = newValue
    }
  })
}

// {}
  • 劫持数组
    方法:函数劫持,重写数组方法,也就是劫持数组方法
// 重写数组
// 1. 获取原来的数组方法
let oldArrayProtoMethods = Array.prototype
// 2. 继承
export let ArrayMethods = Object.create(oldArrayProtoMethods) // 创建一个对象
// 劫持
let methods = [
  "push",
  "pop",
  "unshift",
  "shift",
  "splice"
]
methods.forEach(item => {
  ArrayMethods[item] = function (...args) {  
    console.log('劫持数组');
    let result = oldArrayProtoMethods[item].apply(this, args) // this执行当前的数组 {list: []}
    return result
  }
})

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值