Vue3.X笔记总结
一、Vue3.X与Vue2.X区别
1.全局组件的区别
vue2.X使用new Vue
创建App
vue3.X使用createApp
创建App
import { createApp } from 'vue'
const app = createApp({
/* 根组件选项 */
})
2.选项式API和组合式API
选项式API:(options
)分模块,变量在Data模块,方法在Methods模块中等等,每一模块为一个对象
组合式API:(composition
)“分堆”,所有变量和方法在“一堆”,按照功能“分堆”
二、Vue3.X常用总结
1、Teleport组件
<teleport to ="body"></teleport>
将内容渲染到指定标签内,to="body"
就是将内容渲染到body中,而不是在app
全局组件中。
2、v-once
指令
只绑定一次,如果是双向绑定的变量,也只会改变一次
3、.exact修饰符(精确控制)
<input type="text" @keyup.enter.exact="addNum" v-model="mes">
<p v-for="(x,y) in arr" :key="y">{{x}}</p>
如果不加exact
精确修饰符,除了按enter
会触发事件外,
按ctrl+enter
和alt+enter
等都会触发事件,
加了exact
之后就会精确到,按enter
才会触发事件
注:
(1)vue3.X版本中,for循环要加key属性唯一标识
(2)vue3.X版本中不支持使用键码事件修饰符
(3)新增鼠标按键修饰符
4、vue3.X中可以包含多个根节点
vue2.X版本中的template
模板中只允许有一个根节点
5、状态驱动的CSS
在CSS的style中可以通过v-bind()
函数关联到组件的data()
中的变量
<h1 class="mycolor">user</h1>
<script>
data() {
return{
myc:'red'
}
}
</script>
<style>
.mycolor{
color:v-bind(myc)
}
</style>
6、组合式API
选项式API
与组合式API
区分示意图
选项式API:
https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/1bd101840df446c78d52e9c14711aae7~tplv-k3u1fbpfcp-zoom-in-crop-mark:1304:0:0:0.awebp
https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/568b0ced69f241d282cf2c512e4e5f33~tplv-k3u1fbpfcp-zoom-in-crop-mark:1304:0:0:0.awebp
组合式API:
https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/d05799744a6341fd908ec03e5916d7b6~tplv-k3u1fbpfcp-zoom-in-crop-mark:1304:0:0:0.awebp
1、组合式API的使用:
(1)setup()
入口函数
(2)ref()
函数:使用ref函数,可以使变量响应式改变
(3)变量.value
:改变变量值
(4)要将变量,函数在setup
最后通过return
返回,否则在HTML中无法使用
<script>
import {ref} from "vue";
export default{
//setup入口函数
setup(){
//通过ref绑定值,相当于Vue2.X中的data(){}
var flag=ref(true);
function tab1(){
//要想改变值,需要使用变量.value
flag.value=true
}
function tab2(){
flag.value=false
}
var bgColor=ref('red')
function tab3(){
bgColor.value='red'
}
function tab4(){
bgColor.value='green'
}
//要将变量,函数返回
return{flag,bgColor,tab1,tab2,tab3,tab4}
}
}
</script>
setup入口函数:
(1) setup入口函数
\1. setup 函数是一个新的组件选项,作为组件中组合式API 的起点(入口)
\2. setup 中不能使用 this, this 指向 undefined
\3. setup函数只会在组件初始化的时候执行一次
\4. setup函数在beforeCreate生命周期钩子执行之前执行
<script>
import {ref} from 'vue';
export default {
setup(){
let mes=ref("lyl123");
function con() {
mes.value = "lyl"+mes.value;
}
return {mes,con}
return {mes}
}
}
</script>
(2)ref 函数
ref是一个函数,
接受一个简单类型或者复杂类型的传入并返回一个响应式且可变的ref对象;
在setup函数中使用ref结果,需要通过.value 访问,
模板template中使用不需要加.value
<template>
<input type="text" v-model="user"/>
<h1>{{user}}</h1>
</template>
<script>
import {ref} from "vue";
export default{
setup(){
var user=ref("zhang")
user.value='100'
return {user}
}
}
</script>
(3)reactive函数
reactive是一个对象,接收一个普通的对象传入,把对象数据转化为响应式对象
<input type="text" v-model="user.name"/>
<h1>{{user.name}}</h1>
<script>
import {reactive} from "vue";
export default{
setup(){
var user=reactive({
name:"zhang",
age:10
})
return{user}
}
}
</script>
(4)toRefs函数
经过reactive函数处理之后返回的对象,如果给这个对象解构或者展开,会让数据丢失响应式的能力,为了解决这个问题需要引入toRefs函数,使用 toRefs函数 可以保证该对象展开的每个属性都是响应式的
对于使用reactive定义的对象,使用扩展运算符…,解构之后,让其仍然是响应式的变量,toRefs()
函数写在return
中
...toRefs(user)
<input type="text" v-model="name"/>
<h1>{{name}}</h1>
<h1>{{age}}</h1>
<script>
import {reactive,toRefs} from "vue";
export default{
setup(){
var user=reactive({
name:"zhang",
age:10
})
return{...toRefs(user)}
}
}
</script>
(5)computed
在setup函数中使用计算属性函数(依赖)
用法:
使用前需要使用import导入
将computed绑定到一个变量上
import {ref,computed} from 'vue';
export default {
setup() {
let arr = ref([10, 20, 30, 40])
//将computed绑定到一个变量
let newArr = computed(() => {
return arr.value.filter(v => v > 30)
})
return {arr,newArr}
}
}
(6)watch监听器
和vue2.X中的watch的功能完全一致
用法:
先通过import引入
直接在setup()函数中写 **watch()**函数
1)普通监听(两种写法)
<script>
setup(){
var inp=ref("");
var re = ref("");
//写法1
watch(inp,()=>{
re.value = inp.value
})
//写法2
watch(()=>{
reutrn inp.value
},()=>{
re.value = inp.value;
})
}
</script>
2)开启立即执行(配置immediate属性)
因为watch默认状态下,只有监听数据发生变化才会执行回调,如果你需要在一上来的时候就执行一次,则需要配置immediate属性为true
注:
在watch函数的第三个参数中配置额外属性
<script>
watch(inp,()=>{
re.value='hello '+inp.value
},{immediate:true})
</script>
3)开启深度监听(配置deep属性)
当我们监听的数据为一个对象的时候,默认状态下,对象内部的属性发生变化是不会引起回调函数执行的,如果想让对象下面所有属性都能得到监听,需要开启deep配置为true;或者直接监听对象中要变化的属性也可以,
但是直接监听对象中要变化的属性,不被建议
<script>
watch(()=>{
return inp
},()=>{
console.log('执行了')
},{deep:true})
</script>
(7)vue3.X的生命周期函数
与vue2.x的区分,vue3.x的钩子函数都加上了on
前缀
使用:
1)先引入: 先从vue中导入以on打头的生命周期钩子函数
2)在setup函数中调用生命周期函数并传入回调函数
3)生命周期钩子函数可以调用多次
<script>
//先引入
import {onMounted} from "vue";
export default{
setup(){
onMounted(function(){
console.log("挂在后")
})
}
}
</script>
(8)父子通信(父子组件传参)
注:
调用组件和vue2.X版本一样,
1)先引入组件路径
2)和setup()
入口函数同级,写components:{}
在vue3的组合式API中,父传子的基础思想完全一样,依旧为:父传子是通过prop进行传入,子传父通过调用自定义事件完成;
**a)**setup函数提供俩个参数,第一个参数为props,第二个参数为一个对象context
**b)**props为一个对象,内部包含了父组件传递过来的所有prop数据,context对象包含了attrs,slots, emit属性,其中的emit可以触发自定义事件的执行从而完成子传父
使用:
(1)子组件接收参数仍然使用props
(2)子组件使用父组件中传递的函数,要通过context对象中的emit
调用
父组件:
<AboutChild :mes="mes" @addNum="addNum">
</AboutChild>
子组件:
<template>
<div>
{{mes}}
<p @click="add">点击</p>
</div>
</template>
<script>
import {ref,onMounted} from "vue";
export default{
//接收mes变量
props:['mes'],
//{emit}就是将context对象进行解构赋值的简便写法
setup(props,{emit}) {
function add(){
emit('addNum');
}
return{add}
}
}
</script>
(9)Vue3.X插槽slot
1)具名slot
vue3.X中的具名slot,使用template
包裹起来,再通过#
具名
父组件:
#default
为默认,如果不用#
指定,则子组件也无法显示
<template>
<div class="about">
<!--调用子组件-->
<AboutChild :mes="mes">
<template #default>
<p>我是插槽p</p>
</template>
<template #b1>
<b>我是插槽b</b>
</template>
</AboutChild>
</div>
</template>
子组件:
<template>
<div>
<!--不写name则接收默认default的slot-->
<slot></slot>
<slot name="b1"></slot>
</div>
</template>
2)让slot分发的内容为变量
父组件:
父组件中使用v-slot="name"
此处的name为一个对象,是子组件所有的slot的name
<template>
<div class="about">
<AboutChild v-slot="a">
{{a.user}}
</AboutChild>
</div>
</template>
子组件:
子组件中通过name='值'
传值,进行分发
(将子组件中的变量传递到父组件中,进行分发最后显示在子组件中)
<template>
<div>
<slot user="user"></slot>
<slot age="19"></slot>
</div>
</template>
(10)provide和inject
使用provide
和inject
可以跨多层组件进行数据传递,更加方便
通常我们使用props进行父子之间的数据传递,但是如果组件嵌套层级较深,一层一层往下传递将会变的非常繁琐,那么可以使用 provide 和 inject,它们配合起来可以方便的完成跨层传递数据
用法:
a. 顶层组件在setup方法中使用provide函数提供数据
b. 任何底层组件在setup方法中使用inject函数获取数据
父组件:
<script>
setup(){
var mes=ref("i am 父")
//provide传递参数
provide('mes',mes)
return{mes}
}
</script>
可以在孙子组件中,通过inject
接收参数
孙子组件:
<script>
setup(prop,{emit}){
var mymes=inject("mes")
return{mymes}
}
</script>