vue3笔记

时间:2021-02-23 01:06:16

1.setup函数

1.生命周期

  • 执行顺序在 beforeCreate 和 created这两个钩子函数之前,是最早执行的,在程序运行中,setup函数只执行一次,创建的是data和method
  • 在 setup中没有this
  • beforeDestory/ destoryed 改名 beforeUnmount / unmounted;setup替代了beforeCreate/ created;beforeCreate/ created/ beforeMount/ mounted / beforeUpdate / updated 写在setup()里,并且加前缀on;beforeCreate/ created/ beforeMount/ mounted / beforeUpdate / updated继续使用也不会报错,但是不能继续使用beforeDestory/ destoryed

2.setup的参数
props、context

  1. props
    props是响应式的,当传入新的 prop 时,它将被更新。因为 props 是响应式的,不能使用 ES6 解构,它会消除 prop 的响应性。如果需要解构 prop,可以在 setup 函数中使用 toRefs 函数。
    在子组件中
import { ref, toRefs, watch } from 'vue' // 首先要引入
props: {
  name: {
    type: String,
    default: ''
  }
}, // 定义类型
setup (props) {
  const { name } = toRefs(props) // 解构要用到toRefs
}

2.context
传递给 setup 函数的第二个参数是 context。context 是一个普通的 JavaScript 对象,有三个property。context是普通对象,不是响应式的,可以在传参的时候直接解构。

export default {
  setup(props, context) {
    // Attribute (非响应式对象)
    console.log(context.attrs)

    // 插槽 (非响应式对象)
    console.log(context.slots)

    // 触发事件 (方法)
    console.log(context.emit)
  }
}
export default {
  setup(props, { attrs, slots, emit }) {
    ...
  }
}
  • attrs: 接收在父组件传递过来的,并且没有在props中声明的参数。
  • emit:子组件对父组件发送事件,在vue2中,子对父发送事件采用this.$emit对父组件发送事件,在vue3中子组件对父组件发送事件采用context.emit发送事件。
  • slots:和vue2中的插槽使用类似

3.setup里面的函数
1.ref 使数据响应式。使用ref的数据在setup函数被访问时,需要加.value,在模板中被使用时可以直接访问,但如果是深层次的,还是需要加.value。

2.reactive 使数据响应式
基础数据类型用ref,对象类型用reactive

3.toRefs
与 toRef 不一样的是, toRefs 是针对整个对象的所有属性,目标在于将响应式对象( reactive 封装)转换为普通对象,且保持响应性。

export default {
  name: 'ToRefs',
  setup () {
    const state = reactive({
      age: 20,
      name: 'leyo'
    })
    const stateRefs = toRefs(state)
    return {
      ...stateRefs
    }
  }
}

4.toRef
在一个响应式对象里面,如果其中有一个属性要拿出来单独做响应式的话,就用 toRef。

  • 用于响应式对象,产出的结果具备响应式,且修改响应式数据是会影响到原始数据。
  • 如果用于普通对象(非响应式对象),产出的结果不具备响应式。
  • 和ref的区别:ref本质是拷贝,修改响应式数据不会影响原始数据;toRef的本质是引用关系,修改响应式数据会影响原始数据。

5.watch
三个参数:一个想要侦听的响应式引用或 getter 函数;一个回调;可选的配置选项.

  setup () {
    const count = ref(0)
    const countWatch = ref(0)
    watch(
      // getter 函数
      () => count.value + 1,
      (newValue) => {
        console.log('newValue', newValue)
        countWatch.value = newValue
      },
      {
        immediate: true
      }
    )

    // watch(
    //   // 一个想要侦听的响应式引用
    //   count,
    //   (newValue) => {
    //     countWatch.value = ++newValue
    //   },
    //   {
    //     immediate: true
    //   }
    // )
    return {
      count,
      countWatch
    }
  }

特点:

  1. 具有一定的惰性lazy,第一次页面展示的时候不会执行,只有数据变化的时候才会执行
  2. 参数可以拿到当前值和原始值

6.watchEffect

  1. 立即执行,没有惰性,页面的首次加载就会执行
  2. 不需要传递要侦听的内容 会自动感知代码依赖,不需要传递很多参数,只要传递一个回调函数
  3. 不能获取之前数据的值 只能获取当前值
  setup () {
    const count = ref(0)
    const countWatch = ref(0)
    watchEffect(
      () => {
        countWatch.value = ++count.value
      }
    )
    return {
      count,
      countWatch
    }
  }

7.computed
返回一个不可变的响应式 ref 对象。

	const count = ref(0)
    const countWatch = computed(
      () => count.value + 1
    )
    ```
// 如果希望对象是可写的,则需要用 get 和 set 函数创建
    const count = ref(0)
    const countWatch = computed({
      get: () => count.value + 1,
      set: (val) => {
        count.value = val - 1
      }
    })
    // 结果:
	// count: 0  countWatch: 1

8.readonly
接受一个对象 (响应式或纯对象) 或 ref 并返回原始对象的只读代理。只读代理是深层的:任何被访问的嵌套 property 也是只读的。

9.provider和inject
provide和inject可以实现嵌套组件之间进行传递数据。 这两个函数都是在setup函数中使用的。 父级组件使用provide向下进行传递数据。 子级组件使用inject来获取上级组件传递过来的数据。(可跨层级传值)
为了增加 provide 值和 inject 值之间的响应性,我们可以在 provide 值时使用 ref 或 reactive。而且还是不要改变单向数据流,如果要改变provide的值,建议 provide 一个方法来负责改变响应式 property。最后,如果要确保通过 provide 传递的数据不会被 inject 的组件更改,我们建议对提供者的 property 使用 readonly。

<template>
  <MyMarker />
</template>

<script>
import { provide, reactive, readonly, ref } from 'vue'
import MyMarker from './MyMarker.vue'

export default {
  components: {
    MyMarker
  },
  setup() {
    const location = ref('North Pole')
    const geolocation = reactive({
      longitude: 90,
      latitude: 135
    })

    const updateLocation = () => {
      location.value = 'South Pole'
    }

    provide('location', readonly(location))
    provide('geolocation', readonly(geolocation))
    provide('updateLocation', updateLocation)
  }
}
</script>

2.单文件组件script setup

1. 是组合式 API 的编译时语法糖,相比于普通的

  • 更少的样板内容,更简洁的代码。
  • 能够使用纯 Typescript 声明 props 和抛出事件。
  • 更好的运行时性能 (其模板会被编译成与其同一作用域的渲染函数,没有任何的中间代理)。
  • 更好的 IDE 类型推断性能 (减少语言服务器从代码中抽离类型的工作)。
    1.无需return才能在setup外部使用

2.defineProps 和 defineEmits
在 script setup中必须使用 defineProps 和 defineEmits API 来声明 props 和 emits ,它们具备完整的类型推断并且在 script 标签中是直接可用的:

<script setup>
const props = defineProps({
  foo: String
})

const emit = defineEmits(['change', 'delete'])
// setup code
</script>