Vue中检测数据原理和Vue_set()方法

vue监测数据改变的原理

  • vue监听数据的流程为:数据修改时vm.data = data.然后调用data里边的set方法。set方法重新进行DOM(页面)重新遍历。新的虚拟DOM和旧的虚拟DOM进行对比,数据才被修改。(下面写这么多,只有这句话最有用)

  • 以下是模拟vue监视数据

html 复制代码
<body></body>
<script>
    let data = {
        name: '安斯卡',
        address: '十大科技'
    }
    /*当数据被修改时,Observer是构造函数故调用需要需要
    vue创建一个监视的实例对象,用于监听data中的属性变化.Observer有观察者的意思.*/
    const obs = new Observer(data)
    console.log(obs)
    //准备一个vm的实例对象
    let vm = {}
    //将监听的data放入_data中
    vm._data = data = obs
    //obj可以是data对象,但不会改变原来data的数据
    function Observer(obj){
        //汇总所有对象的属性形成一个数组
        const keys = Object.keys(obj)
        //遍历,k为属性名
        keys.forEach((k)=>{
            //选取this,this指代的是Observer的对象,而不是data的对象。
            Object.defineProperties(this,k,{
                get(){
                    //obj[k]的意思是将obj对象属性名为k进行返回
                    return obj[k]
                },
                set(val){
                    //将obj对象的属性名k进行修改
                    obj[k] = val
                    //`${k}`为name
                    console.log(`${k}被修改了,所以去解析模板,生成虚拟DOM`);
                }
            })
        })
    }
</script>
  • vue可以进行多层监视对象,生成get和set方法。

html 复制代码
//data的属性有多少层对象,vue就对应生成多少个set方法。用于监视数据修改。模拟案例无法实现
let data = {
        name: '安斯卡',
        address: {
            sex: {
            phone: '123'
            }
        }
    }

Vue_set()方法

  • 不可以用vm直接添加信息。

  • 当data中没有定义属性age,在不动用源码的情况下。在控制台使用如下

html 复制代码
Vue.set(vm._data.age,'sex','男'),或者vm.$set(vm._data.age,'set','男')
  • 上边的代码不够严谨,可以直接用vm访问data的属性。

html 复制代码
Vue.set(vm.age,'sex','男'),或者vm.$set(vm.age,'set','男')
  • 设置按下按钮后才在data中的对象添加(属性值、属性名)或对象,不能直接在vm和_data添加

html 复制代码
<template>
  <div class="hello">
    <!-- data中的对象未定义属性,按下按钮后才在data中的对象添加(属性值、属性名)或对象 -->
    <button @click="addshu">按下按钮添加属性</button>
    <p v-if="name.sex">性别:{{ name.sex }}</p>
  </div>
</template>
​
<script>
export default {
  data () {
    return {
      name: {
        age: '12',
        username: '',
        arr: {
          minage: '55',
          maxage: '44'
        },
      }
    }
  },
  methods: {
    addshu () {
      // 这里的this是vm, this.$set(选取添加的对象, 添加属性名, 添加属性值)
      this.$set(this.name, 'sex', '男')
    }
  }
}
</script>
​
<style scoped>
​
</style>
​
  • 在array2: ['开车', '放歌', '开香槟']中,Vue无法给索引值为0、1、2设置get和set的方法,但Vue可以给array2[0].name设置get和set的方法。

  • 解决方案。如:this.$set(this.name.array2.push('拉拉'))。用下列的方法,Vue会调用数组的push,之后进行数据代理。改变DOM页面

    1、给数组最后的位置添加一个元素用,push

    2、给数组开头的位置添加一个元素用,unshift

    3、删除数组最后一个元素用,pop

    4、删除数组第一个元素用,shift

    5、替换或修改数组中的某个元素用,splice

    6、对数组从小到大排序用sort

    7、反转数组用,reverse

  • 过滤数组用,filter。但filter过滤后生成新的数组不归Vue所管理,也就是Vue不会进行数据代理

html 复制代码
<template>
  <div class="hello">
    <ul>
        <!-- 对包含在name对象下的array进行遍历,没有定义id。可以用index作为索引 -->
    <li v-for="(arrays,index) in name.array" :key="index">
      {{ arrays.nameday }}--{{ arrays.ageday }}--{{ arrays.sexday }}
    </li>
        <!-- 遍历array2的数组 -->
    <li v-for="(arr2,index) in name.array2" :key="index">{{ arr2 }}</li>
        <!-- 给数组添加数据 -->
    <button @click="fixNum">给数组添加数据</button>
    <p>{{ name.array2 }}</p>
    </ul>
  </div>
</template>
​
<script>
export default {
  data () {
    return {
      name: {
        array: [
          {nameday: '晓东', ageday: '23', sexday: '男'},
          {nameday: '小志', ageday: '53', sexday: '男'},
          {nameday: '小明', ageday: '63', sexday: '男'}
        ],
        array2: ['开车', '放歌', '开香槟']
      }
    }
  },
  methods: {
    fixNum () {
      this.$set(this.name.array2.push('拉拉'))
    }
    // fixNum () {
    //   array2.splice(选取要修改数组的索引, 修改的个数, 修改后的元素))
    //   this.$set(this.name.array2.splice(0, 1, '拉拉'))
    // },
  }
}
</script>
​
<style scoped>
​
</style>
​
相关推荐
90后小陈老师1 小时前
3D个人简历网站 5.天空、鸟、飞机
前端·javascript·3d
chenbin___1 小时前
react native text 显示 三行 超出部分 中间使用省略号
javascript·react native·react.js
漫路在线4 小时前
JS逆向-某易云音乐下载器
开发语言·javascript·爬虫·python
不爱吃糖的程序媛4 小时前
浅谈前端架构设计与工程化
前端·前端架构设计
BillKu6 小时前
Vue3 Element Plus 对话框加载实现
javascript·vue.js·elementui
郝YH是人间理想6 小时前
系统架构设计师案例分析题——web篇
前端·软件工程
Evaporator Core6 小时前
深入探索:Core Web Vitals 进阶优化与新兴指标
前端·windows
初遇你时动了情7 小时前
html js 原生实现web组件、web公共组件、template模版插槽
前端·javascript·html
QQ2740287567 小时前
Soundness Gitpod 部署教程
linux·运维·服务器·前端·chrome·web3
前端小崔7 小时前
从零开始学习three.js(18):一文详解three.js中的着色器Shader
前端·javascript·学习·3d·webgl·数据可视化·着色器