刚出炉的 Vue 3.0 新特性

围绕最新发布的 vue-compisition-api,同时也是 vue 3.0 最重要的一些新特性,例如 setup() 函数、reactive()、ref() 等这些 Vue Hooks

创建一个 vue3.0-beta项目

// 安装 composition-api 体验 vue3 新特性
npm install @vue/composition-api --save

1、setup 函数

setup() 函数是 vue3 中,专门为组件提供的新属性。它为我们使用 vue3 的 Composition API 新特性提供了统一的入口

1.1 执行时机

setup 函数会在 beforeCreate 之后、created 之前执行

1.2 形参

第一个形参 props 用来接收 props 数据

  1. 在 props 中定义当前组件允许外界传递过来的参数名称
  2. 通过 setup 函数的第一个形参,接收 props 数据
// 父组件
<div p1="aaa"></div>

// 子组件
setup(props) {
    
    
  console.log(props.p1) // aaa
},
props: {
    
    
  p1: String
}

第二个形参 context 用来定义上下文

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

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

注意:在 setup() 函数中无法访问到 this,是个 undefined

1.3 reactive 函数

reactive() 函数接收一个普通对象,返回一个响应式的数据对象

// 3. 在 template 中访问响应式数据
<p>当前的 count 值为:{
    
    {
    
    count}}</p>
<button @click="count+=1">+1</button>

// 1. 按需导入 reactive 函数
import {
    
     reactive } from 'vue'

// 2. 在 setup() 函数中调用 reactive() 函数,创建响应式数据对象
setup() {
    
    
  // 创建响应式数据对象,类似于 vue 2.x 中 data() 返回的响应式对象
  const state = reactive({
    
    count: 0})
  
  // setup 函数中将响应式数据对象 return 出去,供 template 使用
  return state
}

渲染结果:

当前count的值为: 0
+1

1.4 ref 函数

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

import {
    
     ref } from 'vue'
setup () {
    
    
  const count = ref(0)
  console.log(count.value) // 0

  count.value++
  console.log(count.value) // 1
}

在 template 中访问响应式数据

<p>{
    
    {
    
    count}}</p>
import {
    
     ref } from 'vue'
setup () {
    
    
  const count = ref(0)
  console.log(count.value) // 0

  count.value++
  console.log(count.value) // 1
  return {
    
    count}
}
// 1

注意:只在setup函数内部访问ref函数需要加.value

在 reactive 对象中访问 ref 创建的响应式数据

import {
    
     ref, reactive } from 'vue'
setup () {
    
    
  const count = ref(0)
  count.value++
  const state = reactive({
    
    count})
  console.log(state.count) // 1
  return {
    
     state }
}

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

// 创建 ref 并挂载到 reactive 中
const c1 = ref(0)
const state = reactive({
    
    
  c1
})

// 再次创建 ref,命名为 c2
const c2 = ref(9)
// 将 旧 ref c1 替换为 新 ref c2
state.c1 = c2
state.c1++

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

1.5 isRef

isRef() 用来判断某个值是否为 ref() 创建出来的对象

应用场景:当需要展开某个可能为 ref() 创建出来的值的时候

import {
    
     ref, isRef } from 'vue'

setup() {
    
    
  const foo = ref(0)
  const isFoo = isRef(foo) ? foo.value : foo
  console.log(isFoo) // 0
}

1.6 toRefs

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

<p>{
    
    {
    
     count }}</p>
<button @click="increment">+1</button>

import {
    
     toRefs, reactive } from 'vue'

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

  const increment = () => {
    
    
    state.count++
  }

  return {
    
    
    // 将 state 上的每个属性,都转化为 ref 形式的响应式数据
    ...toRefs(state),
    increment 
  }
}

1.7 computed

  1. 创建只读的计算属性
import {
    
     computed, ref } from 'vue'

setup () {
    
    
  // 创建一个 ref 响应式数据
  const count = ref(1)

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

  console.log(plusOne.value) // 输出 2
  return {
    
    count, plusOne}
}
  1. 创建可读可写的计算属性
const count2 = ref(1)

// 创建一个 computed 计算属性
const plusTwo = computed({
    
    
  // 取值函数
  get: () => count2.value + 1,
  // 赋值函数
  set: val => {
    
    
    count2.value = val - 1
  }
})

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

1.8 watch

  1. 基本用法
import {
    
     watch, ref } from 'vue'

setup () {
    
    
  const count = ref(0)

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

  setTimeout(() => {
    
    
    count.value++
    // 输出 1
  }, 1000)
}
  1. 监视指定的数据源
    2.1 监视 reactive 类型的数据源:
// 定义数据源
const state = reactive({
    
     count: 0 })
// 监视 state.count 这个数据节点的变化
watch(
  () => state.count,
  (count, prevCount) => {
    
    
    /* ... */
  }
)

2.2 监视 ref 类型的数据源:

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

  1. 监视多个数据源
const state = reactive({
    
     count: 0, name: 'zs' })

watch(
  [() => state.count, () => state.name],
  ([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 = 'ls'
}, 1000)
  1. 清除监视
    在 setup() 函数内创建的 watch 监视,会在当前组件被销毁的时候自动停止。如果想要明确地停止某个监视,可以调用 watch() 函数的返回值即可,语法如下:
// 创建监视,并得到 停止函数
const stop = watch(() => {
    
    
  /* ... */
})

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

1.9 LifeCycle Hooks

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

import {
    
     onMounted, onUpdated, onUnmounted } from 'vue'

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

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

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

猜你喜欢

转载自blog.csdn.net/weixin_44257930/article/details/108579574