对Vue 数据响应式的理解

简介: 对Vue 数据响应式的理解

对Vue 数据响应式的理解


一、数据响应式

当你把一个普通的 JavaScript 对象传入 Vue 实例作为 data 选项,Vue 将遍历此对象所有的 property,并使用 Object.defineProperty 把这些 property 全部转为 getter/setter

网络异常,图片无法展示
|
总结一下:

  1. 任何一个 Vue Component 都有一个与之对应的 Watcher 实例。
  2. Vue 的 data 上的属性会被添加 getter 和 setter 属性。
  3. 当 Vue Component render 函数被执行的时候, data 上会被 触碰(touch), 即被, getter 方法会被调用, 此时 Vue 会去记录此 Vue component 所依赖的所有 data。(这一过程被称为依赖收集)
  4. data 被改动时(主要是用户操作), 即被, setter 方法会被调用, 此时 Vue 会去通知所有依赖于此 data 的组件去调用他们的 render 函数进行更新

Object.defineProperty()

监听

Vue实现数据响应式主要使用JS的Object.defineProperty(),该API可以设置属性的getter\setter。从而实现监听数据。

let obj = { name: "feng" };
    let _name = obj.name;
    Object.defineProperty(obj, "name", {
        get() {
            console.log("您获取了name属性值");
            return _name;
        },
        set(value) {
            console.log("您设置了name属性值");
            _name = value;
        },
    });

网络异常,图片无法展示
|

使用Object.defineProperty()对name进行劫持后,之后对name属性的读写操作都是走getter或setter。那么我们就可以在getter和setter中通知UI,UI从而进行更新。

代理

Object.defineProperty()还可以实现代理功能。当我们使用data数据时,都是this.name的形式调用的。此时就产生疑问了?this指的是Vue实例,怎么就能读写我们定义的data呢?答案就是Vue代理了data。

let obj = { name: "feng" };
function proxy(data) {
//监听
let _name = data.name;
Object.defineProperty(data, "name", {
  get() {
    console.log("您获取了name属性值");
    return _name;
  },
  set(value) {
    console.log("您设置了name属性值");
    _name = value;
  },
});
//代理
const obj = {};
Object.defineProperty(obj, "name", {
  get() {
    return data.name;
  },
  set(value) {
    data.name = value;
  },
});
return obj;
}
//此处可看成const vm = new Vue(options)
let vueInstance = proxy(obj);
//此时就可以通过vue实例去访问name属性
console.log(vueInstance.name);

this.$set()和Vue.set()

通过上述内容,可以发现想要对数据进行劫持,那么数据一开始就要有属性。换句话说,对于数据后添加的属性,Vue是监听不到的。那么就无法实现数据响应式、更新UI了。因此Vue提供了两个API应对这种情况。

  • this.$set()
  • Vue.set()

这两个API其实是一样的,都是指向同一个函数即this.$set === Vue.set表达式的值是true。

  1. 参数一:要修改的对象
  2. 参数二:修改的属性
  3. 参数三:属性值
{
    data(){
        return {
            obj:{
                name:'feng'
            }
        }
    },
    methods:{
        setAge(){
            //设置新增的属性
            this.$set(this.obj,'age',18)
        }
    }
}

对于对象

Vue 无法检测 property 的添加或移除。由于 Vue 会在初始化实例时对 property 执行 getter/setter 转化,所以 property 必须在 data 对象上存在才能让 Vue 将它转换为响应式的。例如:

var vm = new Vue({
  data:{
    a:1
  }
})
// `vm.a` 是响应式的
vm.b = 2
// `vm.b` 是非响应式的

对于已经创建的实例,Vue 不允许动态添加根级别的响应式 property。但是,可以使用 Vue.set(object, propertyName, value) 方法向嵌套对象添加响应式 property。例如,对于:

Vue.set(vm.someObject, 'b', 2)

您还可以使用 vm.$set 实例方法,这也是全局 Vue.set 方法的别名:

this.$set(this.someObject,'b',2)

有时你可能需要为已有对象赋值多个新 property,比如使用 Object.assign()_.extend()。但是,这样添加到对象上的新 property 不会触发更新。在这种情况下,你应该用原对象与要混合进去的对象的 property 一起创建一个新的对象。

// 代替 `Object.assign(this.someObject, { a: 1, b: 2 })`
this.someObject = Object.assign({}, this.someObject, { a: 1, b: 2 })

对于数组

Vue 不能检测以下数组的变动:

  1. 当你利用索引直接设置一个数组项时,例如:vm.items[indexOfItem] = newValue
  2. 当你修改数组的长度时,例如:vm.items.length = newLength

举个例子:

var vm = new Vue({
  data: {
    items: ['a', 'b', 'c']
  }
})
vm.items[1] = 'x' // 不是响应性的
vm.items.length = 2 // 不是响应性的

