Vue3.x中的新增点
1、多根节点组件
在Vue 3中,组件现在正式支持多根节点组件,即片段!
<template>
<header>...</header>
<main>...</main>
<footer>...</footer>
</template>
2、Teleport 传送
Teleport提供了一种的方法,使我们可以控制要在DOM中哪个父对象下呈现HTML,而不必求助于全局状态或将其拆分为两个部分。
props 属性值
- to [string] 必须的属性 必须是有效的查询选择器或HTMLElement 指定将内容移动到的目标元素
<teleport to="#some-id">
<test />
</teleport>
<teleport to=".some-class">
<test />
</teleport>
<teleport to="[data-teleport]">
<test />
</teleport>
- disabled [boolean] 可用于禁用的功能
可以动态渲染到具体的位置
<teleport to="body" :disabled="displayVideoInline">
<video src="my-movie.mp4">
</teleport>
3、Composition API
import {ref, reactive, watch, computed, reactive, toRefs, createApp} from 'vue'
1. setup
要开始使用Composition API,我们首先需要一个可以实际使用它的地方。在Vue组件中,我们将此位置称为setup。
setup执行时尚未创建组件实例,所以不能使用this,此时this 为 undefined。除了props,无法访问组件中声明的任何data、computed、methods。
参数 (props, context)
// props 父组件传过来的props props是具有反应性的(传入新的props时会自动更新)
// context {attrs, emit, slots}
setup(props, context) {
console.log(context)
/**
* attrs: Proxy
* emit: (event, ...args) => instance.emit(event, ...args)
* slots: Proxy
*/
}
setup 生命周期钩子
| 钩子函数 | setup钩子 |
|---|---|
| beforeCreate | 没有 |
| created | 没有 |
| beforeMount | onBeforeMount |
| mounted | onMounted |
| beforeUpdate | onBeforeUpdate |
| updated | onUpdated |
| beforeUnmount | onBeforeUnmount |
| unmounted | onUnmounted |
| errorCaptured | onErrorCaptured |
| renderTracked | onRenderTracked |
| renderTriggered | onRenderTriggered |
由于setup是围绕beforeCreate和created生命周期挂钩运行的,因此您无需显式定义它们。换句话说,应该在这些钩子中编写的任何代码都应直接在setup函数中编写。
jsx
setup() {
const root = ref(null)
return () => <div ref={root} />
}
2. watch监听
从 vue 中引入 watch 可以参考 第4点 Reactivity(反应性)
- 监听 ref 声明的 反应性数据
- 监听 reactive 声明的反应性数据
- 监听 props 里面的数据
<script>
//一定使用之前引入
import {ref, watch} from 'vue'
setup(props) {
//监听 ref 数据
let count = ref(0)
watch(count, (val, old) => {
// 新数据、老数据
})
//监听 reactive 数据 对象
let person = reactive({
age: 18
})
watch(() => person.age, (val, old) => {
//新数据、老数据
})
//监听 reactive 数据 数组
let arr = reactive([1, 2, 3])
watch(arr, (val, old) => {
//新数据、老数据
})
//监听 props 的数据 加入props传了一个 testkey
watch(() => props.testkey, () => {
})
//要注意 return
return {
count,
person,
arr
}
}
</script>
3. computed 计算属性
从 vue 中引入 computed
<script>
import {ref, computed} from 'vue'
setup(props) {
let count = ref(0)
//当前组件的计算属性
let countCom = computed(() => {
return count.value * 2
})
//props传进来的计算属性
let countCom2 = computed(() => {
return props.propsKey * 2
})
}
</script>
4. setup 生命周期钩子使用
- setup 的 onMounted 执行 在 整个组件的 mounted 之前
- setup 的 onMounted 执行 在 setup 同步组件执行之后
- setup 的 onMounted 里面以及 setup 不能使用this
<script>
import {onMounted} from 'vue'
mounted () {
console.log(4)
},
setup () {
onMounted(() => {
console.log(1)
})
console.log(2)
setTimeout(() => {
console.log(3)
}, 0)
//打印顺序
// 2 1 4 3
onMounted(() => {
console.log(this)
})
//打印
//undefined
}
</script>
5. provide和inject
从 vue 中引入
父组件 provide
<script>
import {provide} from 'vue'
export default {
setup () {
provide('person', {
name: 'Bob',
age: 18
})
provide('city', '杭州')
}
}
</script>
子孙组件 inject
<script>
import {inject} from 'vue'
export default {
setup () {
//父辈组件 provide 的数据
let person = inject('person')
let city = inject('city')
//父辈组件 没有提供的值,给个默认值 不给默认为为 undefined 而且会有Vue warn提醒
let noProvide = inject('noProvide', 'noProvide hah')
}
}
</script>
provide 带有反应性的数据 父组件值修改,子孙组件值会对应的修改
<script>
import {provide} from 'vue'
export default {
setup () {
let city = ref('滨江')
provide('city', city)
}
}
</script>
provide 一个 函数
<script>
import {provide} from 'vue'
export default {
setup () {
let provideFun = () => {
console.log('provide fun')
}
provide('provideFun', provideFun)
}
}
</script>
4、Reactivity(反应性)
Vue最独特的功能之一是不引人注目的反应系统。
当您将纯JavaScript对象作为data选项传递给应用程序或组件实例时,Vue将遍历其所有属性,并使用带有getter和setter的处理程序将它们转换为Proxies
- 跟踪更改它的函数:在代理的getter中进行此操作 effect
- 触发函数,以便它可以更新最终值:在代理中的setter中进行操作 trigger
声明反应性数据
一般使用 ref、reactive、readonly 来声明数据
- ref 声明基本类型
- reactive 声明引用类型
- readonly 声明只读引用类型
import { ref, reactive, readonly } from 'vue'
export default {
setup () {
// 一般用 ref 声明 基本 类型
// 用 reactive 声明 引用 类型
let count = ref(0) // 在 script 使用 count.value,在 template 使用 {{count}}
let state = reactive({
name: 'Bob'
}) // 在 script 使用 state.name, 在 template 使用 {{state.name}}
// 用 ref 声明 引用类型
let obj1 = ref({
count: 1
})
// 用 reactive 声明 基本 类型 警告⚠️ 可以正常使用,但是没有反应性
let num1 = reactive(10) //value cannot be made reactive: 10
// readonly
// readonly 和 reactive 一样,但是声明的是只读数据 声明基本类型和 reactive 一样警告提醒
let person = readonly({age: 18})
setTimeout(() => {
// 定时器 修改 警告 ⚠️
person.age = 10 // Set operation on key "age" failed: target is readonly
});
// 一定要return 才可以在 template 和 script 其他地方使用
return {
count,
state,
obj1
}
}
}
count打印出的数据
RefImpl {_rawValue: 0, _shallow: false, __v_isRef: true, _value: 0}
__v_isRef: true
_rawValue: 0
_shallow: false
_value: 0
value: 0
state打印出的数据
Proxy {name: "Bob"}
[[Handler]]: Object
deleteProperty: ƒ deleteProperty(target, key)
get: ƒ (target, key, receiver)
has: ƒ has(target, key)
ownKeys: ƒ ownKeys(target)
set: ƒ (target, key, value, receiver)
[[Target]]: Object
name: "Bob"
[[IsRevoked]]: false
obj1打印出的数据
RefImpl {_rawValue: {…}, _shallow: false, __v_isRef: true, _value: Proxy}
__v_isRef: true
_rawValue: {count: 1}
_shallow: false
_value: Proxy {count: 1}
value: Proxy
[[Handler]]: Object
[[Target]]: Object
count: 1
[[IsRevoked]]: false
num1打印的数据
10
template中使用
<!-- 使用ref定义的基本类型直接使用 -->
<!-- 使用reactive定义的引用类型直接.对应的属性 -->
<div class="vue3_pro">
count: {{count}}
state: {{state.name}}
</div>