CompositionAPI生命周期函数新写法&Provide、Inject、DOMRef

CompositionAPI生命周期函数新写法

例子

 const app = Vue.createApp({
    setup() {
      // beforMount => onBeforeMount        当Vue实例即将挂载到页面时自动执行的函数
      // mounted => onMounted               当Vue实例挂载到页面时自动执行的函数
      // beforUpdate => onBeforUpdate       当数据发生变化页面重新渲染前自动执行的函数
      // updated => onUpdated               当数据发生变化后页面重新渲染后自动执行的函数
      // beforeUnmount => onBeforeUnmount   当组件即将从页面上移出的时候自动执行的函数
      // unmounted => onUnmounted           当组件从页面上移出之后自动执行的函数

      // onRenderTracked`指的是在收集响应式依赖时自动执行的函数
      // onRenderTrigger 指的是页面重新渲染被触发时自动执行的函数
      const  { ref, onBeforeMount, onMounted, onBeforeUpdate, onUpdated, onRenderTracked, onRenderTriggered} = Vue
      const name = ref('LeBrown')
      const handleClick = () => {
        name.value = "James"
      }
      onBeforeMount(()=>{
        console.log('onBeforeMount');
      })
      onMounted(()=>{
        console.log('onMounted');
      })
      onBeforeUpdate(()=>{
        console.log('onBeforUpdate');
      })
      onUpdated(()=>{
        console.log('onUpdated');
      })
      onRenderTracked(()=>{
        console.log('onRenderTracked');
      })
      onRenderTriggered(()=>{
        console.log('onRenderTriggered');
      })
      return {name,handleClick}
    },
    template: `
        <div @click = "handleClick">
          {{name}}
        </div>
    `
})


const vm = app.mount('#root')

备注

  • 由于setup函数的执行时间就是处于brforeCreatecreated之间,因此如果要在这两个钩子函数中写的逻辑直接写在stup中就可以了,所以CompositionAPI中没有与brforeCreatecreated钩子函数对应函数的新写法
  • CompositionAPI中提供了新的生命周期函数,如:onRenderTracked指的是在收集响应式依赖时自动执行的函数(首次就执行且每次重新渲染到都会重新收集下依赖);onRenderTriggered指的是只有在页面重新渲染被触发时自动执行的函数(惰性,首次不执行,内容发生变化才执行)

Provide、Inject

例1

 const app = Vue.createApp({
      setup() {

        const { provide } = Vue
        provide('name', 'leBrown')
        return {}
      },
      template: `
                <div>
                   <child />
                </div>
            `
    })
    app.component('child', {
      setup() {
        const { inject } = Vue
        const name = inject('name','hello')
        return {name}
      },
      template: `
                <div>
                  {{name}}
                </div>
            `
    }
    )

    const vm = app.mount('#root')

备注

  • 如果父组件没有使用provide传值给子组件,那么 inject的第二个参数表示默认值,如例子中的hello就是name的默认值
  • Provide不仅可以适用于父子组件的传值,而且它适合多层嵌套组件之间的传值

例2: 子组件改变父组件传递过来的值

需求: 点击子组件中的值,改变父组件传递过来的值

const app = Vue.createApp({

      setup() {

        const { provide, ref, readonly } = Vue
        const name = ref('leBrown')
        // 使用readonly封装后再传给子组件
        provide('name', readonly(name))
        // 修改父组件中的数据并传递方法给子组件
        provide('changeName', (value) => {
          name.value = value
        })
        return {}
      },
      template: `
                <div>
                   <child />
                </div>
            `
    })
    app.component('child', {
      setup() {
        const { inject } = Vue
        const name = inject('name')
        // 子组件接收父组件传递过来的方法
        const changeName = inject('changeName')
        const handleClick = () => {
          // 调用父组件传递过来的方法并传值
          changeName('James')
        }
        return { name, handleClick }
      },
      template: `
                <div @click="handleClick">{{name}}</div>
            `
    })

const vm = app.mount('#root')

备注

  • 由于vue中有单向数据流,因此父组件传递过来的数据,如果子组件想要修改,子组件不可以直接修改,而是应该子组件通知父组件,由父组件去修改,即谁提供的数据就在就由谁修改数据。实现的方法就是,在父组件中定义一个修改值的函数,父组件通过provide将这个函数传给子组件,子组件通过inject调用函数并传参,就可以修改父组件中的数据了

  • 如何避免不小心在子组件中直接修改了父组件传递过来的值呢?
    ==> 使用关键字readonly将传给子组件的值变成只读,再传给子组件,这样父组件传给子组件的值,子组件就没法直接修改了

  • 为什么子组件通过调用父组件传递过来的changeName可以修改变量name呢?因为changeName中修改的是name,而传给子组件的name是包装过的只读的name

模板Ref

例子:使用CompositionAPI获取真实DOM元素节点

const app = Vue.createApp({

  setup() {
    const { ref, onMounted } = Vue
    // 定义空的响应式对象hello,这个名字要和模板中引用DOM的ref的名字hello要一样
    const hello = ref(null)
    onMounted(() => {
      console.log(hello.value)
    })
    return {hello}
  },
  template: `
            <div>
              <div ref="hello">Hello World</div>
            </div>
        `
})


const vm = app.mount('#root')

运行结果

image.png

备注

  • 这里的Ref是获取DOM节点的引用,而不是获取响应式引用的Ref,上面的例子是要使用DOM的fef和获取响应式引用的ref配合使用,来获取真实DOM元素节点

  • 定义空的响应式对象hello,这个名字要和模板中引用DOM的ref的名字hello要一样,实际上空的响应式对象hello保存的就是ref为hello的div的DOM引用了

© 版权声明
THE END
喜欢就支持一下吧
点赞0

Warning: mysqli_query(): (HY000/3): Error writing file '/tmp/MYdbo0Jc' (Errcode: 28 - No space left on device) in /www/wwwroot/583.cn/wp-includes/class-wpdb.php on line 2345
admin的头像-五八三
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

图形验证码
取消
昵称代码图片