当前位置: 首页 > news >正文

Vue | Object.defineProperty()、数据代理、计算属性、监视属性

 

目录

一、Object.defineProperty()

二、简单的数据代理小例子

三、数据代理

四、计算属性(Computed)

五、监视属性(Computed) 


说到Object.defineProperty()这个方法,它是给大家可不要小瞧它,Vue底层很多地方都用到了它。比如:数据劫持、数据代理、计算属性等等。

一、Object.defineProperty()

     <script>
        let number = 18;
        let person = {
            name:'王仕丹'
        }
        Object.defineProperty(person,'age',{
            enumerable:true,//控制属性是否可以被枚举,默认为false
            writable:true,  //控制属性是否可以被修改,默认为false
            configurable:true,//控制属性是否可被删除,默认为false
            get(){
                console.log('有人读取age')
                return number
            },
            set(value){
                console.log('有人修改age')
                number = value
            }
        })
    </script>

Object.defineProperty()的第一个参数是给谁添加属性,第二个参数是添加什么属性,第三个参数是配置项,里面有enumerable、writable、configurable、getter、setter等。

工作原理就是当有人读取这个属性时,会把返回值作为属性值传出去,当有人修改这个属性时,会把修改的这个新值赋值给这个变量。

二、简单的数据代理小例子

   <script>
        Vue.config.productionTip = false
        let obj = {
            x:1
        }
        let obj2 = {
            y:2
        }
        Object.defineProperty(obj2,'x',{
            get(){
                return obj.x
            },
            set(value){
                obj.x = value
            }
        })
    </script>

 当有人读取obj2.x时,getter会把obj.x返回出去,当有人修改obj2.x时,setter会把新值赋值给obj.x。

三、数据代理

我们就浅说一下vue中的数据代理吧~

举个栗子:

<body>
    <div id="root">
        <h2>学校:{{school}}</h2>
        <h2>地址:{{address}}</h2>
    </div>
    <script>
        Vue.config.productionTip = false
        const vm = new Vue({
            el:'#root',
            data:{
                school:'阜阳师范大学',
                address:'颍州区'
            }
        })
    </script>
</body>

我们可以看到,我们通过vm可以访问到data中的school属性,也可以通过vm修改data中的school属性值,这是为什么呢?

其实它底层原理是Object.defineProperty()这个方法,我们先来看一下数据代理的原理图:

当我们创建vm这个实例对象时,Vue会把data中的数据原封不动的赋值给_data,并且data会有这样一个动作,就是往vm实例对象身上添加data对象中的所有属性,且每一个属性都会有自己的getter和setter。

当有人读取这个属性时,调用getter,getter读取data中的这个属性,并把data中的这个属性的属性值return出去,也就是作为返回值。

get(){
   return '我是你想要的data中的属性值'
}

当有人修改这个属性时,调用setter,setter会把你修改的新值在内部做一个赋值操作,也就是把原data中的属性值修改了,data中的数据修改了,当然页面也会重新渲染。

set(value){
    school = value
}

四、计算属性(Computed)

emmm……说到计算属性呢……我来想想要怎么来讲……

首先我们先来搞明白什么是计算属性吧~

定义:要用的属性data中不存在,要通过已有属性计算得来。

之前我们也说了,计算属性底层的原理也是借助了Object.defineProperty()这个方法提供的getter和setter,那么它这两个函数在什么时候执行呢?

<body>
    <div id="root">
        姓:<input type="text" v-model="firstName"><br><br>
        名:<input type="text" v-model="lastName"><br><br>
        全名:<span>{{fullName}}</span>
    </div>
    <script>
        Vue.config.productionTip = false

        const vm = new Vue({
            el: '#root',
            data:{
                firstName: '张',
                lastName: '三'
            },
            computed:{
                fullName:{
                    get(){
                        console.log('get被调用了')
                        return this.firstName +'-'+ this.lastName
                    }
                }
            }
        })
        console.log(vm)
    </script>
</body>

我在get函数中输出打印了一下,方便我们观察get函数什么时候被调用了。

可以看到,我们没有任何操作,但是在初始化的时候就已经调用了一次。那如果,我们在页面中用了很多次fullName呢?我们来看看。

    <div id="root">
        姓:<input type="text" v-model="firstName"><br><br>
        名:<input type="text" v-model="lastName"><br><br>
        全名:<span>{{fullName}}</span>
        全名:<span>{{fullName}}</span>
        全名:<span>{{fullName}}</span>
    </div>

可以看到,不管我们使用多少次fullName这个计算属性,getter只被调用了一次。也不卖兜子了,那是因为我们的coputed中有缓存机制,当我们的计算属性所依赖的属性没有发生变化时,就会继续复用我们之前的数据。 这也大大提高了Vue的效率,这也是computed的一大优势!!!

好了,我们来总结一下get函数在计算属性中,什么时候执行了。

  • 初次读取时会执行一次
  • 当依赖的数据发生改变时会被再次调用

在我们前端的面试中,经常也会问到这样的问题:与methosd实现相比,computed会有什么优势呢?之前我们也说了,computed内部有缓存机制(复用),效率更高,调试方便。

 注意:

  1. 计算属性最终会出现在vm上,直接读取使用即可
  2. 如果计算属性要被修改,那必须写set函数去响应修改,且set中要引起计算时依赖的数据发生变化

