vue3快速上手
vue3已经发布了很长的一段时间,不爱学习的我姗姗来迟
vue3的简单介绍
- vue3中全部采用函数式写法,替换了原来类的写法
- vue3移除了生命周期函数、data、watch、computed、methods等vue2中的用法
- 去除了 this 和 filter(api)
- vue3兼容vue2,简而言之,在vue3中可以同时存在vue2和vue3两种写法
- vue3中引入了setup,在methods(vue2)中定义的方法和在setup中返回中的方法,一定不要同名,否则抛出错误;data(vue2)中定义的数据会覆盖setup中返回的同名数据
- vue3用proxy实现数据代理,仅代理第一层数据,避免了深层递归,提高了组件渲染性能
- vue3中支持多个根节点
setup函数
参数:
- props:父组件传入的值或者函数
- context:上下文,包含的属性:root、parent、refs、attrs、listeners、isServer、ssrContext、emit
在控制台中输出:
setup(props,context){
console.log(props)
console.log(context)
}
setup能做什么?
- 1、创建响应式数据,setup中return的数据可以在template中使用,与data中定义的数据类似,vue3中取消了data得写法
- 2、定义函数
- 3、引入的方式调用生命周期函数,如:onMounted(() => {console.log(‘组件挂载1’)})
- 4、return响应式数据,template可以调用
一、创建响应式数据:ref
注意:在setup中使用ref定义响应式数据,在setup中使用该数据,需要通过 .value 的形式获取值,return出去之后,在template中使用,无须 .value
如下:
<template>
<h1>name:{{name}},age:{{age}}</h1>
<button @click="ageChange">年龄增加</button>
</template>
<script>
import { ref } from '@vue/reactivity'
export default {
setup(props,context){
console.log(props)
console.log(context)
//创建响应式数据
let name = ref("张三")
let age = ref(18)
//创建一个方法,类似于在methods中定义
const ageChange = () => {
age.value++
}
return {
name,
age,
ageChange
}
}
}
</script>
二、数据绑定:reactive
reactive中传递的是一个对象,返回的是一个proxy对象,使用toRefs对proxy对象解构,为了更好的在template中使用
注意:reactive一般需要通过toRefs解构在return
如下:
<template>
<input style="border:1px solid red" type="text" v-model="inputValue">
<br>
<button @click="addToDo">添加</button>
<ul>
<li v-for="(item,index) of todoList" :key="index">
{{item}}
</li>
</ul>
</template>
<script>
import { reactive, toRefs } from '@vue/reactivity'
export default {
setup(props,context){
//创建数据绑定:reactive
const data = reactive({
inputValue:'',
todoList:[]
})
const addToDo = () => {
data.todoList.push(data.inputValue)
data.inputValue = ''
}
return {
...toRefs(data), //通过toRef把data变成一个响应式数据
addToDo
}
//等同于
// return {
// inputValue,
// todoList,
// addToDo
// }
}
}
</script>
三、生命周期:
在setup中生命周期函数都变成了回调函数,在setup中可以使用多个生命周期函数
setup(){
onMounted(() => {
console.log('组件挂载1');
});
onMounted(() => {
console.log('组件挂载2');
});
onUnmounted(() => {
console.log('组件卸载');
});
onUpdated(() => {
console.log('组件更新');
});
onBeforeUpdate(() => {
console.log('组件将要更新');
});
onActivated(() => {
console.log('keepAlive 组件 激活');
});
onDeactivated(() => {
console.log('keepAlive 组件 非激活');
});
return {};
}
生命周期的总结:
在vue3中使用setup取代了beforeCreate和created生命周期
Vue2.0 | Vue3.0 |
---|---|
beforeCreate | setup |
created | setup |
beforeMount | onBeforeMount |
mounted | onMounted |
beforeUpdate | onBeforeUpdate |
updated | onUpdated |
beforeDestroy | onBeforeUnmount |
destroyed | onUnmounted |
errorCaptured | onErrorCaptured |
四、计算属性 computed:
在setup中使用computed,computed变成了一个函数,传递一个回调函数,当依赖的数据发生变化,就会执行回调函数
注意:在setup中要使用computed包装的值,需要使用 .value 获取,在template中无须如此
setup(){
//数据绑定
const data = reactive({
a:3,
b:4
})
//计算属性
const sum = computed(() => {
return data.a + data.b
})
//setup中使用sum的值
console.log(sum.value)
return {
sum
}
}
五、侦听器watch:
watch变成函数的写法,用法和vue2相同
watch参数:
参数1:需要侦听的数据,可以是单个数据,可以通过数组同时侦听多个数据
参数2:当侦听的数据发生变化时,执行的方法
<template>
<input style="border:1px solid red" type="text" v-model="newValue1">
<br>
<input style="border:1px solid red" type="text" v-model="newValue2">
</template>
<script>
import { reactive, toRefs } from '@vue/reactivity'
import { computed, watch } from '@vue/runtime-core'
export default {
setup(){
const state = reactive({
newValue1:"",
newValue2:""
})
//通过 () => state.newValue1 返回state.newValue1的值
//监听单个
watch(
() => state.newValue1,
(newVal,oldVal)=>{
console.log(newVal,oldVal)
}
)
//监听多个
watch(
() => [state.newValue1,state.newValue2],
([newVal1,newVal2],[oldVal1,oldVal2]) => {
console.log(newVal1)
console.log(newVal2)
console.log(oldVal1)
console.log(oldVal2)
}
)
return {
...toRefs(state)
}
}
}
</script>
六、watchEffect (新增的方法):
watchEffect中传递一个回调函数,回调函数中依赖的数据发生变化时,会立即执行函数
响应式地跟踪函数中引用的响应式数据,当响应式数据改变时,会重新执行函数
const count = ref(0)
//当count发生变化时,立即执行回调函数
watchEffect(() => console.log(count.value))
七、vue-router:
import {useRoute, useRouter} from 'vue-router'
export default {
setup(){
const route = useRoute() //类似于this.$route 局部,query、param都可以使用
const router = useRouter() //类似于this.$router 全局,push、replace都可以使用
console.log(route,router)
}
}
八、vuex:
import {useStore} from 'vuex'
export default {
setup(){
const store = useStore();
console.log(store)
console.log(store.getters.getCount) //获取store的值
store.dispatch() // 通过store对象来dispatch 派发异步任务,执行actions中的方法
store.commit() // commit 修改store数据,执行mutations中的方法
}
}
九、依赖注入:provide、inject
存入provide的值,在该组件的父类或者子类中可以通过inject获取
provide('age',num)
provide('name',"张三")
//在子组件或者父组件中使用inject获取
const name = inject("name")
const age = inject("age")
十、实验性写法:setup
把setup放到 script 这个标签中,就无须 return 也可以在 template 中使用,简而言之,使用这种写法,会自动return,既在template中可以使用
主要的一点是:
获取上下文:const {proxy} = getCurrentInstance(),类似于vue2中的this
<template>
<h1>name: {{name}},age:{{age}}</h1>
</template>
<script setup>
import { defineProps, getCurrentInstance, inject, onMounted } from '@vue/runtime-core'
//获取上下文,类似于vue2中的this,this.$Dialog
const {proxy} = getCurrentInstance()
//生命周期
onMounted(()=>{
console.log(proxy)
})
//定义props
defineProps({
name:{
type:String,
default:'null'
},
age:{
type:Number,
default:18
}
})
</script>
vue3中的一些小细节:
1、setup是vue3中所有api的入口和出口
2、在setup中你可以使用所有的api,包含:生命周期、computed、watch、vuex、router
3、在vue3中去掉了vue2中的data的写法,用setup中return的值来为template绑定值value
4、如果return的值为常量,便不是响应式数据
5、this.$emit 用 context.emit 方法来替代
6、style动态变量注入(SFC)
SFC样式使用方法:在js中定义一个响应式数据,在style中只需要通过v-bind获取即可;如下:
<script setup>
const color = 'red'
</script>
<style>
.main{
background-color: v-bind(color)
}
</style>