欢迎来到思维库

思维库

[科普文] Vue3 到底更新了什么?

时间:2025-11-05 16:02:13 出处:IT科技阅读(143)

Vue3 已经发布一段时间了,科普这个版本从底层实现到上层 API 设计都发生了非常大的到底变化,但具体改变了些什么呢?更新一起简单盘点下:

一、Composition API

使用传统的科普option配置方法写组件的时候问题,随着业务复杂度越来越高,到底代码量会不断的更新加大;由于相关业务的代码需要遵循option的配置写到特定的区域,导致后续维护非常的科普复杂,同时代码可复用性不高,到底而composition-api就是更新为了解决这个问题而生。

「1.1 Options API 的科普问题」

使用传统OptionsAPI时,新增或者修改一个需求,到底就需要分别在data,更新methods,科普computed里修改 。到底当业务逻辑和功能越来越多的更新时候理解和维护复杂组件变得困难。

「1.2 Composition API 的优势」

而Vue3 的组合式 API 将每个功能点抽成一个function使我们可以更加优雅的组织我们的代码。让相关功能的代码更加有序的组织在一起。WordPress模板

「1.3 reactive对比ref」

在 vue2.x 中,数据都是定义在data中。但是 Vue3.x 可以使用reactive和ref来进行数据定义。那么ref和reactive他们有什么区别呢?

从原理角度对比:

ref用来创建一个包含响应式的数据的引用对象。

接收数据可以是:基本数据类型、对象类型。基本类型的数据:响应式依然是靠object.defineProperty()的get与set完成的。对象类型:内部求助vue3.0中一个新函数reactive函数通过proxy实现。

源码地址:https://github.com/vuejs/vue-next/blob/master/packages/reactivity/src/ref.ts。

reactive用来定义:对象和数组通过使用Proxy来实现响应式(数据劫持), 并通过Reflect操作源对象内部的数据。

从使用角度对比:

ref定义的数据:操作数据需要.value,读取数据时模板中不需要.value直接使用即可。reactive定义的数据:

操作数据与读取数据:均不需要.value。1.4 新增 watchEffect 函数watch 函数需要指明监视的属性,并在回调函数中执行。默认情况仅在侦听的源数据变更时才执行回调。也可以加上immediate: true来使其立即生效。watchEffect不用指明监视哪个属性,监视的IT技术网回调中用到哪个属性,就监视哪个属性。//watchEffect所指定的回调中用到的数据只要发生变化,则直接重新执行回调。

watchEffect(()=>{

const x1 = sum.value

const x2 = person.age

console.log(watchEffect执行了回调)

})

二、重写 VDOM

优化前Virtual Dom的diff算法,需要遍历所有节点,而且每一个节点都要比较旧的props和新的props有没有变化。在Vue3.0中,只有带PatchFlag的节点会被真正的追踪,在后续更新的过程中,Vue不会追踪静态节点,只追踪带有PatchFlag的节点来达到加快渲染的效果。

vue

{{msg}}

{{msg}}