为了解决第一类问题,以下两种方式都可以实现和 vm.items[indexOfItem] = newValue 相同的效果,同时也将在响应式系统内触发状态更新:

// Vue.set
Vue.set(vm.items, indexOfItem, newValue)
// Array.prototype.splice
vm.items.splice(indexOfItem, 1, newValue)

你也可以使用 vm.$set 实例方法,该方法是全局方法 Vue.set 的一个别名:

vm.$set(vm.items, indexOfItem, newValue)

为了解决第二类问题,你可以使用 splice

vm.items.splice(newLength)

Vue中数组的变异方法

Vue、被侦听的数组的变更方法进行了包裹,所以它们也将会触发视图更新。

这些被包裹过的方法包括:

  • push()
  • pop()
  • shift()
  • unshift()
  • splice()
  • sort()
  • reverse()

本文参考摘录了:

  1. Vue 响应式原理白话版
  2. vue文档
相关文章
|
15天前
|
移动开发 JavaScript API
Vue Router 核心原理
Vue Router 是 Vue.js 的官方路由管理器,用于实现单页面应用(SPA)的路由功能。其核心原理包括路由配置、监听浏览器事件和组件渲染等。通过定义路径与组件的映射关系,Vue Router 将用户访问的路径与对应的组件关联,支持哈希和历史模式监听 URL 变化,确保页面导航时正确渲染组件。
|
19天前
|
监控 JavaScript 前端开发
ry-vue-flowable-xg:震撼来袭!这款基于 Vue 和 Flowable 的企业级工程项目管理项目,你绝不能错过
基于 Vue 和 Flowable 的企业级工程项目管理平台,免费开源且高度定制化。它覆盖投标管理、进度控制、财务核算等全流程需求,提供流程设计、部署、监控和任务管理等功能,适用于企业办公、生产制造、金融服务等多个场景,助力企业提升效率与竞争力。
77 12
|
15天前
|
JavaScript 前端开发 开发者
Vue中的class和style绑定
在 Vue 中,class 和 style 绑定是基于数据驱动视图的强大功能。通过 class 绑定,可以动态更新元素的 class 属性,支持对象和数组语法,适用于普通元素和组件。style 绑定则允许以对象或数组形式动态设置内联样式,Vue 会根据数据变化自动更新 DOM。
|
15天前
|
JavaScript 前端开发 数据安全/隐私保护
Vue Router 简介
Vue Router 是 Vue.js 官方的路由管理库,用于构建单页面应用(SPA)。它将不同页面映射到对应组件,支持嵌套路由、路由参数和导航守卫等功能,简化复杂前端应用的开发。主要特性包括路由映射、嵌套路由、路由参数、导航守卫和路由懒加载,提升性能和开发效率。安装命令:`npm install vue-router`。
|
1月前
|
JavaScript 安全 API
iframe嵌入页面实现免登录思路(以vue为例)
通过上述步骤,可以在Vue.js项目中通过 `iframe`实现不同应用间的免登录功能。利用Token传递和消息传递机制,可以确保安全、高效地在主应用和子应用间共享登录状态。这种方法在实际项目中具有广泛的应用前景,能够显著提升用户体验。
96 8
|
JavaScript 前端开发
模拟Vue数据的双向绑定
Vue的数据双向绑定功能一直为人称道, Vue数据的双向数据绑定主要依赖了Object.defineProperty,这里尝试用最简单的代码, 实现数据的双向绑定Demo MVVM ViewModel基本实现原理 Gi...
954 0
|
2月前
|
JavaScript
vue使用iconfont图标
vue使用iconfont图标
161 1
|
1月前
|
存储 设计模式 JavaScript
Vue 组件化开发:构建高质量应用的核心
本文深入探讨了 Vue.js 组件化开发的核心概念与最佳实践。
84 1
|
3月前
|
JavaScript 前端开发 开发者
vue 数据驱动视图
总之,Vue 数据驱动视图是一种先进的理念和技术,它为前端开发带来了巨大的便利和优势。通过理解和应用这一特性,开发者能够构建出更加动态、高效、用户体验良好的前端应用。在不断发展的前端领域中,数据驱动视图将继续发挥重要作用,推动着应用界面的不断创新和进化。
114 58
|
2月前
|
JavaScript 关系型数据库 MySQL
基于VUE的校园二手交易平台系统设计与实现毕业设计论文模板
基于Vue的校园二手交易平台是一款专为校园用户设计的在线交易系统,提供简洁高效、安全可靠的二手商品买卖环境。平台利用Vue框架的响应式数据绑定和组件化特性,实现用户友好的界面,方便商品浏览、发布与管理。该系统采用Node.js、MySQL及B/S架构,确保稳定性和多功能模块设计,涵盖管理员和用户功能模块,促进物品循环使用,降低开销,提升环保意识,助力绿色校园文化建设。

热门文章

最新文章

相关实验场景

更多