美文网首页redux前端开发那些事儿
【vue3.0】16.0 Composition API(四)—

【vue3.0】16.0 Composition API(四)—

作者: bobokaka | 来源:发表于2021-07-08 01:50 被阅读0次

生命周期函数的新写法

准备一个代码模板:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>lesson</title>
  <script src="https://unpkg.com/vue@next"></script>
</head>
<body>
  <div id="root"></div>
</body>
<script>

  const app = Vue.createApp({
    setup() {
      return { }
    },
    template: `
      <div>
        Hello World!
      </div>
    `,
  });
  
  const vm = app.mount('#root');
</script>
</html>

各种勾子函数如下写:

<script>

  const app = Vue.createApp({
    // beforeMount =>(等价于) onBeforeMount 
    // mounted => onMounted
    // beforeUpdate => onBeforeUpdate
    // beforeUnmount => onBeforeUnmount
    // unmouted => onUnmounted
    setup() {
      const {
        ref, onBeforeMount, onMounted, onBeforeUpdate, onUpdated,
        onRenderTracked, onRenderTriggered
      } = Vue;
      const name = ref('dell')
      onBeforeMount(() => {
        console.log('onBeforeMount')
      })
      onMounted(() => {
        console.log('onMounted')
      })
      onBeforeUpdate(() => {
        console.log('onBeforeUpdate')
      })
      onUpdated(() => {
        console.log('onUpdated')
      })
      // 每次渲染后重新收集响应式依赖
      onRenderTracked(() => {
        console.log('onRenderTracked')
      })
      // 每次触发页面重新渲染时自动执行
      onRenderTriggered(() => {
        console.log('onRenderTriggered')
      })
      const handleClick = () => {
        name.value = 'lee'
      }
      return { name, handleClick }
    },
    template: `
      <div @click="handleClick">
        {{name}}
      </div>
    `,
  });
  
  const vm = app.mount('#root');
</script>

Provide、Inject模板

  • provide 和 inject 主要为高阶插件/组件库提供用例。

  • 常用的父子组件通信方式都是父组件绑定要传递给子组件的数据,子组件通过props属性接收,一旦组件层级变多时,采用这种方式一级一级传递值非常麻烦,而且代码可读性不高,不便后期维护。

  • vue提供了provide和inject帮助我们解决多层次嵌套嵌套通信问题。在provide中指定要传递给子孙组件的数据,子孙组件通过inject注入祖父组件传递过来的数据。
    准备模板代码:

    <script>
        const app = Vue.createApp({
            setup() {
                
            },
            template: `
            <div>
              <child/>
            </div>
            `,
        });
        app.component('child',{
            template: `<div>child</div>`,}
        );

        const vm = app.mount('#root');
    </script>

Composition API中有provide方法:

   <script>
       const app = Vue.createApp({
           setup() {
               //父组件准备传递给子组件的数据
               const {
                   provide
               } = Vue;
               provide('name', 'dell')
           },
           template: `
           <div>
             <child/>
           </div>
           `,
       });
       app.component('child', {
           //子组件接收父组件的参数
           setup() {
               const {
                   inject
               } = Vue;
               //如果name没有传值的话,默认值为hello
               const name = inject('name','hello');
               return{name}
           },
           template: `<div>child</div>`,
       });

       const vm = app.mount('#root');
   </script>

如果子组件想要去改变父组件中的provide中的参数的值:

思路:子组件不能改变父组件provide中的值,只能调用父组件中存在的方法,执行父组件的方法去修改provide中的值。

为了方便观察,我们将provide中的name的值设置为ref包裹,方便绑定数据,修改后及时联动。

    <script>
        const app = Vue.createApp({
            setup() {
                //父组件准备传递给子组件的数据
                const {
                    provide,
                    ref
                } = Vue;
                provide('name', ref('dell'))
            },
            template: `
            <div>
              <child/>
            </div>
            `,
        });
        app.component('child', {
            //子组件接收父组件的参数
            setup() {
                const {
                    inject
                } = Vue;
                //如果name没有传值的话,默认值为hello
                const name = inject('name', 'hello');
                const handleClick=()=>{
                    name.value='lee';
                }
                return {
                    name,handleClick
                }
            },
            template: `<div @click="handleClick">{{name}}</div>`,
        });

        const vm = app.mount('#root');
    </script>

以上能够实现目的,但是父组件的内容在子组件修改不符合数据流的要求。尽量让父组件去修改值。推荐写法如下:

    <script>
        const app = Vue.createApp({
            setup() {
                //父组件准备传递给子组件的数据
                const {
                    provide,
                    ref
                } = Vue;
                const name = ref('dell');
                provide('name', name);
                provide('changeName', (value) => {
                    name.value = value;
                })
            },
            template: `
            <div>
              <child/>
            </div>
            `,
        });
        app.component('child', {
            //子组件接收父组件的参数
            setup() {
                const {
                    inject
                } = Vue;
                //如果name没有传值的话,默认值为hello
                const name = inject('name', 'hello');
                const changeName = inject('changeName');
                const handleClick = () => {
                    changeName('lee');
                }
                return {
                    name,
                    handleClick
                }
            },
            template: `<div @click="handleClick">{{name}}</div>`,
        });

        const vm = app.mount('#root');
    </script>

为了防止上面的不建议写法,可以通过readonly修饰,来限制子组件的权限:

......
provide('name', name);
......

修改为:

......
provide('name', readonly(name));
......

ref的用法

CompositionAPI 的语法下,获取真实的 DOM 元素节点(声明和ref对应上,就能获取真实的 DOM 元素节点)

    <script>
        // CompositionAPI 的语法下,获取真实的 DOM 元素节点
        const app = Vue.createApp({
            setup() {
                const {
                    ref,
                    onMounted
                } = Vue;
                const hello = ref(null);//这样声明,和ref对应上,就能获取真实的 DOM 元素节点
                //生命周期函数
                onMounted(() => {
                    console.log(hello.value);
                    //<div>hello world</div>
                })
                return {
                    hello
                }
            },
            template: `
        <div>
          <div ref="hello">hello world</div>
        </div>
      `,
        });

        const vm = app.mount('#root');
    </script>

相关文章

网友评论

    本文标题:【vue3.0】16.0 Composition API(四)—

    本文链接:https://www.haomeiwen.com/subject/ufrzultx.html