export function render(_ctx,_cache,$props, $setup,$data,$options){

return (_openBlock(),_createBlock( span ,null,[

_createVNode( span ,null, vue ),

_createVNode( span ,null,_toDisplayString(_ctx.msg), 1 /* TEXT */),

_createVNode( span ,{

id: _ctx,hello

class: bar

},_toDisplayString(_ctx.msg),9 /* TEXT, PROPS */, [ id ])

}

上面的源码中1 /* TEXT */这个标记就是 PatchFlag,Vue只会追踪第二个和第三个带有PatchFlag的节点。

在第三个span标签中PatchFlag变成了 9 /* TEXT, PROPS */, [ id ],b2b信息网提示我们这个dom元素中不仅有TEXT的变化,PROPS也可能会变化,后边数组中的内容则是有可能发生变化的属性。而静态添加的class没有被标记是因为 dom 元素的静态属性在渲染的时候就已经创建了,并且是不会变动的。在后面进行更新的时候,diff 算法是不会去管它的。

三、响应式实现

3.1 Vue2.x 的响应式

vue官方文档:https://cn.vuejs.org/v2/guide/reactivity.html。

实现原理:

对象类型:通过Object.defineProperty()对属性的读取、修改进行拦截(数据劫持)。数组类型:

通过重写更新数组的一系列方法来实现拦截。(对数组的变更方法进行了包裹)。Object.defineProperty(data, count, {

get () {},

set () {}

})

存在问题:

新增属性、删除属性, 界面不会更新。无法监听数组下标和length长度的变化。不支持 Map、Set、WeakMap 和 WeakSet。3.2 Vue3.0 的响应式

实现原理:

Proxy:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/ProxyReflect:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Reflect通过Proxy(代理): 拦截对象中任意属性的变化——属性值的读写、属性的添加、属性的删除等。通过Reflect(反射):对源对象的属性进行操作。

MDN文档中对Proxy与Reflect描述:

new Proxy(data, {

// 拦截读取属性值

get (target, prop) {

return Reflect.get(target, prop)

},

// 拦截设置属性值或添加新属性

set (target, prop, value) {

return Reflect.set(target, prop, value)

},

// 拦截删除属性

deleteProperty (target, prop) {

return Reflect.deleteProperty(target, prop)

}

})

proxy.name = tom

四、新的生命周期钩子

去掉了vue2.0中的 beforeCreate 和 created 两个阶段,新增了一个setup。执行setup 时,组件实例尚未被创建。每个生命周期函数必须导入才可以使用,并且所有生命周期函数需要统一放在 setup 里使用。destroyed 销毁后被重命名为 unmounted卸载后;beforeDestroy 销毁前生命周期选项被重命名为 beforeUnmount卸载前。

五、新的组件

「5.1 片段(Fragment)」

Vue2:组件必须有一个根标签。

</template>

Vue3: 组件可以没有根标签, 可以直接写多个根节点,内部会将多个标签包含在一个Fragment虚拟元素中。

</template>

好处: 减少标签层级, 减小内存占用,提升了渲染性能。

5.2 TeleportTeleport

就像是一个「任意门」,将包裹组件html结构传送到任何指定的地方。

例如我们日常开发中经常会使用到弹窗组件,Dialog组件会被渲染到一层层子组件内部,处理样式、定位都变得十分困难。这时我们希望将组件挂载在body上面,来更方便的控制Dialog的样式。简单来说,我们既希望继续在组件内部使用Dialog,又希望渲染的 DOM 结构不嵌套在组件内部的 DOM 中。就可以用到, 它可以在「不改变组件内部元素父子关系」的情况下,建立一个传送门将Dialog渲染的内容传送到body上面。

弹窗

</teleport>

5.3 Suspense等待异步组件时渲染一些额外内容,让应用有更好的用户体验。它提供两个template slot, 刚开始会渲染一个 fallback插槽下的内容, 直到到达某个条件后才会渲染 default 插槽的正式内容, 通过使用Suspense组件进行展示异步渲染更加简单。

我是App组件

加载中.....

</template>

分享到:

上一篇:假如是在虚拟机中使用Ubuntu,那么设置之前请先参照我的上一遍文章虚拟机Net方式设置连接外网 中的网络设置部分,先设置好主机的网络,然后配置虚拟机Ubuntu的IP和网关 假如主机操作系统就是Ubuntu,请直接参照下文进行设置 内容如下: 1. 检验是否可以连通,就使用ping命令ping 网关 永久修改Ubuntu LINUX IP 一、使用命令设置ubuntu的ip地址 并用下面的行来替换有关eth0的行: # The primary network interface - use DHCP to find our address auto eth0 iface eth0 inet dhcp 用下面的命令使网络设置生效: sudo /etc/init.d/networking restart 也可以在命令行下直接输入下面的命令来获取地址 sudo dhclient eth0 /etc/network/interfaces: sudo vi /etc/network/interfaces 并用下面的行来替换有关eth0的行: # The primary network interface auto eth0 iface eth0 inet static address 203.171.239.155 gateway 203.171.239.129 netmask 255.255.255.224 #network 203.171.239.128 #broadcast 192.168.3.159 将上面的ip地址等信息换成你自己就可以了.用下面的命令使网络设置生效: sudo /etc/init.d/networking restart /etc/network/interfaces: sudo vi /etc/network/interfaces 在该文件中添加如下的行: auto eth0:1 iface eth0:1 inet static address 192.168.1.155 netmask 255.255.255.0 work x.x.x.x broadcast x.x.x.x gateway x.x.x.x 根据你的情况填上所有诸如address,netmask,network,broadcast和gateways等信息. 用下面的命令使网络设置生效: sudo /etc/init.d/networking restart PS:根据上文方式,在虚拟机Vmware中安装Ubuntu,虚拟机网络连接方式为Net,设置静态IP连接网络,我已经测试通过,直接修改resolv.con和interfaces的方式可以保证开机后设置的IP依然存在。 设置后不能连接网络,欢迎留言,共同讨论,呵呵!

下一篇:播放本地音乐或者收听国外的音乐电台,Ubuntu 14.04 自带的音乐播放器 Rhythmbox 完全能够满足,但是假如你想有像酷狗那样的国内播放器就需要折腾一下,还好有深度音乐播放器,这是一款完全为中国人开发的音乐播放器,深度音乐播放器(Dmusic)+ 百度音乐插件=酷狗,但是假如是deepin系统用户就完全不需要折腾了。先截图一下:安装方法(注释:我的系统是Ubuntu 14.04 其他系统没有实验,所以不保证是否成功)先安装深度音乐播放器,安装很方便,有PPA可用,不过安装之前需要安装依赖包gstreamer0.10-ffmpeg,然后安装Dmusic,打开终端输入以下命令:sudo add-apt-repository ppa:noobslab/deepin-scsudo apt-get updatesudo apt-get install deepin-music-player安装完成之后,假如在Dash里面搜索不到深度音乐,重启一下系统。第一次启动会有一个向导:安装百度音乐插件(深度音乐播放器):1、安装 cython libwebkitgtk-dev python-dev git, 打开终端,输入以下命令:sudo apt-get install cython libwebkitgtk-dev python-dev git2、安装pyjavascriptcore,打开终端,输入以下命令:git clone https://github.com/sumary/pyjavascriptcore.gitcd pyjavascriptcoresudo python setup.py install3、安装百度音乐插件,打开终端,输入以下命令:git clone https://github.com/sumary/dmusic-plugin-baidumusic.gitcd dmusic-plugin-baidumusiccp -r baidumusic ~/.local/share/deepin-music-player/plugins/运行深度音乐, 选项设置->附加组件 中启用百度音乐即可

温馨提示:以上内容和图片整理于网络,仅供参考,希望对您有帮助!如有侵权行为请联系删除!

猜你喜欢

友情链接: