一篇文章让你明白Vue3.0
2020/4/27 11:33:44
本文主要是介绍一篇文章让你明白Vue3.0,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
前言
4月21日,尤大大在B站分享了Vue.js3.0 Beta的最新进展,从2019年6月份的第一次发布的Vue3.0 Function-based API RFC,再到2019年10月份的Vue.js3.0 pre-alpha,经历一次次的更新,如果你还没有对3.0的更新内容有所了解,那么如何升职加薪,迎娶白富美,走上人生巅峰。
对于有理想有追求的小伙伴不要慌,认真读完这篇文章,相信你对于Vue3.0不再迷茫。废话不多说,手摸手带你开始学习!
设计目标
作为Vue这种全球热门的前端框架,每一次大版本的更新都会对开发人员带来巨大的影响,如果没有足够的“好处”,很难让已经习惯了Ctrl CV的同学们去接受。那么Vue3.0带来了哪些改变呢?
亮点
- 更快
- 基于 Proxy 的变动侦测,性能整体优于 getter / setter
- Virtual DOM 重构
- 编译模板的优化
- 更高效的组件初始化
- update性能提高1.3~2倍
- SSR速度提高了2~3倍
- 更小:Tree shaking support,可以将未使用模块“剪辑”,仅打包需要的,并不像2.x提供了所有的API,
- Composition API:可以实现更灵活且无副作用的复用代码。在2.x实现逻辑复用最常用的是 Mixins,然而存在两个问题:数据来源不清晰、命名空间容易冲突。那Composition API好在哪,后面会以实际代码介绍
- 加强TypeScript支持:Vue3.0的源码基本都是由TS编写,Vue 3 + TypeScript 插件正在开发,有类型检查,自动补全等功能。所以还是推荐大家在项目开发过程中使用ts
关于正式版
Vue的发布版本:Alpha - Beta - RC - 正式
所以还会经历RC版本才会有正式版可用,2020年估计不太可能会出了,不过也不用着急,正式版相比于beta主要是开发配套基础功能,比如脚手架、vue-router、以及生态插件等;
不过对于我们开发者来讲,最关心的还是它的语法,这块变动还是比较大的。下面来跟着项目看一下到底有哪些改动。
吐槽
"一堆东西丢在setup里,我还不如直接用react"
"代码结构还没有2.x版本清晰,更不好维护了"
"不就是抄react么"
个人认为吐槽Vue3.0的原因主要有两点
-
习惯了基于选项的开发方式,但是代码只是看上去更整洁。
- 一个复杂的组件往往需要同时处理多个不同的逻辑任务,每个逻辑任务所涉及的代码在选项 API 下是被分散在多个选项之中的。举例来说,从服务端抓取一份数据,可能需要用到 props, data(), mounted 和 watch。极端情况下,如果我们把一个应用中所有的逻辑任务都放在一个组件里,这个组件必然会变得庞大而难以维护,因为每个逻辑任务的代码都被选项切成了多个碎片分散在各处。
- 对比之下,基于函数的 API 让我们可以把每个逻辑任务的代码都整理到一个对应的函数中。当我们发现一个组件变得过大时,我们会将它切分成多个更小的组件;同样地,如果一个组件的 setup() 函数变得很复杂,我们可以将它切分成多个更小的函数。而如果是基于选项,则无法做到这样的切分,因为用 mixin 只会让事情变得更糟糕。
-
关于抄袭react。首先如果从原理的角度对于关于react hook和vue hook会发现其实还是有很大区别。 当然不得不承认Composition-Api灵感来源于react hooks,但是也谈不上抄不抄的,开发都提倡开源精神,优秀的框架也不是一开始就能赢得所有人的青睐,也是一次一次版本的迭代中逐渐更好的。使用框架的目的不就是为了广发开发人员么,何必非得搞门派之争。
基于 Composition Api 学习Vue3.0
创建项目
npm install -g @vue/cli //升级cli
vue create vue3.0-test // 创建项目,其实这里还是用的vue2.x
npm i @vue/composition-api -S
-
// mian.js import Vue from 'vue' import VueCompositionApi from '@vue/composition-api' Vue.use(VueCompositionApi) 复制代码
2.x的API可正常使用
Composition-API
setup()函数
-
执行时间
setup() 是 Vue3.0 中引入的一个新的组件选项,这是一个组件的入口,处于2.0的beforeCreate 和 Created 之间,setup 返回的是一个对象,里面的所有被返回的属性值,都会被合并到 Vue2.0 的 render 渲染函数里面,支持返回 JSX 代码片段。
-
接收 props 数据
props: { msg: String }, setup (props) { console.log(props.msg) const data = reactive({ showList: 1 }) console.log(data.showList) // 1 return { showList } } 复制代码
在 setup() 里的方法不能通过 this 来访问实例上的数据,而是通过直接读取 data 来访问。 这里传进来的 props 对象是响应式的 —— 它可以被当作数据源去观测,当后续 props 发生变动时它也会被框架内部同步更新。但对于用户代码来说,它是不可修改的(会导致警告)。
-
context
setup 函数的第二个形参是一个上下文对象,这个上下文对象中包含了一些有用的属性,这些属性在 vue 2.x 中需要通过 this 才能访问到,在 vue 3.x 中,它们的访问方式如下:
const MyComponent = { setup(props, context) { context.attrs context.slots context.parent context.root context.emit context.refs } } 复制代码
ref
ref() 函数用来根据给定的值创建一个响应式的数据对象,ref() 函数调用的返回值是一个对象,这个对象上只包含一个 .value 属性:
<template> <div>{{showRef}}</div> <div>{{name}}</div> </template> // 注意每个用到的api都要引入 import { ref } from '@vue/composition-api' export default { name: 'Home', setup () { const showRef = ref('test') //要访问 ref()创建出来的响应式数据对象的值,必须通过 .value 属性才可以 console.log(showRef.value) // test console.log(name.value) // error return { showRef, name: ref('zs') } } } 复制代码
reactive
reactive 它主要是处理你的对象让它经过 Proxy 的加工变为一个响应式的对象,类似于 Vue2.0 版本的 data 属性,需要注意的是加工后的对象跟原对象是不相等的,并且加工后的对象属于深度克隆的对象。
<template> <div>{{showList}}--{{showData2}}</div> </template> // 注意每个用到的api都要引入 import { toRefs, reactive } from '@vue/composition-api' export default { name: 'Home', setup () { const data = reactive({ showData1: 1, showData2: 2 }) }) return { ...toRefs(data) } } } 复制代码
ref和reactive都能创建响应式数据,那有什么区别呢? ref()单独地为某个数据提供响应式能力;而 reactive()给一整个对象赋予响应式能力。
但是在具体的用法上,通过 reactive() 包装的对象会有一个坑。如果想要保持对象内容的响应式能力,在 return 的时候必须把整个 reactive() 对象返回出去,同时在引用的时候也必须对整个对象进行引用而无法解构,否则这个对象内容的响应式能力将会丢失。
“对象的特性”是赋予给整个“对象”的,它里面的内容如果也想要拥有这部分特性,只能和这个对象捆绑在一块,而不能单独拎出来。
如果无法使用解构取出 reactive() 对象的值,每次都需要通过 . 操作符访问它里面的属性会是非常麻烦的,所以官方提供了 toRefs() 函数来为我们填好这个坑。只要使用 toRefs() 把 reactive() 对象包装一下,就能够通过解构单独使用它里面的内容了,而此时的内容也依然维持着响应式的特性。
对于我个人来说,会更倾向于使用 reactive() 搭配 toRefs() 来使用,因为经过 ref() 封装的数据必须通过 .value 才能访问到里面的值,写法上要注意的地方相对更多一些。
computed
- 创建只读计算属性
import { toRefs, reactive, computed } from '@vue/composition-api' export default { name: 'Home', setup () { const data = reactive({ showList: 1, onShowList: computed(() => { return data.showList + 1 }) }) console.log(data.onShowList) // 2 data.onShowList++ // error return { ...toRefs(data), } } } 复制代码
- 创建可读可写的计算属性
setup () { const data = reactive({ showList: 1, onShowList: computed({ // read get: () => data.showList + 1, // write set: val => { data.showList = val - 2 } }) }) 触发set函数 data.onShowList = 10 console.log(data.onShowList) // 10-2+1=9 return { ...toRefs(data) } } 复制代码
watchEffect
watchEffect与2.x watch类似,但是不需要分离监视的数据源和副作用回调。
import { toRefs, reactive, watchEffect } from '@vue/composition-api' export default { name: 'Home', setup () { const data = reactive({ showList: 1, watchShowList: 0, }) watchEffect(() => { data.watchShowList = data.showListAdd }) return { ...toRefs(data), } } } </script> 复制代码
function
没有了methods选项,那事件处理该怎么调用方法?
setup () { const data = reactive({ showList: 1, showListAdd: 0, }) function getShowList () { data.showListAdd = data.showList++ } function getMethods () { getShowList() } return { ...toRefs(data), getShowList, getMethods } } 复制代码
LifeCycle Hooks
import { onMounted, onUpdated, onUnmounted } from "@vue/composition-api"; export default { setup() { const data = reactive({ showList: 1 }) onMounted(() => { console.log('mounted!') }); onUpdated(() => { console.log('updated!') }) onUnmounted(() => { console.log('unmounted!') }) return { ...toRefs(data) }; } }; 复制代码
vue 2.x 的生命周期函数与新版 Composition API 之间的映射关系: (生命周期函数需要按需引入)
- beforeCreate -> use setup()
- created -> use setup()
- beforeMount -> onBeforeMount
- mounted -> onMounted
- beforeUpdate -> onBeforeUpdate
- updated -> onUpdated
- beforeDestroy -> onBeforeUnmount
- destroyed -> onUnmounted
- errorCaptured -> onErrorCaptured
逻辑复用
来举栗子感受一下:跟踪鼠标的位置
import { ref, onMounted, onUnmounted } from 'vue' export function useMousePosition() { const x = ref(0) const y = ref(0) function update(e) { x.value = e.pageX y.value = e.pageY } onMounted(() => { window.addEventListener('mousemove', update) }) onUnmounted(() => { window.removeEventListener('mousemove', update) }) return { x, y } } 复制代码
import { useMousePosition } from './mouse' export default { setup() { const { x, y } = useMousePosition() // other logic... return { x, y } } } 复制代码
Vue2.x的逻辑复用方式:
-
渲染上下文中公开的属性的来源不清楚。例如,当使用多个mixin读取组件的模板时,可能很难确定从哪个mixin注入了特定的属性。
-
命名空间冲突。Mixins可能会在属性和方法名称上发生冲突,而HOC可能会在预期的prop名称上发生冲突。
-
性能。HOC和无渲染组件需要额外的有状态组件实例,这会降低性能。
相比之下,使用Composition API:
-
暴露给模板的属性具有明确的来源,因为它们是从合成函数返回的值。
-
合成函数返回的值可以任意命名,因此不会发生名称空间冲突。
-
没有创建仅用于逻辑重用的不必要的组件实例。
有兴趣详细了解的小伙伴可以移步vue-composition-api
总结
总的来说,基于api的开发方式更灵活了,更上“档次”了,有木有~,期待正式版早点发布
最后,文章也只是我个人在学习过程中的一点心得,欢迎大家一起交流经验。如果文章对你有帮助的话,麻烦各位小伙伴动动小手点个赞吧 ~
这篇关于一篇文章让你明白Vue3.0的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-10-04package.json 文件位置在哪?-icode9专业技术文章分享
- 2024-10-01Craco.js学习:从入门到实践指南
- 2024-10-01Create-React-App学习:入门与实践指南
- 2024-10-01CSS-in-JS学习:从入门到实践指南
- 2024-09-30JSX语法学习:从入门到初步掌握
- 2024-09-30Mock.js学习:入门教程与实战演练
- 2024-09-30React Hooks学习:从入门到实践
- 2024-09-30受控组件学习:React中的基础入门教程
- 2024-09-29JS定时器教程:初学者必看指南
- 2024-09-29JS对象教程:初学者的全面指南