Vue3 Day3-Vue3响应式原理

news2024/9/23 3:18:38

3.1 子传父emit

非语法糖写法

子组件

<template>
    <h1>{{ name }}</h1>
    <h1>{{ school }}</h1>
    <button @click="test">按钮</button>
</template>
​
<!-- setup取代了export default -->
<script>
    export default {
        props: ['name', 'school'],
​
        emits: ['hello'] //派发hello,否则会警告
        setup(props, context) {
            let test = () => {
                context.emit('hello', '我是子组件的数据')
            }
            return {
                test
            }
        }
    }
</script>
​
<style scoped>
    .read-the-docs {
        color: #888;
    }
</style>

父组件

<template>
    <div>
        <HelloWorld name="白泽" school="观音大士学府" @hello="helloworld"></HelloWorld>
    </div>
</template>
​
<script>
    import HelloWorld from './components/HelloWorld.vue'
    export default {
        setup() {
            let helloworld = (val) => {
                console.log('val=>', val);
            }
            return {
                helloworld
            }
        },
        components: {
            HelloWorld
        }
    }
</script>
​
<style scoped>
​
</style>

语法糖写法

子组件

<template>
    <button @click="test">按钮</button>
</template>
​
<!-- setup取代了export default -->
<script setup>
    let emit = defineEmits(['hello']) //将子传父的方法名解构出来的
    let test = () => {
        emit('hello', [11, 22, 33])
    }
</script>
​
<style scoped>
    .read-the-docs {
        color: #888;
    }
</style>

父组件

<template>
    <div>
        <HelloWorld @hello="helloworld"></HelloWorld>
    </div>
</template>
​
<script setup>
    import HelloWorld from './components/HelloWorld.vue'
​
    let helloworld = (val) => {
        console.log('val=>', val);
    }
</script>
​
<style scoped>
​
</style>

3.2 defineExpose的使用

子组件

<template>
    <h1>{{name}}</h1>
    <h1>{{info}}</h1>
</template>
​
<!-- setup取代了export default -->
<script setup>
    import {
        ref,
        reactive
    } from 'vue'
    let name = ref('我是子组件')
    let info = reactive({
        age: 12,
        hobby: '敲代码'
    })
    // 将响应式数据暴露出去
    defineExpose({
        name,
        info
    })
</script>
​
<style scoped>
    .read-the-docs {
        color: #888;
    }
</style>

父组件

<template>
    <div>
        <!-- 这里的ref是获取子组件传过来的数据 -->
        <HelloWorld ref="hello"></HelloWorld>
        <button @click="getData">接收子组件的数据</button>
    </div>
</template>
​
<script setup>
    import HelloWorld from './components/HelloWorld.vue'
    import {
        ref
    } from 'vue'
​
    let hello = ref()
    let getData = () => {
        console.log('val', hello); //RefImpl
        console.log('name', hello.value.name); //我是子组件
        console.log('info', hello.value.info); //Proxy(Object) {age: 12, hobby: '敲代码'}
    }
</script>
​
<style scoped>
​
</style>

3.3 Vue3响应式原理

proxy代理
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    <body>
        <script>
            var proxy = new Proxy({
                add: function(value) {
                    return value + 10
                },
                info: '我是proxy'
            }, {
                get: function(target, key, poperty) {
                    // console.log('target', target); // target {info: '我是proxy', add: ƒ}
                    // console.log('key', key); //key name
                    // console.log('poperty', poperty); // proxy实例本身,该参数可选
​
​
                    // console.log('我是钩子函数'); // 我是钩子函数  先打印这里,相当于之前学的钩子函数
                    return target[key]
                },
                set: function(target, key, value, receiver) {
                    return target[key] = value
                }
            })
            console.log('proxy.info=>', proxy.info); // proxy.info=> 我是proxy
            proxy.info = 'proxy' //target[key] = value
            console.log('proxy.info=>', proxy.info); // proxy.info=> proxy
        </script>
    </body>
