vue3入门06 - vue3生命周期、依赖注入、模版refs

570 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第12天,点击查看活动详情

前言

这一小节,主要对Vue3中的生命周期、依赖注入、模版refs进行相关介绍。

生命周期钩子函数

  • vue3中的生命周期钩子都采用onXXX()的函数形式进行按需导入使用。
  • 命周期钩子注册函数只能在 setup() 期间同步使用, 因为它们依赖于内部的全局状态来定位当前组件实例(正在调用 setup() 的组件实例), 不在当前组件下调用这些函数会抛出一个错误。
  • 与 2.x 版本生命周期相对应的组合式 API
    • beforeCreate -> 使用 setup()
    • created -> 使用 setup()
    • beforeMount -> onBeforeMount
    • mounted -> onMounted
    • beforeUpdate -> onBeforeUpdate
    • updated -> onUpdated
    • beforeDestroy -> onBeforeUnmount
    • destroyed -> onUnmounted
    • errorCaptured -> onErrorCaptured

注意:短横线的生命周期在vue3中已经废弃

  • 新增的钩子函数
    • onRenderTracked:注册一个调试钩子,当响应式依赖被组件的渲染作用追踪后调用。
    • onRenderTriggered:注册一个调试钩子,当响应式依赖触发了组件渲染作用的运行之后调用。
export default {
  onRenderTriggered(e) {
    debugger
    // 检查哪个依赖性导致组件重新渲染
  },
}
  • 生命周期钩子示例
export default {
  setup() {
    onBeforeMount(() => {
      console.log("onBeforeMount");
    });
    onMounted(() => {
      console.log("onMounted");
    });
    onBeforeUpdate(() => {
      console.log("onBeforeUpdate");
    });
    onUpdated(() => {
      console.log("onUpdated");
    });
    onBeforeUnmount(() => {
      console.log("onBeforeUnmount");
    });
    onUnmounted(() => {
      console.log("onUnmounted");
    });
    const count = ref(1);
    return {
      count,
    };
  },
  mounted() {
    console.log("Vue 2.x mounted");
  },
};

依赖注入

  • 依赖注入就是祖先组件向后代组件传递数据,使用provide()inject() 函数来实现,功能类似vue 2.x 中的 provide/inject
  • 注意
    • 这两个函数只能在当前活动组件的setup()函数中调用
    • 可以使用字符串或者Symbol作为依赖注入的key值
    • 在祖先组件中使用 provide()函数向下传递数据
    • 在后代组件中使用 inject()函数获取上层传递过来的数据
    • 我们可以传入响应式数据,达到provideinject之间的响应
    • 这里讲述基础使用方式,后面会有进阶
  • 父组件
// app.vue
<h1>父组件</h1>
 <button @click="colorRef='red'"></button>
 <button @click="colorRef='yellow'"></button>
 <button @click="colorRef='blue'"></button>
 <hr>
<CompSon/>
 import CompSon from './components/10.son'
import { provide, ref } from 'vue'
export default {
  name: 'App',
  components: {
    CompSon
  },
  setup() {
    // 向后代传递普通数据
    provide('color','green')
    // 传递响应式数据
    const colorRef = ref('red')
    provide('colorRef',colorRef)
    return {
      colorRef
    }
  }
}
  • 子组件
// son.vue
<template>
  <div>
    <h2>子组件</h2>
    <CompGrandson/>
  </div>
</template>

<script>
import CompGrandson from './11.grandson'
export default {
  components: {
    CompGrandson
  },
  setup() {

  }
}
</script>
  • 孙子组件
// grandson
<template>
  <div>
    <h2 :style="{color:color}">孙子组件</h2>
    <h3 :style="{color:colorRef}">ref</h3>
  </div>
</template>

<script>
import { inject } from 'vue'
export default {
  setup() {
    const color = inject('color')
    console.log(color);
    const colorRef = inject('colorRef')
    return {
      color,
      colorRef
    }
  }
}
</script>

模版 Refs

  • 通过 ref()函数还可以引用页面上的元素或组件,功能类似于 vue 2.x 中的 vm.$refs,使用步骤:
    1. setup() 中创建一个 ref 对象并返回它。
    2. 在页面上为元素添加 ref 属性,并设置属性值与创建的 ref 对象的名称相同。
    3. 当页面渲染完成后,可以通过该 ref 对象获取到页面中对应的 DOM 元素。

在普通dom元素上使用

<template>
  <div>
    <h3 ref="h3Ref">标题</h3>
  </div>
</template>

<script>
import { ref, onMounted, unref } from 'vue'
export default {
  setup() {
    // 创建一个值为null的ref的对象,并返回
    // 获取元素
    const h3Ref = ref(null)
    onMounted(()=>{
      // 必须在页面渲染完成之后才能获取到
      console.log(h3Ref.value)
    })
    return {
      h3Ref,
    }
  }
}
</script>

在组件上使用

  • 父组件
<template>
    <compRef
      ref="compRef"
      :index="123"
      @update="update"
    />
</template>
<script>
import { ref, onMounted, unref } from 'vue'
import compRef from './compRef'
export default {
  components:{
    compRef
  },
  setup() {
    // 创建一个值为null的ref的对象,并返回
    // 获取组件
    const compRef = ref(null)
    // 在页面渲染完成后才能获取
    onMounted(()=>{
      console.log(compRef);
      compRef.value.change()  // 父组件调用子组件方法
    })
    const update = (value)=>{
      console.log(value);
    }
    return {
      compRef,
      update
    }
  }
}
</script>
  • compRef
<template>
  <div>
   {{msg}}
  </div>
</template>
<script>
import { ref } from 'vue'
export default {
  setup(props,context) {
    const msg = ref('welcome')
    const change = () =>{
      msg.value = '欢迎'
    }
    console.log(context);
    console.log(context.attrs);
    // 子组件调用父组件方法
    context.emit('update',true)
    return {
      msg,
      change
    }
  }
}
</script>

v-for获取所有元素

  • 需要使用函数型的 ref(3.0 提供的新功能)来自定义处理方式:
<template>
  <div v-for="(item, i) in list" :ref="el => { divs[i] = el }">
    {{ item }}
  </div>
</template>

<script>
  import { ref, reactive, onBeforeUpdate } from 'vue'

  export default {
    setup() {
      const list = reactive([1, 2, 3])
      const divs = ref([])

      // 确保在每次变更之前重置引用
      onBeforeUpdate(() => {
        divs.value = []
      })

      return {
        list,
        divs,
      }
    },
  }
</script>

总结

  • 以上就是对于生命周期、依赖注入、模版Refs的基础使用的介绍
  • 关于使用到的sfc我们可以等使用脚手架创建项目之后再回过头来看一下。