前段时间,尤大牛将Vue3正式发布,至此,我们的前端的三大框架都进入了新的时代,那么Vue3的发布带来了哪些新的变化和语法呢,作为一名前端开发者,我也想结合自己的实际应用,做一个分享,下面请看目录和示例:
目录
- Vue3项目创建
- 实例化
- Composition Api
- 组件通信
- 生命周期
一. vue3项目创建
安装vue3脚手架,打开命令行窗口,执行命令:
npm install -g @vue/cli@next
npm update -g @vue/cli // 如果你已经安装过vue的cli,用此命令更新到最新版本
查看安装结果,在命令行窗口,继续运行:
vue -V
创建项目
vue create study-vue3-demo
这里是选择项目配置项,有vue2的,有vue3的,我们选择最后一个自定义的 Manually select features
在这里使用空格键选择你需要的模块,Router,Vuex,这两个不用说,必要的,其它啥单元格测试,EsLinter,看你个习惯去安装,选择完成之后回车,后面还有一系列Yes or No的选择,就是根据你的需要选择就OK了:
上面的选项选择完后,就是安装依赖了,至此,我们的vue3项目,使用vue3的官方脚手架,创建项目成功。整个项目创建过程,和vue2最明显的不同就是,vue2选择完配置项后是不会安装依赖包的,需要在进入到项目文件里去npm install
,而vue3是默认安装。这个时候我们可以进入项目文件夹里,打开cmd,运行:
npm run serve
,我们的项目就启动起来了。
二. 实例化
打开我们项目main.js
文件,我们可以看到vue3一些变化:
- 使用
createApp
函数创建vue实例, - 使用
createRouter
函数创建vue路由实例, - 使用``
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import ElementPlus from 'element-plus'
import 'element-plus/lib/theme-chalk/index.css'
import './assets/reset.css'
createApp(App).use(store).use(router).use(ElementPlus).mount('#app')
三. Composition Api
Composition Api是整个vue3核心。在vue2.x的版本,采用的是options的设计,在vue3 composition的里,所有的代码逻辑都放在了setup函数里,所需要的模块也都是按需引入,并且setup函数里也不在有this;
- reactive & ref,定义响应式数据,这两者的区别在于reactive是用来定义对象型数据的响应式,ref是用来定义基础数据的响应式。
import {reactive, ref, toRefs} from 'vue'
export default{
setup(){
const state = reactive({ // 定义对象响应式数据
obj: {id: 1, name: 'tom', hooby: 'sing'},
arr: ['red', 'yellow', 'blue', 'green']
})
const num = ref(99) // 定义基础类型响应式数据
return{
...toRefs(state),
num
}
}
}
- computed计算属性,和2.x语法基本一致,同样支持get,set的对象语法;
import {reactive, computed, toRefs} from 'vue'
export default {
setup(){
const state = reactive({
totalNum: computed(() => { // 默认get语法
return 2 + 2
}),
color: computed({ // 对象语法
get(){
return 'red'
},
set(newVal){
if (newVal !== 'red') {
return 'red'
} else {
return 'bule'
}
}
})
})
return {
...toRefs(state)
}
}
}
- watch & watchEffect监听属性,watch的变化,一是不支持'obj.key.key'的写法了,二是支持监听多个对象,同时新增了个watchEffect这个属性,watchEffect这个属性监听时不需要指定的监听对象,加载属性所在页面,该监听属性就立即执行;
import {reactive, watch, watchEffect, toRefs} from 'vue'
export default {
setup() {
const state = reactive({
pageName: 'watch study',
num2: 0,
num1: 0,
})
watch(() => state.color, (newVal, oldVal) => { // 监听单个数据
console.log('newVal', newVal)
console.log('oldVal', oldVal)
} )
const stopWatch = watchEffect(() => { // 监听单个属性,不需要指定监听属性
console.log('newVal', state.num2)
console.log('oldVal', state.num2)
})
watch([() => state.num1, () => state.num2], ([newNum1, newNum2], [oldNum1, oldNum2]) => { // 监听多个数据
console.log('new num1', newNum1, 'old num1', oldNum1)
console.log('new num2', newNum2, 'old num2', oldNum2)
})
return {
...toRefs(state)
}
}
- 生命周期 onBeforeMount, onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount, onUnmounted, onErrorCaptured,vue2的beforeCreate和created替换成了setup;
onBeforeMount(() => {
console.log('component is onBeforeMount')
})
onMounted(() => {
console.log('component is onMounted')
})
onBeforeUpdate(() => {
console.log('component is onBeforeUpdate')
})
onUpdated(() => {
console.log('component is onUpdated')
})
onBeforeUnmount(() => {
console.log('component is onBeforeUnmount')
})
onUnmounted(() => {
console.log('component is onUnmounted')
})
onErrorCaptured(() => {
console.log('component is onErrorCaptured')
})
- getCurrentInstance, 返回自身实例,在vue3的setup函数里,this被取消了,定义成了undefined,但是提供了
getCurrentInstance
方法,该方法可以返回当前模块实例。
import {getCurrentInstance} from 'vue'
export default{
setup(){
const $this = getCurrentInstance() // 获取当前实例
return {}
}
}
在控制台输出,打开ctx这个属性,就能看见你定义的数据和方法,包括inject注入和mixin混入的数据和方法了
- readonly只读属性,通过字面意思的理解,就是readonly返回的数据就是只读,不可以操作。
import {readonly} from 'vue'
export default {
setup() {
const pageName = readonly('页面名称')
return {
pageName // 模板里使用就可以了
}
}
}
- provide/Inject注入;父辈组件向子辈组件,孙子辈组件传递数据的一种方式。该方法可以很好的用来封装我们的私有公共方法,通过provide注入传递给所有子组件使用。
// 父辈组件
import {provide} from 'vue'
export default {
setup() {
provide({ // 注入数据
'testProvide': 'testProvide',
})
}
}
// 子辈组件
import {inject} from 'vue'
export default {
setup() {
let testProvide = inject('testProject') // 获取父辈组件注入的数据
}
}
组件通信
vue3组件通信略有变化,主要是体现在应用上的改变。先说第一种最常用的传值方式,props
传值:
` // 父组件使用子组件方式不变,传递值的方式同样还是使用 v-bind方式,重点是子组件获取props的变化 // 因为vue3里的this不在是像vue2里的组件实例对象,你要使用传入的props的值,就依靠setup的第一个参数
props: {
testParams: {
type: Object,
default: {}
}
},
setup(props, context) {// 子组件setup函数的第一个参数,就是props传入的值
let state = reactive({
name: '子组件',
})
let methods = {
// 子组件的方法里获取传入的props,原来的vue2就是this.testParams,现在采用setup的第一个参数
testFn() {
console.log(props.testParams)
}
}
}
`
父组件获取子组件实例的变化,在vue2当中,获取子组件实例直接this.$refs.child
就搞定了,在vue3当中,略有变化:
`
import {ref, reactive, toRefs} from 'vue' // 必须引入ref
setup() {
// 注意 这个child变量,必须和子组件上的ref的值保持一致
const child = ref() // 这个就是获取到子组件的实例,child变量必须在setup返回的对象中注册
function testFn(){
console.log(child.value.name)// 使用,假设这个child子组件的data里有name这个数据,那么你就需要使用这个格式
}
return {
child,
testFn
}
}
`
总结概述
vue3整体的核心变化在于compostiton Api的改变,所有的数据方法都集成在setup函数体里,其他一些细节的变化都是应用层使用的变化,后续在补充其他应用上的变化。