Vue3-API与生命周期

2周前 (01-13) 52次浏览 已收录 0个评论

导读

toRef、toRefs、vue3生命周期、markRaw与toRaw、customRef自定义Ref、provide与inject祖后代组件间通信、组合式API的优势、teleport标签、Suspense、defineAsyncComponent异步引入、readonly


toRef

  • 创建一个ref对象,其value值指向另一个对象中的某个属性。
  • 将响应式对象中某个属性单独响应式提供给外部使用
  • toRefs与toRef功能一致,但可以批量创建多个ref对象。
    • return{
            //因为person是响应式的,所以这个对象在后期添加属性也是响应式的,也会检测到新添加的新属性
            person,
      
            //因为这是展开且setup只执行一次,所以对象新添加的属性,不会监测到,更不是响应式的,
            ...toRefs(person) 
          }
<template>
  <h1>子组件</h1>
  <h2>姓名:{{ name }}</h2>
  <h2>性别:{{ job.a.sex }}</h2>
  <button @click="name += '~'">修改名字</button>
  <button @click="job.a.sex = '女'">修改为女</button>
  <button @click="job.a.sex = '男'">修改为男</button>
</template>

<script>
import { reactive, toRef, toRefs } from 'vue'
export default {
  name: 'Demo',
  setup(props, context) {
    //数据
    let person = reactive({
      name: 'wxl',
      age: 18,
      job: {
        a: {
          sex: '男',
        },
      },
    })
    return {
      //这种ref虽然也能实现相同效果,但是不推荐,因为这样会造成以后修改的值不是person对象里的值
      // name:ref(person.name)

      //但是这种就可以,因为这是引用(value---->person.namee)
      //   name:toRef(person,'name'),
      //   age:toRef(person,'age'),
      //   sex:toRef(person.job.a,'sex')

      //toRefs把person对象里的所用属性全部变成ref
      ...toRefs(person),//展开person对象的所有属性
    }
  },
}
</script>

生命周期

vue3也提供了组合式(Composition)API的生命周期钩子,也就是放在setup里面,放入之前要在import引入(组合式与上面的不推荐同时使用

  • beforeCreate ——–> setup() 官方认为组合式API没有这个 钩子,setup就是这个钩子
  • created——-> setup()
  • beforeMount——->onBeforeMount(()=>{})
  • mounted——->onMounted
  • beforeUpdate——->onBeforeUpdate
  • updated——->onUpdated
  • beforeUnmount——–>onBeforeUnmount
  • unmounted———–>onUnmounted

其他API

readonly 与 shallowReadonly

  • readonly: 让一个响应式数据变为只读。接收一个响应式数据。

    • let job = reactive({
            name:2,
            time:3,
            z:0,
            type:{
              name:'wxl'
            }
          })
          //接收一个响应式的数据
          job = readonly(job)

       

  • shallowReadonly:让一个响应式数据变为浅只读,即深的还是可以修改的。接收一个响应式数据。

  • 应用场景: 不希望别的组件的数据被修改时

shallowReactive 与 shallowRef

  • shallowReactive:只处理对象最外层属性的响应式(浅响应式)。

    let job = shallowReactive({
          name:2,
          time:3,
          z:0,
          type:{
            name:'wxl'
          }
        })
    //也就是只考虑第一层的响应式
  • shallowRef:只处理基本数据类型的响应式, 不进行对象的响应式处理。

markRaw与toRaw

  • markRaw
    • 标记一个对象,让他永远不会再成为响应式对象
    • 应用场景
      • 有些值不应该背设置为响应式,例如第三方类库
      • 当渲染具有不可变数据源的大型列表时,跳过响应式转换可以提高性能
  • toRaw
    • 将一个由reactive生成的响应式对象转为普通对象
      • let job = reactive({
              name:2,
              time:3,
              z:0,
              type:{
                name:'wxl'
              }
            })
            //接收一个响应式的数据
            job = toRaw(job)
    • 用于读取响应式对象对应的普通对象,对这个普通对象的所有操作,不会引起页面上的更新

customRef

创建一个自定义ref

<template>
  <h1>子组件</h1>
  <input type="text" v-model="keyWord">
  <h2>{{keyWord}}</h2>
</template>

<script>
import { customRef } from 'vue'
export default {
  name: 'Demo',
  setup(props, context) {
    // /自定义一个ref :myRef
    function myRef(value){
        let timer
        return customRef((track,trigger)=>{
            return{//return get/set对象
                get(){
                    console.log(`被读取数据${value}`)
                    track()//2再通知vue追踪数据value的变化,才能真正拿到最新的value值
                    return value
                },
                set(newValue){
                    console.log(`被改为${newValue}`)
                    clearTimeout(timer)
                    timer = setTimeout(()=>{
                        value = newValue

                       //1改过之后trigger通知vue去重新解析页面模版,即重新调用get(),此时value已经被修改了
                        trigger()
                    },1000)
                }
            }
        })
    }
    let keyWord = myRef('zzl')
    return {
      keyWord
    }
  },
}
</script>

provide与inject祖后代组件间通信

  • 父组件有一个provide选项来提供数据,组件有一个inject选项来开始使用这些数据

祖组件

setup(props, context) {
      let person = reactive({name:'wxl',age:'23'})
      provide('personData',person)
}

后代组件

setup(props, context) {
      const person = inject('personData')
}

组合式API的优势

  • 使用传统的配置式API,新增或者修改一个需求,就需要再data、methods、computed等里面修改,
  • 但是组合式API利用hooks函数,可以让相关功能的代码有序的组织在一起。

/hooks/userPoint.js

import { reactive,onMounted,onBeforeUnmount } from "vue";
export default function(){
    //实现鼠标打点的相关数据
    let point = reactive({
        x:0,
        y:0
    })

    //实现鼠标打点的相关方法 
    function savePoint(event){
        point.x=event.pageX
        point.y=event.pageY
    }
    
    //实现鼠标打点的相关生命周期钩子
    onMounted(()=>{
        // window.addEventListener('click',function(){})
        window.addEventListener('click',savePoint)
    })
    onBeforeUnmount(() => {
        window.removeEventListener('click',savePoint)
    })

    //返回数据
    return point
}

App.vue

<template>
  <h1>父组件</h1>
  <h2>x:{{point.x}}----y:{{point.y}}</h2>
</template>

<script>
import userPoint from './hooks/userPoint.js'
export default {
  name: 'App',
  setup() {
    let point = userPoint()
    return {point}
  }
}
</script>

teleport标签

<template>
  <h1>后代组件</h1>
  <teleport to='#tcBox'>
    <div class="box">
      我会被传送给ID为tcBOx下,以便不占用我所处后代层级的大小,当然也可以放在body等下
    </div>
  </teleport>
</template>

defineAsyncComponent异步引入

<Suspense>
    <template v-slot:default>
      <child></child>
    </template>
    <template v-slot:fallback>
      <h3>加载中...</h3>
    </template>
  </Suspense>
</template>

<script>
import {defineAsyncComponent} from 'vue'
////异步组件
const child = defineAsyncComponent(()=>{'./components/Demo.vue'})

export default {
  components:{child},
  name: 'App',
}
name:'child',
  async setup(props,context) {
    let p = new Promise((resolve,reject)=>{
      //...
    },3000)
    return{
      await p
  }

  • setup不能是一个async函数,因为这样返回值不再是return的对象, 而是promise, 模板看不到return对象中的属性。
  • 在Suspense和异步组件child的配合下,才可以返回一个Promise实例,setup才能使用async,才能return await 值


渣渣龙, 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:Vue3-API与生命周期
喜欢 (0)

您必须 登录 才能发表评论!