注意事项:
Vue CLI
从 v4.5.0 开始,vue-cli
现在提供了内置选项,可在创建新项目时选择 Vue 3。现在可以升级 vue-cli
并运行 vue create
来创建 Vue 3 项目。
Vue Router
Vue Router 4.0 提供了 Vue 3 支持,并有许多非兼容的变更,详情见迁移指南。
Vuex
Vuex 4.0 提供了 Vue 3 支持,其 API 与 3.x 基本相同。唯一的非兼容变更是插件的安装方式
创建项目
在创建项目目录位置打开终端,输入:
vue create 项目名
选择配置要素
根据开发需要选择需要的功能
选择vue3版本
2.Vue3合成型API (Composition API) 理解
1.defineComponent函数
- defineComponent函数,只是对setup函数进行封装,使用defineComponent 构建应用及绑定事件
2.setup函数
- setup函数,它将接受两个参数:(props、context(包含attrs、slots、emit))
- attrs: 获取当前组件标签上所有没有通过
props
接收的属性的对象, 相当于this.$attrs
- slots: 包含所有传入的插槽内容的对象, 相当于
this.$slots
- emit: 用来分发自定义事件的函数, 相当于
this.$emit
setup函数第一个参数props
是响应式的,当传入新的 prop 时,它将被更新。但是,因为props
是响应式的,你不能使用 ES6 解构,它会消除 prop 的响应性。- setup函数是处于 生命周期函数 beforeCreate 和 Created 两个钩子函数之前的函数
- setup函数与模板一起使用:需要返回一个对象 (在setup函数中定义的变量和方法最后都是需要 return 出去的 不然无法再模板中使用)
-
setup
是组合Composition API
中的入口函数,也是第一个要使用的函数。setup
只在初始化时执行一次,所有的Composition API
函数都在此使用。 - 可以使用setup的俩个参数实现组件通信,代码如下:
父组件代码:
<template>
<div>
<p>{{ss}}</p>
<son :fatherSend="data" @resSon="get"></son>
</div>
</template>
<script>
import son from "@/components/son"
import { defineComponent,ref } from "vue"
export default defineComponent({
components:{ son },
setup(props,context){
let data='父传子数据'
console.log(props)
console.log(context)
let msg="hello"
var ss=ref("hello")
const get=(arg)=>{
ss.value=arg
}
return{
msg,
data,
ss,
get,
}
}
})
</script>
<style>
</style>
子组件代码:
<template>
<div>
{{fatherSend}}
<button type="button" @click="sonSend">子传父</button>
</div>
</template>
<script>
export default {
props:[ "fatherSend" ],
setup(props,context){//可以将context换成{emit}
const sonSend=()=>{
context.emit("resSon",'子传父数据')
// 将context换成{emit}可以这样进行组件通信 emit("resSon",'子传父数据')
}
return {
sonSend
}
}
}
</script>
<style>
</style>
3.ref函数
- 作用:接受简单类型或者复杂类型的值传入并返回一个响应式且可变的ref对象
- 使用步骤:从vue框架导出ref函数,在setup里面调用ref函数并传入数据, 把ref函数调用完毕的返回值以对象的形式返回出去,
- 注意:在setup函数中使用ref结果,需要通过.value 访问,模板中使用不需要加.value
- 实例:在上面setup函数组件通信中的父组件中有使用到
4.toRefs函数
- 作用:简化响应式对象的使用
- 经过reactive函数处理之后返回的对象,如果给这个对象解构或者展开,会让数据丢失响应式的能力,为了解决这个问题需要引入toRefs函数,使用 toRefs函数 可以保证该对象展开的每个属性都是响应式的
- 实例如下:
<template>
<div>
<p>{{ num }}</p>
<button type="button" @click="get">翻倍</button>
</div>
</template>
<script>
import { reactive, toRefs } from 'vue';
export default {
setup() {
const data = reactive({
num: 2,
get: () => {
data.num = data.num * 2;
}
});
return {
...toRefs(data)
};
}
};
</script>
<style></style>
5.reactive函数
- 作用:reactive是一个函数,接收一个普通的对象传入,把对象数据转化为响应式对象并返回
- 在Vue2中响应式数据是通过defineProperty来实现的
- 而在Vue3响应式数据是通过ES6的Proxy来实现的
- 注意:reactive参数必须是对象
6. computed计算属性函数
- 作用:根据现有响应式数据经过一定的计算得到全新的数据。
- 特性:依赖的响应式数据一旦发生变化后描绘立刻重新求值
- 实例如下:
<template>
<div>
<p>{{ num }}</p>
<button type="button" @click="get">翻倍</button>
<p>{{sum}}</p>
</div>
</template>
<script>
import { reactive, toRefs,computed} from 'vue';
export default {
setup() {
const data = reactive({
num: 2,
get: () => {
data.num = data.num * 2;
},
sum:computed(() => {//sum通过计算得到对应的值 注意return返回值
return data.num+3
})
});
return {
...toRefs(data)
};
}
};
</script>
<style></style>
7.watch监听函数
- 作用:基于响应式数据的变化执行回调逻辑,和vue2的watch的功能完全一致
- watch函数第一个参数为监听的对象,第二个参数为函数,函数里面有俩个参数分别代表旧的值和新的值,第三个参数为一个对象,在里面配置是否开启立刻执行{immediate:true}或者深度监听{deep:true}
- 最佳实现:如果想要监听一个比较深层次的对象属性,建议直接通过点语法监听具体属性,而不是直接开启深度监听
- 注意:只能监听ref,reactive,getter/effect 函数
- 实例如下:
<template>
<div>
<input type="text" v-model="val" />
<p>{{ val }}</p>
</div>
</template>
<script>
import { ref,watch } from 'vue';
export default {
setup() {
let val = ref('');
let listen=watch(val,(newValue,oldValue)=>{
console.log("length",val.value.length)
console.log("old",oldValue) //之前的数据
console.log("new",newValue) //当前的数据
})
return { val,listen };
}
};
</script>
<style></style>
- 用到深度监听的实例:
<template>
<div>
<input type="text" v-model="val" />
<p><input type="text" v-model="vals" /></p>
<button :disabled="isdis">按钮</button>
<p>{{ val }}</p>
<p>{{ vals }}</p>
</div>
</template>
<script>
import { ref, watch, reactive, toRefs } from 'vue';
export default {
setup() {
let isdis = ref(true);
let form = reactive({
val: '',
vals: ''
});
let listen = watch(
() => {
return form;
},
() => {
if (form.val.length != 0 && form.vals.length != 0) {
isdis.value = false;
} else {
isdis.value = true;
}
},
{
deep: true //开启深度监听
}
);
return { ...toRefs(form), listen, isdis };
}
};
</script>
<style></style>
8.watchEffect函数
- 作用:每次初始化时会执行一次回调函数来自动获取依赖
- 特性:无法获取到原值,只能得到变化后的值,不需要手动传入依赖。类似computed计算属性,依赖发生改变才会执行
- 实例如下:
<template>
<div>
<input type="text" v-model="val">
</div>
</template>
<script>
import {watchEffect,ref} from "vue"
export default {
setup(){
let val=ref("")
let res=watchEffect(()=>{
console.log(val.value)
})
return {val,res}
}
}
</script>
<style>
</style>
9.生命周期函数
- setup() :开始创建组件之前,在beforeCreate和created之前执行。创建的是data和method
- onBeforeMount() : 组件挂载到节点上之前执行的函数。
- onMounted() : 组件挂载完成后执行的函数。
- onBeforeUpdate(): 组件更新之前执行的函数。
- onUpdated(): 组件更新完成之后执行的函数。
- onBeforeUnmount(): 组件卸载之前执行的函数。
- onUnmounted(): 组件卸载完成后执行的函数
- 若组件被
<keep-alive>
包含,则多出下面两个钩子函数。 - onActivated(): 被包含在中的组件,会多出两个生命周期钩子函数。被激活时执行 。
- onDeactivated(): 比如从 A组件,切换到 B 组件,A 组件消失时执行。
- 实例如下:
let {ref, onBeforeMount, onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount, onUnmounted, onErrorCaptured, onRenderTracked, onRenderTriggered} = Vue;
export default {
// setup相当于vue2中的beforeCreate和created,并且在两者之前执行
setup(){
let test = ref('测试')
// 挂载开始之前被调用
onBeforeMount(()=>{
console.log('onBeforeMount',test)
})
// 实例被挂载后调用,不会保证所有的子组件也被挂载完
onMounted(()=>{
console.log('onMounted',test)
})
// DOM更新前
onBeforeUpdate(()=>{
console.log('onBeforeUpdate',test)
})
// DOM更新后,不会保证所有的子组件也都一起被重绘
onUpdated(()=>{
console.log('onUpdated', test)
})
// 卸载组件实例之前,此时实例仍然是完全正常的
onBeforeUnmount(()=>{
console.log('onBeforeUnmount', test)
})
// 卸载组件实例后调用。调用此钩子时,组件实例的所有指令都被解除绑定,所有事件侦听器都被移除,所有子组件实例被卸载。
onUnmounted(()=>{
console.log('onUnmounted', test)
})
// 当捕获一个来自子孙组件的错误时被调用
onErrorCaptured(()=>{
console.log('onErrorCaptured',test)
})
// 跟踪虚拟 DOM 重新渲染时调用
onRenderTracked(()=>{
console.log('onRenderTracked',test)
})
// 当虚拟 DOM 重新渲染为 triggered.Similarly 为renderTracked,接收 debugger event 作为参数。此事件告诉你是什么操作触发了重新渲染,以及该操作的目标对象和键。
onRenderTriggered(()=>{
console.log('onRenderTriggered',test)
})
return {test};
}
}