Vue3新特性学习笔记

Vue3新特性

Vue3新增了很多新的特性,vue3将会对vue2进行向下兼容,因此不必担心因为使用vue3后vue2的特性不能够使用。

1.setup

  • setup()函数是vue3中,专门为组件提供的新属性。它为我们使用Vue3的composition API 新特性提供了统一的入口。
    1.1 执行时机
  • setup函数会在beforeCreate之后,created之前执行!!!!
    1.2. 将代码片显示选择的高亮样式
  • props中定义当前组件允许外界传递过来的参数名称:props{p1:String}
  • 通过setup函数的第一个形参,接收props数据:
setup(props){
console.log(props.p1)}

1.3. context
setup函数的第二个形参是一个上下文对象,这个上下文对象中包含了一些有用的属性,这些属性在vue 2.x 中需要通过this才能访问到,在vue 3.x中,它们的访问方式如下:

const MyComponent = {
setup(props,context){
context.attrs
context.slots
context.parent
context.root
context.refs
}
}

注意:在setup() 函数中无法访问到this !!!!!!!!!!!!

2reactive

reactive()函数接受一个普通对象,返回一个响应式的数据对象。
2.1基本用法
等价于vue 2.x 中的Vue.observable()函数,vue 3.x中提供了reactive()函数,用来创建响应式的数据对象,基本代码示例如下:

import{ reactive } from '@vue/composition-api'
//创建响应式数据对象,得到的state类似于vue 2.x中data()返回的响应式对象
const state=reactive({count : 0})

2.2定义响应式数据供template使用
按需导入reactive函数:

import{ reactive } from '@vue/composition-api'

setup()函数中调用reactive()函数,创建响应式数据对象:

setup(){
//创建响应式数据对象
const state = reactive({count :0})
//setup 函数中将响应式数据对象 return 出去,供template使用
return state
}

在template 中访问响应式数据:

<p> 当前的 count 值为:{{count}}p>

3.ref

3.1基本语法
ref() 函数用来根据给定的值创建一个响应式数据对象ref()函数调用的返回值是一个对象,这个对象只包含一个.value属性:

import { ref } from '@vue/composition-api'
//创建响应式数据对象count,初始值为0
const count =ref(0)
//如果要访问ref()创建出来的响应式数据对象的值, 必须通过.value属性才可以
console.log(count.value)//输出0
//让count 的值+1
count.value++

3.2在template中访问ref创建的响应式数据
setup()中创建响应式数据:

import { ref } from '@vue/composition-api'
setup() {
const count = ref(0)

return {
count,
name: ref('zs')
}
}

在template 中访问响应式数据:

<template>
<p>{{count}} --- {{name}}p>
template>

3.3在reactive 对象中访问ref创建的响应式数据
当把ref()创建出来的响应式数据对象,挂载到 reactive() 上时,会自动把响应式数据对象展开为原始的值,不需要通过.value就可以直接被访问,例如:

const count = ref(0)
const state = reactive({
 count 
})
console.log(state.count) //输出0
state.count++ //此处不需要通过 .value 就能直接访问原始值
console.log(count) //输出1

注意:新的ref会覆盖旧的ref,示例代码如下:

//创建ref并挂载到 reactive 中
const c1 = ref(0)
const state = reactive({
c1
})
//再次创建 ref, 命名为 c2
const c2 = ref(9)
state.c1 = c2
state.c1++

console.log(state.c1) //输出10
console.log(c2.value) //输出10
console.log(c1.value) //输出0

4. isRef

isRef() 用来判断某个值是否为 ref() 创建出来的对象;应用场景:当需要展开某个可能为 ref() 创建出来的值的时候,例如:

import{ isRef } from '@vue/compositon-api'

const unwrapped = isRef(foo) ? foo.value : foo

5.toRefs

toRefs() 函数可以将reactive()转换成普通的对象,只不过,这个对象上的每个属性节点,都是ref()类型的响应式数据,最常见的应用场景如下:

 import {toRefs} from 'vue'
  //定义响应式数据对象
   const state =reactive({
     count :0
   })
   //定义页面上可用的事件处理函数
   const increment = () =>{
     state.count++
   }
   //在 setup 中返回一个对象供页面使用
   //这个对象中可以包含响应式的数据,也可以包含事件处理函数
   return {
     //将state 上的每个属性,都转化为 ref 形式的响应式数据
     //对象中的扩展运算符(...)用于取出参数对象中的所有可遍历属性,拷贝到当前对象之中
    ...toRefs(state),
    //自增的事件处理函数
     increment
   }

页面上可以直接访问setup()中return出来的响应式数据:

<template>
  <div class="hello">
<p>当前的count值为:{{count}}p>
<button @click="increment">+button>
  div>
template>

computed计算属性

computed() 用来创建计算属性,computed()函数的返回值是一个ref的实例。使用computed之前需要按需导入:

import { computed } from '@vue/composition-api'

6.1创建只读计算属性
在调用 computed()函数期间,传入一个function 函数,可以得到一个只读的计算属性,示例代码如下:

