Vue3中的新增点

147 阅读3分钟

Vue3.x中的新增点

1、多根节点组件

在Vue 3中,组件现在正式支持多根节点组件,即片段!

<template>
  <header>...</header>
  <main>...</main>
  <footer>...</footer>
</template>

2、Teleport 传送

Teleport提供了一种的方法,使我们可以控制要在DOM中哪个父对象下呈现HTML,而不必求助于全局状态或将其拆分为两个部分。

props 属性值
  1. to [string] 必须的属性 必须是有效的查询选择器或HTMLElement 指定将内容移动到的目标元素
<teleport to="#some-id">
    <test />
</teleport>
<teleport to=".some-class">
    <test />
</teleport>
<teleport to="[data-teleport]">
    <test />
</teleport>
  1. 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没有
beforeMountonBeforeMount
mountedonMounted
beforeUpdateonBeforeUpdate
updatedonUpdated
beforeUnmountonBeforeUnmount
unmountedonUnmounted
errorCapturedonErrorCaptured
renderTrackedonRenderTracked
renderTriggeredonRenderTriggered

由于setup是围绕beforeCreate和created生命周期挂钩运行的,因此您无需显式定义它们。换句话说,应该在这些钩子中编写的任何代码都应直接在setup函数中编写。

jsx
setup() {
    const root = ref(null)
    return () => <div ref={root} />
}
2. watch监听

从 vue 中引入 watch 可以参考 第4点 Reactivity(反应性)

  1. 监听 ref 声明的 反应性数据
  2. 监听 reactive 声明的反应性数据
  3. 监听 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 生命周期钩子使用
  1. setup 的 onMounted 执行 在 整个组件的 mounted 之前
  2. setup 的 onMounted 执行 在 setup 同步组件执行之后
  3. 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>