setup

概括

  • setup 函数其实是一个生命周期钩子,它对应的其实就是 Vue2 中的 beforeCreate 和 create。在vue3中我们通过这个函数来定义 Vue2 中的 data, methods, watch, computed 属性(数据定义与处理相关)

    作用:业务分离

  • 下面是一段描述vue2代码的伪代码

    1. new Vue({
    2. data () {
    3. 数据项1:[],
    4. 数据项2:{}
    5. },
    6. methods: {
    7. 与数据1相关的操作 () {}
    8. 与数据2相关的操作 () {}
    9. },
    10. computed: {
    11. 与数据1相关的计算属性:(){}
    12. 与数据2相关的计算属性:(){}
    13. }
    14. })
  • 缺点:与数据1相关的代码分散在不同的配置项中,并没有集中起来,不方便写代码:你往往需在不同配置项中跳转。例如:添加一个数据要去data中,添加对应的操作方法要在methods中。

  • 在 Vue3,我们可以这样写

    • 它的典型特点是,可以把业务相关的代码在放在同一个位置来写。
      1. const use数据项1 = function() {
      2. const 数据项1 = reactive({})
      3. const 计算属性1 = computed(()=>{})
      4. const 操作1 = ()=>{}
      5. return { 数据项1 计算属性1,操作1 }
      6. }
      7. const use数据项2 = function() {
      8. return { 数据项2 计算属性2,操作2 }
      9. }
      10. new Vue({
      11. data () {},
      12. setup () {
      13. const { 数据项1 计算属性1,操作1 } = use数据项1()
      14. const { 数据项2 计算属性2,操作2 } = use数据项2()
      15. return { 数据项1 计算属性1,操作1 , 数据项2 计算属性2,操作2}
      16. }
      17. })

      语法

  • setup(props,context) { const title = ref(0); return { title } }

  • setup 函数含有两个参数,并且必须返回一个对象,对象里包含所有在 template 模板中需要使用到的属性(包含data,methods 等),可直接在 template 中使用。 ```javascript

  1. <a name="Cn7mb"></a>
  2. ## 最新语法糖
  3. ![image.png](https://cdn.nlark.com/yuque/0/2021/png/2389794/1613405147706-1d0663f8-1cfe-4e30-b5f5-2a7f5a1ef2cd.png#align=left&display=inline&height=378&margin=%5Bobject%20Object%5D&name=image.png&originHeight=378&originWidth=917&size=19307&status=done&style=stroke&width=917)
  4. - 当 `<script>` SFC中的变量具有 `setup` 属性时,将对其进行编译,以使代码在 `setup()` 组件功能的上下文中运行。所有ES模块导出均被视为要暴露给渲染上下文并包含在 `setup()` 返回对象中的值。
  5. ```javascript
  6. <script setup="props, { emit }">
  7. import { watchEffect } from 'vue'
  8. watchEffect(() => console.log(props.msg))
  9. emit('foo')
  10. </script>

参数(props,context)

props

  • 用于接收 props,也就是定义在组件上的属性(同vue2),接收的 props 必须先在 props 属性中定义,否则不会被接收到

    1. export default{
    2. props: {
    3. title: String
    4. },
    5. setup(props,context) {
    6. console.log(props.title)
    7. }
    8. }
  • 解构:因为 props 是响应式的,所以不能使用 ES6 解构,因为它会消除 prop 的响应性。

    • toRefs

      1. import { toRefs } from 'vue'
      2. setup(props) {
      3. const { title } = toRefs(props)
      4. console.log(title.value)
      5. }
    • toRef:如果 title 是可选的 prop,则传入的 props 中可能没有 title 。在这种情况下,toRefs 将不会为 title 创建一个 ref 。需要使用 toRef 替代它。

      1. import { toRef } from 'vue'
      2. setup(props) {
      3. const title = toRef(props, 'title')
      4. console.log(title.value)
      5. }

      context

  • context 是一个普通的 JavaScript 对象,它暴露三个组件的 property:

    1. export default {
    2. setup(props, context) {
    3. // Attribute (非响应式对象)
    4. console.log(context.attrs)
    5. // 触发事件 (方法)
    6. console.log(context.emit)
    7. // 插槽 (非响应式对象)
    8. console.log(context.slots)
    9. }
    10. }

    响应式 API

    ref

  • 接受一个参数并返回一个响应式且可变的 ref 对象,用 ref 定义的变量,如果需要取到其变量值,需要使用 .value 属性


  • ```javascript

  1. <a name="b0rT4"></a>
  2. ### reactive
  3. - reactive 函数和 ref 作用非常接近,但是它的参数是一个对象,我们可以在对象中定义其方法,通过这个形式,就不需要再对其进行进行 .value 调用
  4. ```javascript
  5. <template>
  6. <button @click="data.changeCount">count is: {{ data.count }}</button>
  7. </template>
  8. <script>
  9. import { reactive } from "vue";
  10. export default {
  11. setup(props) {
  12. const data = reactive({
  13. count: 0,
  14. changeCount: () => { data.count++ },
  15. });
  16. return {
  17. data
  18. };
  19. },
  20. };
  21. </script>
  • 由于 reactive 返回的对象本质上已经是一个 Proxy 对象,所以通过 … 扩展符号展开的属性,是无法进行响应式的,解构时需要使用 toRefs

    1. const refData = toRefs(data);
    2. return {
    3. ...refData,
    4. };

    Vue3 的生命周期

  • Vue2 的所有生命周期写法与 Vue3 兼容

  • 在 Vue3 中,生命周期添加了 on 前缀,需要导入并写在 setup 函数中
    • 开始创建组件—— - setup()
    • 组件挂载到页面之前执行—— - onBeforeMount()
    • 组件挂载到页面之后执行—— - onMounted()
    • 组件更新之前—— - onBeforeUpdate()
    • 组件更新之后—— - onUpdated()

      Vue2 对比 Vue3

      1. Vue2--------------vue3
      2. beforeCreate -> setup()
      3. created -> setup()
      4. beforeMount -> onBeforeMount
      5. mounted -> onMounted
      6. beforeUpdate -> onBeforeUpdate
      7. updated -> onUpdated
      8. beforeDestroy -> onBeforeUnmount
      9. destroyed -> onUnmounted
      10. activated -> onActivated
      11. deactivated -> onDeactivated
      12. errorCaptured -> onErrorCaptured

      示例

      1. <template>
      2. <h1>{{ msg }}</h1>
      3. </template>
      4. <script>
      5. import { onMounted } from "vue";
      6. export default {
      7. props: {
      8. msg: String,
      9. },
      10. mounted() {
      11. console.log("mounted outside setup <vue2>");
      12. },
      13. setup(props) {
      14. onMounted(() => { //等同于 Vue2 的 mounted()
      15. console.log("onMounted in setup <vue3>")
      16. });
      17. return {
      18. };
      19. },
      20. };
      21. </script>
      setup函数 (ref&reactive) 生命周期 - 图1