</html>
Vue3响应式原理

proxy和Reflect结合产生的,产生更好的兼容性,可以很好的捕获错误

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title></title>
    </head>
    <body>
        <script>
            let obj = {
                name: 'vue3',
                arr: [11, 22, 33],
                obj: {
                    obj1: {
                        num: 99
                    }
                }
            }
​
            function proxyData(value) {
                let proxy = new Proxy(value, {
                    get: function(target, key) {
                        let val = target[key]
                        if (typeof val == 'object') {
                            proxyData(val)
                        }
                        return val
                    },
                    set: function(target, key, value) {
                        return target[key] = value
                    },
                    deleteProperty: function(target, key) {
                        delete target[key]
                        return true
                    }
                })
                return proxy
            }
            let pro = proxyData(obj)
            pro.age = 12 //新增属性及属性值
            console.log('pro', pro); // Proxy(Object) {name: 'vue3', arr: Array(3), obj: {…}, age: 12}
            delete pro.name //删除
            console.log('pro', pro); //Proxy(Object) {arr: Array(3), obj: {…}, age: 12}
            pro.arr.push(44) //数组方法
            console.log('pro.arr', pro.arr); // arr:(4) [11, 22, 33, 44]
            pro.arr[0] = 666 //通过数组下标修改值
            console.log('pro.arr', pro.arr); // arr:(4) [666, 22, 33, 44]
        </script>
    </body>
</html>
Reflect

产生更好的兼容性,可以很好的捕获错误

<!-- <!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title></title>
    </head>
    <body>
        <script>
            let obj = {zhangsan:100,lisi:200}
            Object.defineProperty(obj,'wangwu',{
                get(){
                    return 300
                }
            })
            Object.defineProperty(obj,'wangwu',{
                get(){
                    return 400
                }
            })
        </script>
    </body>
</html> -->
<!-- <!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title></title>
    </head>
    <body>
        <script>
            let obj = {zhangsan:100,lisi:200}
            Reflect.defineProperty(obj,'wangwu',{
                get(){
                    return 300
                }
            })
            Reflect.defineProperty(obj,'wangwu',{
                get(){
                    return 400
                }
            })
        </script>
    </body>
</html> -->
​
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title></title>
    </head>
    <body>
        <script>
            let obj = {
                zhangsan: 100,
                lisi: 200
            }
            const a = Reflect.defineProperty(obj, 'wangwu', {
                get() {
                    return 300
                }
            })
            const b = Reflect.defineProperty(obj, 'wangwu', {
                get() {
                    return 400
                }
            })
            console.log(a);
            console.log(b);
​
            // proxy和Reflect结合产生的
        </script>
    </body>
</html>
Vue2的响应式原理

Object.defineProperty() 可以监测到属性的获取、修改,但是新增、删除监测不到

对于数组:Object.defineProperty()不能监听数组的变化

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>数据响应式原理</title>
    </head>
    <body>
        <div id="app">
            Hello Vue
        </div>
        <script>
            //模拟Vue实例中的data选项
            let data = {
                msg: 'Hello Vue',
                arr: [1, 2, 3],
                count: 0
            }
​
            //模拟Vue的实例
            let vm = {};
​
            function defineProperties(data) {
                //循环给每个属性使用Object.defineProperty()
                Object.keys(data).forEach(key => {
                    //数据劫持,当访问或者设置vm中的成员的时候,做一些干预操作
                    Object.defineProperty(vm, key, {
                        //可枚举(即可被遍历)
                        enumerable: true,
                        //可配置(可以使用delete删除,可以通过defineProperty重新定义)
                        configurable: true,
​
                        //当获取值时执行
                        get() {
                            console.log('getter:', data[key]);
                            return data[key];
                        },
                        //当设置、更新msg变量时执行
                        set(newValue) {
                            console.log("setter:", newValue);
                            if (data[key] === newValue) {
                                return; //前后数据相同,则不用做操作DOM的多余操作
                            }
                            data[key] = newValue;
                            // 将id=app的标签元素的内容改成newValue
                            document.querySelector("#app").textContent = newValue;
                        }
                    })
                });
            }
​
            //执行该函数,使每个属性添加响应式
            defineProperties(data);
​
            //测试setter
            vm.msg = "Hello 响应式原理";
            vm.arr[1] = 4
            //测试getter
            console.log(vm);
        </script>
    </body>
</html>
Proxy-Vue3的响应式原理案例对比
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title></title>
    </head>
    <body>
        <div></div>
        <script>
            const arr = [1, 2, 3];
​
            const handler = {
                get(target, key) {
                    console.log(`修改了数组下标为 ${key} 的元素`);
                    return target[key];
                },
                set(target, key, value) {
                    console.log(`set修改了数组下标为 ${key} 的元素,新值为 ${value}`);
                    target[key] = value;
                    return true;
                }
            };
​
            const proxyArr = new Proxy(arr, handler);
​
            proxyArr[1] = 4; // 输出 "修改了数组下标为 1 的元素,新值为 4"
            //触发了set 我们认为就是产生页面响应性变化
        </script>
    </body>
</html>
Property-Vue2的响应式原理案例对比
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>数据响应式原理</title>
    </head>
    <body>
        <div id="app">
            Hello Vue
        </div>
        <script>
            let arr = [1, 2, 3]
            let obj = {}
            Object.defineProperty(obj, 'arr', {
                get() {
                    console.log('get arr')
                    return arr
                },
                set(newVal) {
                    console.log('set', newVal)
                    arr = newVal
                }
            })
            obj.arr[1] = 4 // 只会打印 get arr, 不会打印 set
            //没有触发set 我们认为就是没有产生页面响应性变化
        </script>
    </body>
</html>

3.4 插槽

具名插槽

作用域插槽:父组件有权访问子组件的数据并修改

子组件

<template>
    <!-- 具名插槽 -->
    <!-- <slot name="left">11</slot>
    <slot name="center">22</slot>
    <slot name="right">3344</slot> -->
​
    <!-- 作用域插槽 -->
    <slot :info="info"></slot>
</template>
​
<!-- setup取代了export default -->
<script setup>
    import {
        ref,
        reactive
    } from 'vue'
​
    // 作用域插槽
    let info = reactive({
        age: 12,
        hobby: '敲代码'
    })
</script>
​
<style scoped>
    .read-the-docs {
        color: #888;
    }
</style>

父组件

<template>
    <div>
        <!-- 具名插槽 -->
        <!-- <HelloWorld> -->
        <!-- 写法1: -->
        <!-- <template #left></template>
            <template #center></template>
            <template #right></template> -->
​
        <!-- 写法2: -->
        <!-- <template v-slot:left></template>
            <template v-slot:center></template>
            <template v-slot:right></template> -->
​
        <!--错误 <span slot="left"></span>
            <span slot="center"></span>
            <span slot="right">我是right</span>
             这种不要写了 -->
        <!-- </HelloWorld> -->
​
        <!-- 作用域插槽 -->
        <HelloWorld v-slot="zyycc">{{zyycc}}</HelloWorld>
    </div>
</template>
​
<script setup>
    import HelloWorld from './components/HelloWorld.vue'
    import {
        ref
    } from 'vue'
</script>
​
<style scoped>
​
</style>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2156433.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

算法-K个一组翻转链表

// 要实现没k个节点进行翻转的操作&#xff0c;可以按照一下步骤进行 // 1.计算链表长度 // 2.分组反转 // 3. 使用一个虚拟头节点来处理边界情况 // 4.每次处理k个节点进行反转 // 5.如果剩余节点不足k个 则保持原有顺序 // 6.依次反转每组中的节点 // 1.使用prevGroupEEnd追…

EvilScience靶机详解

主机发现 arp-scan -l 得到靶机ip 192.168.229.152 端口扫描 nmap -sV -A -T4 192.168.1.20 这段代码使用 nmap 命令来扫描目标主机 192.168.1.20&#xff0c;并执行以下操作&#xff1a;-sV&#xff1a;探测开放的端口&#xff0c;以确定服务/版本信息。-A&#xff1a;启…

[大语言模型] LINFUSION:1个GPU,1分钟,16K图像

1. 文章 2409.02097 (arxiv.org)https://arxiv.org/pdf/2409.02097 LINFUSION: 1 GPU, 1 MINUTE, 16K IMAGE 摘要 本文介绍了一种新型的扩散模型LINFUSION&#xff0c;它能够在保持高分辨率图像生成性能的同时显著降低时间和内存复杂度。该模型采用了基于Transformer的UNet进…

常用卫星学习

文章目录 Landsat-8 Landsat-8 由一台操作陆地成像仪 &#xff08;OLI&#xff09; 和一台热红外传感器 &#xff08;TIRS&#xff09;的卫星&#xff0c;OLI 提供 9 个波段&#xff0c;覆盖 0.43–2.29 μm 的波长&#xff0c;其中全色波段&#xff08;一般指0.5μm到0.75μm左…

Java的IO流(二)

目录 Java的IO流&#xff08;二&#xff09; 字节缓冲流 基本使用 使用缓冲流复制文件 字符缓冲流 缓冲流读取数据原理 字符编码 字符集 转换流 序列化流与反序列化流 基本使用 禁止成员被序列化 序列号不匹配异常 打印流 基本使用 系统打印流与改变流向 Prop…

【kaggle竞赛】毒蘑菇的二元预测题目相关信息和思路求解代码

毒蘑菇的二元预测 您提供了很多关于不同二元分类任务的资源和链接&#xff0c;看起来这些都是Kaggle竞赛中的参考资料和高分解决方案。为了帮助您更好地利用这些资源&#xff0c;这里是一些关键点的总结&#xff1a; Playground Season 4 Episode 8 主要关注的竞赛: 使用银行…

2024 硬盘格式恢复软件大揭秘

宝妈们硬盘存储图片、设计师用硬盘存储素材、学生们用硬盘存储作业和数据已经是一个普遍的社会现象了。但是有时候数据迁移之后想要一份全新的硬盘我们就会采取硬盘格式化的操作&#xff0c;如果格式化之后发现硬盘数据没有备份好硬盘格式化后能恢复数据吗&#xff1f;这次我就…

没错,我给androidx修了一个bug!

不容易啊&#xff0c;必须先截图留恋&#x1f601; 这个bug是发生在xml中给AppcompatTextView设置textFontWeight&#xff0c;但是却无法生效。修复bug的代码也很简单&#xff0c;总共就几行代码&#xff0c;但是在找引起这个bug的原因和后面给androidx提pr却花了很久。 //App…

git学习【完结】

git学习【完结】 文章目录 git学习【完结】一、Git基本操作1.创建本地仓库2.配置本地仓库1.局部配置2.全局配置 3.认识工作区、暂存区、版本库4.添加文件5.修改文件6.版本回退7.撤销修改8.删除文件 二、Git分支管理1.理解分支2.创建、切换、合并分支3.删除分支4.合并冲突5.合并…

【每天学个新注解】Day 2 Lombok注解简解(一)—@Data、@Build、@Value

Data 相当于同时使用了 Getter 、Setter 、RequiredArgsConstructor、ToString、EqualsAndHashCode 1、如何使用 需要同时使用Getter 、Setter 、RequiredArgsConstructor、ToString、EqualsAndHashCode注解一个Bean的时候。 2、代码示例 例&#xff1a; Data public cla…

H5白色大方图形ui设计公司网站HTML模板源码

源码名称&#xff1a;白色大方图形ui设计公司网站模板源码 源码介绍&#xff1a;一款H5自适应白色大方图形ui设计公司官网网站模板源码。源码含有七个页面&#xff0c;可用于各种设计公司官网。 需求环境&#xff1a;H5 下载地址&#xff1a; https://www.51888w.com/369.ht…

