前言本文将简单介绍一下Vue3的setup函数以及如何通过数据驱动视图的方式来实现数据响应式的界面效果一从“搬砖”到“自动化”Vue3在前端开发中与html js有什么区别。又为什么会成为主流框架之一呢这也与Vue3其数据驱动视图的特性相关联。假如我们想要来修改一个页面中的某个属性的数值我该如何实现下面是一个二者之间的简单对比一JS开发流程在js中要想修改页面中的某个元素的值需要经过这样的一个流程1.定位元素位置document.querySelector()定位元素**2.确定元素类型innerText区分内容与输入值3.元素赋值element.textContent new_value赋值下面是一个简单的代码案例!DOCTYPEhtmlhtmllangenheadmetacharsetUTF-8metanameviewportcontentwidthdevice-width, initial-scale1.0titleDocument/title/headbody!-- 定义一个简单的盒子 --divclasscontainerh2测试内容/h2p姓名:spanidnamecheems/span/pp年龄:spanidage21/span/pbuttonid修改姓名测试按键/button/divscript//获取元素位置constelementdocument.querySelector(#name)constmodifydocument.querySelector(#修改姓名)//绑定点击事件modify.addEventListener(click,function(){element.textContentdoge//修改元素值alert(姓名已修改)})/script/body/html效果展示可以看到基本流程都是要经过获取元素-修改数值但是如果一个页面中有100处需要修改我难道需要来定位一百次元素所在位置再去修改吗未免太麻烦太臃肿了。这也就是js开发的痛点所在而Vue3就能很好的解决这一点二Vue3解决方案Vue3引入了setup()以及响应式系统使得我们程序员只需要关注修改的数据本身把其他的累赘操作交由框架去完成响应式系统Vue3 的响应式系统是其核心特性简单来说当数据发生变化时依赖该数据的视图 / 逻辑会自动更新无需手动操作 DOM听上去好像很复杂类比来讲。如果把响应式数据需要修改的数据比作一个传感器那么页面模版样式就可以看做是一个报警器。当传感器检测到数据变动时自动完成数据的逻辑更新生活中的声控灯也是如此检测到分贝提升就自动开灯。这在JS的开发中却还需要经过一系列的找灯按开关的操作。二Vue3响应式处理既然前面已经粗略了解了响应式系统的基本概念下面就来简单认识一下Vue3是如何实现这一点的。(一)ProxyProxy是响应式处理的底层机制ES6 原生 API用于拦截对象操作适用于任意类型的数据1.拦截对象操作指在代码访问或修改一个对象的属性时人为地插入一个“中间层”在这个中间层里你可以监视、修改甚至拒绝该行为。就像是一个小区的安保人员任何人想要进入修改数据set修改读取数据get都需要经过Proxy的审批2.为什么要拦截如果没有拦截数据就是“死”的。有了拦截数据就变成了响应式 (Reactive)的。这是 Vue 3 实现“数据变化视图自动更新”的灵魂。3.如何实现拦截在 Vue 3 中通过拦截实现响应式的核心公式是响应式 拦截 (Proxy) 追踪 (Track) 触发 (Trigger)。Proxy建立拦截追踪发生在get读取阶段触发发生在set修改阶段如果把Proxy比作一个哨兵那么get和set就可以视为两种陷阱而响应式系统也就需要经过这三个阶段阶段一拦截使用Proxy建立一个“哨位”。无论谁访问或修改数据都必须经过get和set陷阱。阶段二追踪当 渲染函数 运行并读取数据时get陷阱会被触发。此时Vue 会把这个渲染函数记录在一个“名单”里。阶段三触发当你修改数据时set陷阱被触发。Vue 会立刻翻开刚才的“名单”把上面记录的所有渲染函数重新执行一遍二setup函数setup是Vue3中的钩子函数它是程序的逻辑入口类似于C语言的main在其内部用于定义响应式的变量函数可以用于返回return对应想响应式数据1.基本用法在Vue3中使用setup来渲染一个组件一共需要四步分别是**1.引入源码scriptsrchttps://unpkg.com/vue3/dist/vue.global.js/script*2.创建容器dividapp/div3.创建Vue3应用并提供需要渲染数据scriptVue.createApp({})/script4.渲染数据使用双层花括号{{ }}包裹需要渲染的数据需要在容器内部假如我要渲染的数据是persondividapp!-- 渲染数据 --{{ person }}/div2.代码参考!DOCTYPEhtmlhtmllangenheadmetacharsetUTF-8metanameviewportcontentwidthdevice-width, initial-scale1.0titleDocument/title/headbody!-- 1.引入Vue3源码 --scriptsrchttps://unpkg.com/vue3/dist/vue.global.js/script!-- 2.准备容器 --dividapp!-- 4.渲染数据 --{{ person }}/div!-- 3.创建Vue3应用并提供需要渲染数据 --script//(1)创建Vue3应用Vue.createApp({//(2)提供渲染数据setup(){//注意此处使用了方法简写 ;完整写法 setup: function() { ... }constperson{id:114,name:cheems,class:Vue3}return{//此处return 使用简写键和值名字一样时可以简写 person:personperson}}}).mount(#app)//指定渲染的盒子对象的id是appVue.createApp({})/script/body/html**注意细节**在Vue.createApp({}之后需要添加.mount(‘#app’)来指定渲染的盒子所在位置3.效果展示三响应式函数响应式函数就是基于上述的Proxy的封装,其主要功能就是赋予数据响应式的特性作为联系数据与视图的媒介1.reactive函数1reactive作用reactive函数只能用于定义对象的响应式数据也就是它只能使得对象获得响应式的特性但是如果传入一个基本数据类型给reactive则不能使其获得响应式的特性一言以蔽之reactive函数可以使得对象数组这样的引用数据类型获得响应式的特性。2.reactive的使用!DOCTYPEhtmlhtmllangenheadmetacharsetUTF-8metanameviewportcontentwidthdevice-width, initial-scale1.0titleDocument/title/headbodyscriptsrchttps://unpkg.com/vue3/dist/vue.global.js/scriptdividappp我是 {{ obj.name }},我今年 {{ obj.age }}岁,我的爱好是{{ obj.hobby }}/p/divscript// 解构出 reactive 响应式函数const{createApp,reactive}VuecreateApp({setup(){//reactive响应式对象constobjreactive({name:cheems,age:18,hobby:唱跳rap篮球})return{//返回一个响应式对象objobj}}}).mount(#app)//定位渲染对象所在的盒子位置/script/body/html3效果展示那么这个页面和不使用reactive函数的有什么区别呢我们先来安装一个插件Vue.js.devtools,在chrome浏览器的拓展商店下载解压安装即可下面附上商店链接https://chrome.zzzmh.cn/index注意下载之后要启用插件在我们之前的页面中按下f12。在功能里找到Vue这个插件在前面的代码案例中我们发现当我们在插件页面中对于对象的value值做出的修改可以同步到页面的视图上这就是Vue3的对象响应式2.ref函数1ref函数的作用如果说reactive函数的作用是赋予对象可响应式那ref则使用范围更广一些ref可以同时使得基本数据类型以及引用数据类型的可响应式。也就是ref的使用不受到数据类型的限制下面是一个简单的对比我们给reactive传入一个字符串类型的str “Hello Cheems”时在浏览器的界面上虽然可以渲染成功但是在Vue的插件上却不能对str的内容做出修改2ref的使用但是使用ref就不同了我们先从Vue中解构出ref函数。可以将任意的数据类型传给ref使其获得可响应式的特性比如我们这样传入一个字符串类型“Hello Cheems”给ref注意事项当一个数据被ref函数调用时需要使用.value的方式来获取到对应的值。而reactive则不需要这一点。比如const str ref(‘Hello cheems’), 如果需要对str进行重新赋值的话我们需要使用str.value ‘新值’ 的形式。如果是一个对象使用了ref 比如const obj { name : ‘cheems’ , age : ‘18’}我们获取obj的键值时就需要通过obj.name.value来获取。其根本原因在于ref函数把其传入的参数对象封装为一个Proxy的响应式对象就像是给对象加了一层包裹拿到经过ref处理的对象的.value操作就好比拆包裹的操作。但是reactive函数不需要这一点是因为它虽然也可以把传入的参数对象转化为响应式的Proxy对象但不是通过包装而是拦截。相当于给对象加了一个监控不光如此我们也可以通过ref函数赋予一个事件可响应式的特性。比如我们在页面中定义一个图片以及对应的按钮当我们点击按钮时就会切换图片的样式不妨通过ref来实现!DOCTYPEhtmlhtmllangenheadmetacharsetUTF-8titleGemini 3 修正指南/title/headbodyscriptsrchttps://unpkg.com/vue3/dist/vue.global.js/scriptdividapph1{{ str }}/h1h2{{ str2 }}/h2p我是 {{ obj.name }}, 我今年 {{ obj.age }} 岁, 我的爱好是 {{ obj.hobby }}/pimg:srccurStatus ? activeImage : defaultImagealt动态图片stylewidth:300px;height:auto;display:block;margin-bottom:20px;buttonclicktoggleImg{{ curStatus ? 恢复图片 : 切换图片 }}/button/divscriptconst{createApp,reactive,ref}VuecreateApp({setup(){// 定义图片地址constdefaultImagehttps://pic4.zhimg.com/v2-21a3c6db3ef1f96846c835485983123f_b.jpgconstactiveImagehttps://picx.zhimg.com/50/v2-de7d59c0dd91ee6c2c7d58107a85025c_720w.jpg?source1def8acaconstobjreactive({name:cheems,age:18,hobby:唱跳rap篮球})conststrref(Hello Cheems)conststr2ref(要去码头整点薯条吗)constcurStatusref(false)// 切换逻辑consttoggleImg(){curStatus.value!curStatus.value// .value}return{obj,str,str2,curStatus,defaultImage,activeImage,toggleImg}}}).mount(#app)/script/body/html3.Vue 3refvsreactive对比表维度refreactive底层原理基于Object.defineProperty()拦截.value属性处理对象时内部调用reactive。基于ES6 Proxy拦截整个对象的属性读写。适用类型万能。基本类型String, Number 等及复杂类型Object, Array。仅限复杂类型。只能传入 Object, Array, Set, Map 等。访问方式脚本需带.value模板自动解包不带.value。脚本/模板均不带.value直接读写属性。重新赋值支持。通过x.value newValue替换响应式不会丢失。不支持。直接给变量赋值新对象x {}会导致响应式丢失。解构操作支持。解构后拿到的依然是 ref 对象响应式依然生效。不支持。直接解构let { a } obj会使属性变为普通变量。推荐场景1. 基本数据类型2. 以后可能需要替换整个对象3. 简单的数据结构。1. 成员较多、逻辑紧密的表单对象2. 深层嵌套的对象3. 逻辑聚合度高的实体。有关Vue3的基本介绍就到这里了此文只不过是初学者对于Vue3响应式处理的浅薄理解如果纰漏还请指出~~