//创建一个ref响应式数据
const count =ref(1)
//根据 count 的值,创建一个响应式的计算属性plusOne
//它会根据依赖的ref自动计算并返回一个新的ref
const plusOne = computed(() => count.value+1)

console.log(plusOne.value) //输出2
plusOne.value++ //error

6.2 创建可读可写的计算属性
在调用 computed() 函数期间,传入一个包含 getset 函数的对象,可以得到一个可读可写的计算属性,示例代码如下:

//创建一个ref响应式数据
const count = ref(1)
//创建一个computed 计算属性
/const plusOne = computed({
//取值函数
get:() => count.value+1
//赋值函数
set: val=>{
 count.value = val -1
}
})

//为计算属性赋值的操作,会触发set 函数
plusOne.value = 9
//触发 set 函数后,count 的值会被更新
console.log(count.value) //输出8

7.watch

watch()函数用来监视某些数据项的变化,从而触发某些特定的操作,使用之前需要按需导入:
一个简单的表格是这么创建的:

import { watch } from 'vue'

7.1基本用法

const count =ref(0)
//定义watch,只要count值变化,就会触发watch回调
//watch 会在创建时会自动调用一次
watch(() => console.log(count.value))
seTimeout(()=>{
count.value++
//输出1
},1000)

7.2监视指定的数据源
监视reactive类型的数据源:
//定义数据源

const state = reactive({count : 0})
//监视state.count 这个数据节点的变化
watch(
()=>state.count,
(count,prevCount)=>{
/*...*/
}
)

监视 ref 类型的数据源:

//定义数据源
const count = ref(0)
//指定要监视的数据源
watch(count,(count,prevCount)=>{
/*...*/
})

**7.3监视多个数据源
监视reactive类型的数据源:

const state = reactive({count :0,name:'zs'})

watch(
[()=>state.count, () => state.name], //Object.values(toRefs(state))
([count,name],[prevCount,prevName]) =>{
console.log(count) //新的 count 值
console.log(name) //新的name 值
console.log('-------------')
console.log(prevCount) //旧的 count 值
console.log(prevName) //旧的 name 值
},
{
lazy:true //在watch 被创建的时候,不执行回调函数中的代码
}
)
setTimeout(()=>{
state.count++
state.name='qs'
},1000)

监视 ref 类型的数据源:

const count = ref(0)
const name =ref('zs')

watch(
[count,name], //需要被监视的多个ref数据源
([count,name],[prevCount,prevName])=>{
console.log(count)
console.log(name)
console.log('------------')
console.log(prevCount)
console.log(prevName)
},
{
lazy:true
}
)
setTimeout(()=>{
count.value++
name.value='xxxxs'
},1000)

7.4清除监视
setup()函数内创建watch监视,会在当前组件被销毁的时候自动停止,如果想要明确地停止某个监视,可以调用watch()函数的返回值即可,语法如下:

//创建监视,并得到 停止函数
const stop =watch(()=>{
/*....*/
})

//调用停止函数,清除对应的监视
stop()

7.5 在watch中清除无效的异步任务
有时候,当被watch监视的值发生变化时,或watch本身stop之后,我们期望能够清除那些无效的异步任务,此时,watch回调函数中提供了一个cleanup
registrator function来执行清除的工作。这个清除函数会在如下情况下被调用:

  • watch 被重复执行了
  • watch 被强制 stop
    Template 中的代码示例如下:
/*template中的代码*/ <input type = 'text' v-model="keywords">

Script 中的代码示例如下:

//定义响应式数据 keywords
const keywords = ref('')

//异步任务:打印用户输入的关键词
const asyncPrint = val =>{
//延时 1秒后打印
return setTimeout(()=>{
console.log(val)
},1000)
}
//watch监听数据变化
watch(
[keywords],
(keywords,prevKeywords,onCleanup)=>{
//执行异步任务,并得到关闭异步任务的timerId
const timerId=asyncPrint(keywords)

//如果watch监听被重复执行了,则会先清除上次未完成的异步任务
onCleanup(()=>clearTimeout(timerId))
},
//watch 刚被创建的时候不执行
{lazy:true}
)
//把template 中需要的数据return 出去
return {
keywords
}

8.LifeCycle Hooks

新版的生命周期函数,可以按需导入到组件中,且只能在setup()函数中使用,代码示例如下:

import { onMounted, onUpdated, onUpdated,onUnmounted } from '@vue/composition-api'

const MyComponent = {
setup() {
onMounted(() =>{
console.log('mounted!')
})
onUpdated(()=>{
console.log('updated!')
})
onUnmounted( ()=>{
console.log('unmounted!')
})
}
}

下面的列表,是vue2.x的生命周期函数与新版Composition API之间的映射关系:

  • beforeCreate -> use setup()
  • created -> setup()
  • beforeMount -> onBeforeMount
  • mounted -> onMounted
  • beforeUpdate -> onBeforeUpdate
  • updated -> onUpdated
  • beforeDestroy -> onBeforeUnmount
  • destroyed -> onUnmounted
  • errorCaptured -> onErrorCaptured