基于vue框架的宠物托管系统设计与实现is203(程序+源码+数据库+调试部署+开发环境)系统界面在最后面。

系统程序文件列表 项目功能&#xff1a;用户,宠物种类,商家,咨询商家,用户宠物,宠物托管,宠物状况,宠物用品,用品分类,商家公告,结束托管,账单信息,延长托管 开题报告内容 基于Vue框架的宠物托管系统设计与实现开题报告 一、引言 随着现代生活节奏的加快&#xff0c;越来越…

如何在Linux Centos7系统中挂载群晖共享文件夹

前景&#xff1a;企业信息化各种系统需要上传很多的图片或者是文件&#xff0c;文件如何在群晖中显示&#xff0c;当文件或者图片上传到linux指定文件夹内&#xff0c;而文件夹又与群晖共享文件夹进行挂载&#xff0c;就能保证上传的文件或者图片出现在群晖并在群晖里进行管理。…

分布式安装LNMP

目录 搭建LNMP架构 安装mysql 1.上传mysql软件包&#xff0c;关闭防火墙和核心防护 2.安装环境依赖包&#xff0c;桌面安装可能有自带的数据库除 3.配置软件模块 4.编译及安装 5.创建mysql用户 6.修改mysql 配置文件 7.更改mysql安装目录和配置文件的属主属组 8.设置…

Rumor Mitigation in Social Media Platforms with Deep Reinforcement Learning

ABSTRACT 社交媒体平台已成为人们传播和获取信息的主要渠道之一&#xff0c;其可靠性受到网络谣言的严重威胁。现有的辟谣手段如暂停用户、播放真实信息等&#xff0c;要么成本高&#xff0c;要么扰乱用户。在本文中&#xff0c;我们引入了一种新颖的谣言缓解范例&#xff0c;…

springboot每次都需要重设密码?明明在springboot的配置中设置了密码

第一步&#xff1a;查看当前的密码是什么&#xff1f; 打开redis-cli.exe&#xff0c;输入config get requirepass&#xff0c;查看当前的密码是什么&#xff1f; 接着&#xff0c;修改redis的配置文件&#xff0c;找到redis的安装目录&#xff0c;找到相关的conf文件&#x…

Spring高手之路24——事务类型及传播行为实战指南

文章目录 1. 编程式事务&#xff08;不推荐&#xff09;2. 声明式事务&#xff08;推荐&#xff09;3. 事务的传播行为&#xff08;复杂混合事务场景及时序图说明&#xff09;3.1 NESTED和REQUIRES_NEW传播行为的区别 1. 编程式事务&#xff08;不推荐&#xff09; 定义&#…

如何从 Nutanix 迁移至 SmartX 超融合?解读 4 类迁移方案和 2 例迁移实践

2022 年底&#xff0c;Nutanix&#xff08;路坦力&#xff09;正式宣布将中国市场交由合作伙伴&#xff08;联想&#xff09;主导销售&#xff0c;并于 2023 年 8 月完成全面转型。转型后&#xff0c;虽然中国用户依旧可以使用 Nutanix 产品&#xff0c;但在软件的续保和维保方…

企业EMS -能源管理系统-能源管理系统源码-能源在线监测平台

能源管理系统是以帮助工业生产企业在扩大生产的同时&#xff0c;合理计划和利用能源&#xff0c;降低单位产品能源消耗&#xff0c;提高经济效益&#xff0c;降低CO2排放量为目的信息化管控系统。 我国能源管理从上世纪80年代中期开始&#xff0c;通过“能量平衡测试”、“能源…

安卓数据存储——SharedPreferences

共享参数 SharedPreferences 1、sharedPreferences是Android的一个轻量级存储工具&#xff0c;采用的存储结构是key - value的键值对方式 2、共享参数的存储介质是符合XML规范的配置文件。保存路径是&#xff1a;/data/data/应用包名/shared_prefs/文件名.xml 使用场景&…