【学习笔记】《玩转Vue3全家桶》--初探Vue3新特性

前言: Vue3出来一段时间了,借着《玩转Vue3全家桶》的课程,来好好了解一下Vue3吧。

一、Vue2的核心模块和历史遗留问题

    从普通开发者的角度来说,Vue2响应式并不是真正意义上的代理,而是基于Object.defineProperty()实现的。对于Object.defineProperty()这个API的细节,其实这个API并不是代理,而是对某个属性进行拦截,所以有很多缺陷,比如:删除数据就无法监听,需要$delete等API辅助才能监听到。
    并且,Option API在组织代码较多组件的时候不易维护。对于Option API来说,所有的methods、computed都在一个对象里配置,这对小应用来说还好。但代码超过300行的时候,新增或修改一个功能,就需要不停地在data、methods里跳转写代码,上下反复横跳。

二、从七个方面了解Vue3新特性

    在Vue3新特性中,其中,响应式系统、Composition API组合语法、新的组件和Vite是需要重视的;自定义渲染器这方面的知识,想用Vue开发跨端应用时会用到;如果想对Vue源码作出贡献,RFC机制需要好好研究一下,并且得对TypeScript重构有很好的经验。
    1.RFC机制
    Vue3的第一个新特性和代码无关,而是Vue团队开发的工作方式。

    2.响应式系统
    Vue2的响应式机制是基于Object.defineProperty()这个API实现的,此外,Vue还是用了Proxy,这两者看起来都像是对数据的读写进行拦截,但是defineProperty是拦截具体某个属性,Proxy才是真正的“代理”。
    怎么理解这两者的区别呢?首先看defineProperty这个API,defineProperty的使用,要明确地写在代码里,下面是示例代码:

Object.defineProperty(obj,'title',{
	get() {},
	set() {},
})

    当项目里“读取obj.title”和“修改obj.title”的时候被defineProperty拦截,但defineProperty对不存在的属性无法拦截,所以,Vue2中所有数据必须要在data里声明。
    而且,如果title是一个数组的时候,对数组的操作,并不会改变obj.title的指向,虽然我们可以拦截.push等操作实现部分功能,但是对数组的长度的修改等操作还是无法实现拦截,所以还需要额外的$set等API。
    而Proxy这个API就是真正的代理了,先看它的用法:

new Proxy(obj,{
	get() { },
	set() { },
})

    需要注意的是,虽然Proxy拦截obj这个数据,但obj具体是什么属性,Proxy则不关心,统一都拦截了。而且Proxy还可以监听更多的数据格式,比如Set、Map,这是Vue2做不到的。
    当然,Proxy存在一些兼容性问题,这也是为什么Vue3不兼容IE11以下的游览器的原因,还好现在IE用的人不多了。
    更重要的是,Proxy代表一种方向,就是框架会越来越多的拥抱游览器的新特性。在Proxy普及之前,我们是没有办法完整的监听一个JavaScript对象的变化,只能使用Object.defineProperty()去实现一部分功能。

    3.自定义渲染器
    Vue2内部所有的模块都是揉在一起的,这样做会导致不好扩展的问题。Vue3如何解决这个问题的呢?通过拆包,使用最近流行的monorepo管理方式,响应式、编译和运行时全部独立了,变成下图所示的模样:
【学习笔记】《玩转Vue3全家桶》--初探Vue3新特性_第1张图片
    在Vue3的组织架构中,响应式独立了出来。而Vue2的响应式只服务于Vue,Vue3的响应式就和Vue解耦了,甚至可以在Node.js和React中使用响应式。
    渲染的逻辑也拆成了平台无关渲染逻辑游览器渲染API两部分。
    在这个架构下,Node的一些库,甚至React都可以依赖响应式。在任何时候,如果你希望数据被修改了之后能通知你,你都可以单独依赖Vue3的响应式。
    那么,在你想使用Vue3开发小程序、开发canvas小游戏以及开发客户端的时候,就不用全部fork Vue的代码,只需要实现平台的渲染逻辑就可以。
【学习笔记】《玩转Vue3全家桶》--初探Vue3新特性_第2张图片
    在Vue3中,响应式、编译和运行时几部分组合在一起就是运行在游览器端的Vue3,每个模块又都可以独立扩展出新的功能。

    4.全部模块使用TypeScript重构
    JavaScript是弱类型的语言。类型系统带来的好处,笼统地说,就是类型系统带来了更方便的提示,并且让我们的代码能够更健壮
    来看看例子吧,在下面这段代码中,我们首先定义了name这个变量,在定义的时候标记的是一个字符串,因而后面赋值时,赋值为数字就会报错。
    之后,我们定义一个类型Person,里面的变量name是字符串类型,变量age是数字类型。违反这个设置的数据就报错,这在多人协同和长期维护的项目里带来的收益是巨大的,因为这样可以使错误的代码在编译阶段就被发现,从而避免程序上线运行后,可能会发生的更大的异常错误。

let name:string = '我是个靓女'
name = 1 //报错
interface Person {
	name: string;
	age: number;
}
let me:Person = {
	name:'靓仔胜',
	age:18
}
me.age = '整条街' //报错

    所以,大部分开源的框架都会引入类型系统,来对JavaScript进行限制。这样做的原因就是:①类型系统带来了更方便的提示;②类型系统让代码更健壮。

    5.Composition API组合语法
    Composition API是Vue3中,最喜欢的一个特性,饿哦们也叫它组合API。
    先举个vue2的栗子,一个累加器,并且还有一个计算属性显示累加器乘以2的结果。