provide & inject

provide()inject() 可以实现嵌套组件之间的数据传递。这两个函数只能在setup()函数中使用。父级组件中使用provide() 函数向下传递数据;子级组件中使用inject() 获取上层传递过来的数据。
9.1共享普通数据
App.vue根组件:

<template>
<div id="app">
<h1>App 根组件h1>
<hr />
<levelOne />
div>
template>

<script>
import LevelOne from './components/LevelOne'
//1.按需导入provide
import { provide } from '@vue/composition-api'

export default {
name: 'app',
setup(){
//2.App 根组件作为父级组件,通过Provide函数向子级组件共享数据(不限层级)
//provide('要共享数据名称','被共享的数据')
provide('globalColor','red')
},
components:{
LevelOne
}
}
script>

LevelOne.vue 组件:

<template>
<div>

<h3 :style="{color: themeColor}">Level Oneh3>
<hr />
<LevelTwo />
div>
template>
<script>
import LevelTwo from './LevelTwo'
//1. 按需导入inject
import { inject } from '@vue/composition-api'

export default {
setup() {
//2. 调用inject 函数时,通过指定的数据名称,获取到父级共享的数据
const themeColor = inject('globalColor')
// 3.把接收到的共享数据 return 给 Template 使用
return {
themeColor
}
},
compoents:{
LevelTwo
}
}
script>

LevelTwo.vue组件:

<template>
<div>

<h5 :style="{color: themeColor}">Level Twoh5>
div>
template>

<script>
// 1.按需导入inject
import { inject } from '@vue/composition-api'

export default {
setup() {
//2.调用 inject 函数时,通过指定的数据名称,获取到父级共享的数据
const themeColor = inject('globalColor')
//3. 把接收到的共享数据 return 给 Template使用
return{
themeColor
}
}
}
script>

9.2共享ref响应式数据
如下代码实现了点按钮切换主题颜色的功能,主要修改了 App.vue组件中的代码,LevelOne.vueLevelTwo.vue中的代码不受任何改变:

<template>
<div id="app">
<h1>App 根组件h1>


<button @click='themeColor="red"'>红色button>
<button @click='themeColor="blue"'>蓝色button>
<button @click='themeColor="orange"'>橘黄色button>

<hr />
<LevelOne />
div>
template>

<script>
import LeveOne from './components/LevelOne'
import { provide, ref } '@vue/composition-api'

export default {
name :"app",
setup(){
//定义ref响应式数据
const themeColor = ref('red')
//把ref数据通过provide提供给子组件使用
provide('globalColor',themeColor)
//setup中return 数据供当前组件的Template使用
return {
themeColor
}
},
components:{
LevelOne
}
}
script>

10. template refs

通过ref()还可以引用页面上的元素或组件。

<template>
<div>
<h3 ref="h3Ref">TemplateRefOneh3>
div>
template>

<script>
import {ref, onMounted} from '@vue/composition-api'

export default {
setup(){
//创建一个 DOM 引用
const h3Ref = ref(null)

//在DOM 首次加载完毕之后,才能获取到元素的引用
onMounted(()=>{
//为dom 元素设置字体颜色
// h3Ref.value 是原生DOM对象
h3Ref.value.style.color = 'red'
})
//把创建的引用 return 出去
return {
h3Ref
}
}
}
script>

10.2组件的引用
TemplateRefOne.vue 中的示例代码如下:

<template>
<div>
<h3>TemplateRefOneh3>

<button @click="showNumber">获取TemplateRefTwo中的count值button>

<hr />

<TemplateRefTwo ref="comRef" />
div>
template>

<script>
import { ref } from '@vue/composition-api'
import TemplateRefTwo from './TemplateRefTwo'

export default{
setup(){
//1.创建一个组件的ref引用
const comRef = ref(null)
//5.展示子组件中count 的值
const showNumber =() =>{
console.log(comRef.value.count)
}
//2.把创建的引用return 出去
return {
comRef,
showNumber
}
},
components:{
TemplateRefTwo
}
}
script>

TemplateRefTwo.vue中的示例代码:

<template>
<div>
<h5>TemplateRefTwo --- {{count}}h5>

<button @click="count+1">+1button>
div>
template>

<script>
import {ref} from '@vue/composition-api'

export default {
setup(){
//1.定义响应式的数据
const count = ref(0)
//2.把响应式数据return 给 Template使用
return {
count
}
}
}
script>

11.createComponent

这个函数不是必须的,除非你想要完美结合TypeScript提供的类型推断来进行项目的开发。
这个函数仅仅提供了类型推断,方便在结合TypeScript书写代码时,能为setup()中的props提供完整的类型推断。

import { createComponent } from 'vue'

export default createComponent({
props:{
foo:String
},
setup(props){
props.foo // <- type:string
}
})

你可能感兴趣的:(vue)