五、监视属性(Computed) 

我们先来看一个小案例。

<body>
    <div id="root">
        <h2>今天天气很{{info}}</h2>
        <button @click = 'isHot = !isHot'>点击切换天气</button>
    </div>
    <script>
        Vue.config.productionTip = false
        new Vue({
            el:'#root',
            data:{
                isHot:true
            },
            computed:{
                info(){
                    return this.isHot ? '炎热':'凉爽'
                }
            },
            watch:{
                isHot:{
                    // deep:true,
                    immediate:true,
                    handler(oldvalue,newvalue){
                        console.log('isHot被修改了',oldvalue,newvalue)
                    }
                }
            }
        })
    </script>
</body>

 这是一个关于切换天气的一个小案例,添加了一个watch的配置项,当我们监视的属性【isHot】发生变化时,就会调用handler函数,函数中有两个参数,分别是变化前的旧值和变化后的新值。其中,有两个属性。【deep:true】,是否开启深度监视?vue是具备深度监视这个功能的,但是需要我们把【deep】从false改为true;还有一个属性【immediate:true】,是否立即执行?当我们的这个监视过程中,如果是一个漫长的过程,可能要等很久,如果把【immediate】从默认的false改为true,它就不会等这个监视结束,会立即执行。

除了在new Vue里这样用对象的形式写之外,我们还可以这样写:

        vm.$watch('isHot',(ewvalue,oldvalue)=>{
            console.log('isHot被修改了',newvalue,oldvalue)
        })

其实这种写法其中的handler函数我用了简写,只要不需要【immediate】和【deep】配置项,我们都可以简写,比如第一种写法:

                isHot(newvalue,oldvalue){
                    console.log('isHot被修改了',newvalue,oldvalue)
                }

好了好了,今天就说到这里。拜比~

相关文章:

  • 常见的排序总结
  • kvm存储池
  • T1055 判断闰年 (信息学一本通C++)
  • 【C++】-- STL之用哈希桶模拟实现unordered_set和unordered_map
  • Games104现代游戏引擎入门-lecture17游戏引擎的Gameplay玩法系统基础_Advanced AI
  • [JS]数据类型
  • Transformer 无卷积骨干网络
  • 服务器安全狗是什么意思?有什么功能?
  • MySQL主从复制与读写分离
  • Mysql 面试题
  • 找回过期的微信文件,赶紧收藏这4个方法!
  • dsox4034a是德科技Keysight DSOX4034A示波器
  • [网鼎杯 2018]Fakebook
  • 《32天SQL筑基》导读
  • 【云原生 | Kubernetes 系列】--Envoy Tcp请求静态配置
  • 2018以太坊智能合约编程语言solidity的最佳IDEs
  • 77. Combinations
  • Java 9 被无情抛弃,Java 8 直接升级到 Java 10!!
  • JavaScript 一些 DOM 的知识点
  • JavaWeb(学习笔记二)
  • LeetCode29.两数相除 JavaScript
  • Magento 1.x 中文订单打印乱码
  • MYSQL如何对数据进行自动化升级--以如果某数据表存在并且某字段不存在时则执行更新操作为例...
  • Node项目之评分系统(二)- 数据库设计
  • PV统计优化设计
  • 聊聊spring cloud的LoadBalancerAutoConfiguration
  • 前端面试总结(at, md)
  • 如何在GitHub上创建个人博客
  • 删除表内多余的重复数据
  • 使用 Node.js 的 nodemailer 模块发送邮件(支持 QQ、163 等、支持附件)
  • 微信开放平台全网发布【失败】的几点排查方法
  • [地铁译]使用SSD缓存应用数据——Moneta项目: 低成本优化的下一代EVCache ...
  • postgresql行列转换函数
  • 宾利慕尚创始人典藏版国内首秀,2025年前实现全系车型电动化 | 2019上海车展 ...
  • 数据库巡检项
  • 曾刷新两项世界纪录,腾讯优图人脸检测算法 DSFD 正式开源 ...
  • # Swust 12th acm 邀请赛# [ E ] 01 String [题解]
  • ### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLTr
  • #控制台大学课堂点名问题_课堂随机点名
  • (11)MATLAB PCA+SVM 人脸识别
  • (3)nginx 配置(nginx.conf)
  • (4) PIVOT 和 UPIVOT 的使用
  • (Redis使用系列) Springboot 整合Redisson 实现分布式锁 七
  • (ZT)出版业改革:该死的死,该生的生
  • (二)构建dubbo分布式平台-平台功能导图
  • (附源码)spring boot基于小程序酒店疫情系统 毕业设计 091931
  • (附源码)springboot 智能停车场系统 毕业设计065415
  • (力扣记录)1448. 统计二叉树中好节点的数目
  • (免费分享)基于springboot,vue疗养中心管理系统
  • (三)docker:Dockerfile构建容器运行jar包
  • (十) 初识 Docker file
  • (四)搭建容器云管理平台笔记—安装ETCD(不使用证书)
  • (推荐)叮当——中文语音对话机器人
  • (转)Android学习系列(31)--App自动化之使用Ant编译项目多渠道打包
  • (转)AS3正则:元子符,元序列,标志,数量表达符