<div id="app">
	<h1 @click="add">{{count}}*2</h1>
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
let App = {
	data(){
		return {
			count:1
		}
	},
	methods:{
		add(){
			this.count++
		}
	},
	computed:{
		double(){
			return this.count*2
		}
	}
}
Vue.createApp(App).mount('#app')
</script>

    在Vue3中,除了上面这种这个写法,还可以采用下面的写法,新增一个setup配置:

<div id="app">
	<h1 @click="add">{{state.count}} * 2 = {{double}}</h1>
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
const {reactive,computed} = Vue
let App = {
	setup(){
		const state = reactive({
			count:1
		})
		function add(){
			state.count++
		}
		const double = computed(()=>state.count*2)
		return {state,add,double}
	}
}
Vue.createApp(App).mount('#app')
</script>

    使用Composition API后,代码看起来很繁琐,没有Vue2中Options APId 写法简单好懂,但Options API的写法也有几个很严重的问题:

  • 由于所有数据都挂载在this之上,因而Options API的写法对TypeScript的类型推导很不友好,并且这样也不好做Tree-shaking清理代码;
  • 新增功能基本都得修改data、method等配置,并且代码上300行之后,会经常上下反复横跳,开发很痛苦;
  • 代码不好复用,Vue 2的组件很难抽离通用逻辑,只能使用mixin,还会带来命名冲突的问题。

    我们使用Composition API后,虽然看起来繁琐了一些,但是带来了很多好处:

  • 所有API都是import引入的。用到的功能都import进来,对Tree-shaking很友好,例子里没用到的功能,打包的时候会被清理掉,减少包的大小;
  • 不再上下反复横跳,可以把一个功能呢模块的methods、data都放在一起书写,维护更轻松;
  • 代码方便服用,可以把一个功能所有的methods、data封装在一个毒瘤的函数里,复用代码非常容易;
  • Composotion API新增的return等语句,在实际项目中使用< script setup >特性可以清除,我们后续项目中都会用到这样的操作。

Composition API对我们开发Vue项目起到了巨大的帮助。 下面的图示很好地说明了问题:每一个功能模块的代码颜色一样,左边是Options API,一个功能的代码零散的分布在data、methods等配置内,维护起来很麻烦,二右边的Composition API就不一样了,每个功能模块都在一起维护。
【学习笔记】《玩转Vue3全家桶》--初探Vue3新特性_第3张图片
    6.新的组件
    Vue3还内置了Fragment、Teleport和Suspense三个新组件。

  • Fragment:Vue 3组件不再要求有一个唯一的根节点,清除了很多无用的占位div;
  • Teleport:允许组件渲染在别的元素内,主要开发弹框组件的时候特别有用;
  • Suspense:异步组件,更方便开发有异步请求的组件。

    7.新一代工程化工具Vite
    Vite不在Vue3的代码包内,和Vue也不是强绑定,Vite的竞品是Webpack,而且按照现在的趋势看,使用率超过Webpack也是早晚的事。
    Vite主要提升的是开发的体验,Webpack等工程化工具的原理,就是根据你的import依赖逻辑,形成一个依赖图,然后调用对应的处理工具,把整个项目打包后,放在内存里再启动调试。
    由于要预打包,所以复杂项目的开发,启动调试环境需要 3 分钟都很常见,Vite 就是为了解决这个时间资源的消耗问题出现的。
    你可能不知道,现代浏览器已经默认支持了 ES6 的 import 语法,Vite 就是基于这个原理来实现的。具体来说,在调试环境下,我们不需要全部预打包,只是把你首页依赖的文件,依次通过网络请求去获取,整个开发体验得到巨大提升,做到了复杂项目的秒级调试和热更新。
    下图展示了 Webpack 的工作原理,Webpack 要把所有路由的依赖打包后,才能开始调试。
【学习笔记】《玩转Vue3全家桶》--初探Vue3新特性_第4张图片
    而下图所示的是 Vite 的工作原理,一开始就可以准备联调,然后根据首页的依赖模块,再去按需加载,这样启动调试所需要的资源会大大减少。
【学习笔记】《玩转Vue3全家桶》--初探Vue3新特性_第5张图片
总结:
这篇学习的重点就是vue3主要的新特性,再来对这些特征做一个回顾吧:

  • 新的RFC机制也让我们所有人都可以参与Vue新语法的讨论;
  • 工程化工具Vite带来了更丝滑的调试体验;
  • 对于产品的最终效果来看,Vue3性能更高,体积更小;
  • 对于普通开发者来说,Composition API组合语法带来了更好的组织代码的形式。全新的响应式系统基于Proxy,也可以独立使用;
  • Vue3内置了新的Fragment、Teleport和Suspense等组件;
  • 对于Vue的二次开发来说,自定义渲染器让我们开发跨端应用时更加得心应手;
  • 对于Vue的源码维护者,全部的模块使用TypeScript重构,能够带来更好的可维护性;
        总而言之,Vue3带给我们的就是更快、更强且更易于扩展的开发体验,我们也可以用下面这个图来做个总结:
    【学习笔记】《玩转Vue3全家桶》--初探Vue3新特性_第6张图片

你可能感兴趣的:(玩转Vue3全家桶,vue.js,vue.js,javascript)