18.Vue3.x Composition API 以及 Provide Inject

一、Provide Inject

通常,当我们需要将数据从父组件传递到子组件时,我们使用props。想象一下这样的机构:你有一些深嵌套的组件,而你只需要来自深嵌套子组件中父组件的某些内容。在这种情况下,你任然需要将prop传递到整个组件链中,这可能会很烦人。

对于这种情况,我们可以使用provide和inject对父组件可以作为其所有子组件的依赖项提供程序,而不管组件层次结构有多深。这个特性有两个部分:父组件有一个provide选项来提供数据,子组件有一个inject选项来开始使用这个数据。
在这里插入图片描述

  1. 非组合是API中的写法:

    定义一个子组件Location.vue,使用inject接收app根组件传递的值

    <template>
        <div class="location">
            <h3>Location组件</h3>
            App组件的Title={{title}}
            <br>App组件里面的userInfo:
           {{userinfo.username}}--{{userinfo.age}}
        </div>
    </template>
    
    <script>
        export default {
            name: "",
            inject:['title','userinfo'],
            data() {
                return {}
            },
            methods: {}
        }
    </script>
    
    <style lang="scss" scoped>
        .location{
          text-align: center;
        }
    </style>
    

    定义一个组件Home.vue,调用子组件Location.vue

    <template>
        <div>
            <h2>Home组件</h2>
            <br>
            <v-location></v-location>
        </div>
    </template>
    
    <script>
        import Location from "@/components/Location";
        export default {
            name: "",
            data() {
                return {}
            },
            components:{
              "v-location":Location,
            },
            methods: {}
        }
    </script>
    
    <style lang="scss" scoped>
        h2{
          text-align: center;
        }
    </style>
    

    在根组件App.vue中调用Home.vue组件,并使用provide传值,并且定义方法改变titile的值,运行发现,改变的值并不会传递到Location.vue组件

    <template>
        <h1>我是app根组件</h1>
        <button @click="setTitle">改变title</button>
        <br>
        {{title}}
        <hr>
        <v-home></v-home>
    </template>
    <script>
        import Home from "@/components/Home";
        export default {
            name: "App",
            data(){
                return{
                    title:"app组件里面的titile"
                }
            },
            provide(){
              return{
                  title:this.title,
                  userinfo:{
                      username:"张三",
                      age:20
                  }
              }
            },
            components: {
                "v-home": Home,
            },
            methods: {
                setTitle(){
                    this.title="改变后的app根组件标题"
                }
            }
        }
    </script>
    
    <style lang="scss" scoped>
      h1 {
        text-align: center;
      }
    </style>
    
  2. 组合式API中的写法

    Provide:

    在setup()中使用provide时,我们首先从vue显示导入provide方法。这使我们能够调用provide时来定义每个property。

    provide函数允许你通过两个参数定义property:

    1. property的name(类型)
    2. property的value
    语法:provide(“key”,value);

    将上面的例子按如下方式重构:则实现了同步改变

    Location.vue

    <template>
        <div class="location">
            <h3>Location组件</h3>
            App组件传递的的Title={{title}}
            <br>
            App组件传递的userinfo:
            <br>
            {{userinfo.username}}--{{userinfo.age}}
            <br>
            双向数据绑定:
            <br>
            <input type="text" v-model="userinfo.username" placeholder="username"/>
            <br>
            <input type="text" v-model="userinfo.age" placeholder="age"/>
            <br>{{userinfo.username}}--{{userinfo.age}}
        </div>
    </template>
    <script>
        import {inject} from "vue"
        export default {
            name: "",
            setup(){
              let title=inject("title");
              let userinfo=inject("userinfo");
              return {
                  title,
                  userinfo
              }
            },
            methods: {}
        }
    </script>
    
    <style lang="scss" scoped>
        .location{
          text-align: center;
        }
    </style>
    

    App.vue

    <template>
        <h1>我是app根组件</h1>
       <button @click="setTitle">改变title</button>
        <br>
        {{ title }}
        <br>
        双向数据绑定:
        <br>
        <input type="text" v-model="userinfo.username" placeholder="username"/>
        <br>
        <input type="text" v-model="userinfo.age" placeholder="age"/>
        <br>{{userinfo.username}}--{{userinfo.age}}
        <hr>
        <v-home></v-home>
    </template>
    
    <script>
        import Home from "@/components/Home";
        import {ref,reactive,provide} from "vue";
        export default {
            name: "App",
            setup() {
                let title = ref("app根组件里面的title");
                provide("title",title);
                let userinfo=reactive({
                    username:"张三",
                    age:20
                });
                provide("userinfo",userinfo);
                let setTitle=()=>{
                  title.value="改变后的title";
                };
                return {
                    title,
                    userinfo,
                    setTitle
                }
            },
            components: {
                "v-home": Home,
            }
        }
    </script>
    <style lang="scss" scoped>
      h1 {
        text-align: center;
      }
    </style>
    
    

    运行时,我们点击App.vue组件的按钮,改变title的值,Location.vue组件里面的值跟着改变。

    在App.vue里面用v-model双向数据绑定,文本框的值改变时,对应的Locaiton.vue的值也跟着改变。

    在Location.vue里面用v-model双向数据绑定,文本框的值改变时,App.vue组件里面的值也跟着改变。

    注意:

    对比以前父子组件使用props接收值时,子组件时无法改变父组件的值的。

    provide inject实现父子组件传值的时候,子组件改变数据也会影响父组件。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值