vue的响应式-2,和响应式原理

vue的响应式-2

  • 除了未被声明过和未被渲染的数据外,还有什么数据更改后不会渲染页面?

    1. 利用索引直接设置一个数组项时:

    <!-- 即使向数组中添加了第4项,数组仍然显示3项 -->
    <!-- 咳咳,一家三口,有第4个人也不能摆出来给大家看呀~ -->
    <div id="app">{{ dengFamily }}</div>
    
    const vm = new Vue({
      el: '#app'
      data: {
        dengFamily: ['邓哥', '小刘', '王小宝']
      }
    })
    vm.dengFamily[3] = '铁锤妹妹'; // 不是响应式的
    

    2. 修改数组的长度时:

    <!-- 更改了数组长度后,数组仍然显示1项 -->
    <div id="app">{{ dengWife }}</div>
    
    const vm = new Vue({
      el: '#app'
      data: {
        dengWife: ['小刘']
      }
    })
    vm.dengWife.length = 0; // 不是响应式的
    

    3. 添加或删除对象:

    <!-- 身高还是那个身高,媳妇也只有一个,不要痴心妄想 -->
    <div id="app">{{ deng }}</div>
    
    const vm = new Vue({
      el: '#app'
      data: {
        deng: {
          wife: '小刘',
          son: '王小宝',
          weight: '100kg',
          height: '140cm',
          age: 60
        }
      }
    })
    vm.deng.secondWife = '铁锤妹妹'; // 不是响应式的
    delete vm.deng.height; // 不是响应式的
    
  • 问:要如何响应式的更新数组和对象?

    更改数组:
    1. 利用数组变异方法:push、pop、shift、unshift、splice、sort、reverse
    2. 利用vm.$set/Vue.set实例方法
    3. 利用vm.$set或Vue.set删除数组中的某一项

    vm.$set是Vue.set的别名
    使用方法:Vue.set(object, propertyName, value),也就是这个意思:Vue.set(要改谁,改它的什么,改成啥)

    vm.$delete是Vue.delete的别名
    使用方法:Vue.delete(object, target),也就是这个意思:Vue.delete(要删除谁的值,删除哪个)

    <!-- 从此,一家三口过上了愉快生活 -->
    <div id="app">{{ list }}</div>
    
    const vm = new Vue({
      el: '#app'
      data: {
        dengFamily: ['邓哥', '小刘', '王小宝']
      }
    })
    // 使用数组变异方法
    vm.dengFamily.push('铁锤妹妹');
    // 使用vm.$set
    vm.$set(vm.dengFamily, 3, '铁锤妹妹');
    
    
    <!-- 邓哥的媳妇多了起来~ -->
    <div id="app">{{ list }}</div>
    
    const vm = new Vue({
      el: '#app'
      data: {
        dengWife: ['小刘']
      }
    })
    // 更改长度时,可以用数组的splice方法
    vm.dengWife.splice(100); 
    

    更改对象:
    1. 添加利用vm.$set/Vue.set实例方法
    2. 删除利用vm.$delete/Vue.delete方法

    <div id="app">{{ deng }}</div>
    
    const vm = new Vue({
      el: '#app'
      data: {
        deng: {
          wife: '小刘',
          son: '王小宝',
          weight: '100kg',
          height: '140cm',
          age: 60
        }
      }
    })
    // 添加
    vm.$set(vm.deng, 'secondWife', '铁锤妹妹');
    // 删除
    vm.$delete(vm.deng, 'height')
    
  • 总结:

    更改数组用变异方法,就够了
    更改对象就用vm.$set和vm.$delete

剖析Vue响应式原理

  
const data = {
  name: 'shanshan',
  age: 18,
  shan: {
    name: 'shanshan',
    age: 18,
    obj: {}
  },
  arr: [1, 2, 3]
}

const arrayProto = Array.prototype;
const arrayMethods = Object.create(arrayProto);
['push', 'pop', 'shift', 'unshift' ,'sort', 'splice', 'reverse'].forEach(method => {
  arrayMethods[method] = function () {
    arrayProto[method].call(this, ...arguments);
    render();
  }
})

function defineReactive (data, key, value) {
  observer(value);
  Object.defineProperty(data, key, {
    get () {
      return value;
    },
    set (newVal) {
      if(value === newVal) {
        return;
      }
      value = newVal;
      render();
    }
  })
}

function observer (data) {
  if(Array.isArray(data)) {
    data.__proto__ = arrayMethods;
    return;
  }

  if(typeof data === 'object') {
    for(let key in data) {
      defineReactive(data, key, data[key])
    }
  }
}

function render () {
  console.log('页面渲染啦');
}

function $set (data, key, value) {
  if(Array.isArray(data)) {
    data.splice(key, 1, value);
    return value;
  }
  defineReactive(data, key, value);
  render();
  return value;
}

function $delete(data, key) {
  if(Array.isArray(data)) {
    data.splice(key, 1);
    return;
  }
  delete data[key];
  render();
}

observer(data);

利用Object.defineProperty实现响应式的劣势

  1. 天生就需要进行递归
  2. 监听不到数组不存在的索引的改变
  3. 监听不到数组长度的改变
  4. 监听不到对象的增删
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

努力爬坑的小崔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值