• 有问题请联系QQ:2374146085
  • 有问题请联系QQ:2374146085

Vue3-API与生命周期

1年前 (2022-01-13) 1083次浏览 已收录 0个评论 扫描二维码

导读

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


toRef

  • 创建一个ref对象,其value值指向另一个对象中的某个属性。
  • 将响应式对象中某个属性单独响应式提供给外部使用
  • toRefs与toRef功能一致,但可以批量创建多个ref对象。
return{
      //因为person是响应式的,所以这个对象在后期添加属性也是响应式的,也会检测到新添加的新属性
      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: '男',
        },
      },
    })
    //因为这是解构取值且setup只执行一次。解构出来的值,以后不会监测到,更不是响应式的, 
    let {name,age}=person //所以这个不是响应式的
    let {name,age}=toRefs(person) //2、这种也可以变成ref
    return {
      //这种ref虽然也能实现相同效果,但是不推荐,因为这样会造成以后修改的值不是person对象里的值
      // name:ref(person.name)

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

      //1、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'
          }
        })
        //接收一个响应式对象的数据,然后传给子组件使用
        let childUseJob = 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',readonly(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'
////异步组件,defineAsyncComponent接收一个peomise,而import返回的就是promise。
const child = defineAsyncComponent(()=>import{'./components/Demo.vue'})

export default {
  components:{child},//此时这个组件都是异步加载的了
  name: 'App',
}

Suspense

它是一个内置的全局组件,有两个插槽。

  • default:如果default可以显示,就显示default的内容
  • fallback:如果default无法显示,那么就会显示fallback插槽的内容
<suspense>
    <template #default>
      <p></p>
    </template>
    <template #fallback>
      <p></p>
    </template>
</suspense>

vue3中获取ref

<template>
<!-- 3 -->
  <h1 ref="title">标题</h1>
</template>

<script>
import { defineComponent, onMounted } from 'vue'
export default defineComponent({
  setup(props, context) {
    //1
    const title = ref(null)

    onMounted(()=>{
        //vue3中ref只有在挂载之后才能拿到值
        // 4
        console.log(title)
    })
    return {
      // 2
      title,
    }
  },
})
</script>

<style></style>

 


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

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