Vue 组件的信息传递

举报
小妖现世 发表于 2020/07/16 14:40:05 2020/07/16
【摘要】 vue中组件信息传递

最近看了一下vue框架,把里面组件的信息传递总结了一下:哪里写的不对地方,希望大家可以提出宝贵意见!


单向数据流

在vue中,当父组件通过方法改变自己的数据时,如果子组件也用到了这个数据,那么子组件也会跟着更新发生改变;父组件的数据流动到了子组件,子组件更新,这就是vue数据的单向数据流

父子组件的信息交互

  • 父传子:可通过属性传递,子组件先在行内用动态属性接收,然后在组件中用props注册之后才可以使用

```

<html>

    <body>

    <div id="app">

    <my-child :mydata="name"></my-child>

  </div>

  <template id="myChild">

     <p class="bg">{{mydata}}</p>

  </template>

    </body>

    <script>

    let my-child={

        template:'#myChild',

        //简写:props:['mydata'],

        props:{ //子组件需要props 接收一下才能用

            mydata:{

                type:[Number,String], //数据类型检测

                default:'大妖',  //默认值

                required:true,  //是否为必传

                validator(val){  //自定义规则使用的属性;不管成功与否都会继续渲染页面

                    //val值为传进来的mydata

                    return val.length>2

                }

            }

        }

    }

    let vm=new Vue({

        el:'#app',

        data:{

            name:'小妖',

        },

        components:{  //[kəmˈpəʊnənts]组件,子组件需要在父组件components注册才能使用

            //全写:my-child:my-child,

            my-child

        }

    })

    </script>

</html>

```

新增父传后代

  • 把要传递的属性也要先在子组件的行内属性接收一下,子组件通过\$attrs 获取传递的属性值,通过\$listeners 获取传递的方法

  •  孙子组件则需要在行内通过v-bind 接收属性,v-on 接收方法

```

<html>

    <body>

        <div id="app">

    <child :val="a" user='大妖' age="18" @hhh='fn'></child>

        </div>

    </body>

    <script>

    let  grandson={

    template:"<div>{{$attrs.val}}{{$attrs.user}}<button @click='$listeners.f'>改一改</button></div>"

    }

    let  child  ={

        data(){

          return {}

        }, 

        components:{

          grandson

        },

      // props:["val"],

      // 可以通过v-bind将child的行间的属性以对象的形式传递给grandson组件

      // v-bind :属性 v-on : 事件方法

        template:"<div><grandson v-bind='$attrs' v-on='$listeners'></grandson></div>"

    }

    let  vm = new Vue({

    el:"#app",

      data:{

      a:"小妖"

      },

      components:{

      child

      },

      methods:{

      fn(){

        this.a="小妖现世"

        }

    }

    })

    </script>

</html>

```

子传父

  • + 通过自定义事件发布订阅,子组件通过this.$emit("方法名") 通知父组件方法执行;简写用.sync修饰符::x.sync="xx" ;在子件中修改用,写在方法中 this.$emit("update:x", mm);mm为要修改的值

```

<html>

    <body>

        <div id="app">

           <!-- 自定义事件:自己起的名字 -->

           {{money}}

           <!-- 订阅 -->

           <son :m="money" @changemoney="fn"></son>

        //sync修饰符

        <!--<son v-bind:m="money"  @update:m="money=$event"></son>-->

          <son :m.sync="money"></son>

        </div>

    </body>

    <script>

            let son = {

            data(){

              return {}

            },

            methods:{

               add(){

                 // 发布订阅==>自定义事件

                 // 子组件订阅了父组件的方法;在子组件中,触发了父组件的方法,让父组件改变自己的数据;

                 // 发布让订阅的方法执行

                 // $emit: 是vue实例的一个方法;发布自定义事件的方法

                 this.$emit("changemoney");

                 //update:m 自定义事件的名字

                 //888是最新值,传给了$event,触发事件必须是update:m

                 this.$emit("update:m",888);

               }   

           },

           props:["m"],

           template:"<div>{{m}}<button  @click='add'>多要点</button></div>"

        }

        let vm = new Vue({

          el:"#app",

          data:{

          money:666

          },

          methods:{

            fn(){

            this.money=888;

            }

          },

          components:{

          son

          }

        });

    </script>

</html>

```

 兄弟组件之间的交互

```

<body>

    <div id="app">

       <bro1></bro1>

       <bro2></bro2>

    </div>

<body>

<script>

let  eventBus = new Vue;// 这个就是个容器,能够把两个兄弟进行关联

let bro1 = {

data(){

    return {

    color:"红色"

    }

},

  methods:{

  changeBro2(){

    // 让eventBus中的订阅的changeRed执行

      eventBus.$emit("changeRed");

    }

},

  template:"<div>{{color}}<button @click='changeBro2'>变红色</button></div>"

};

let bro2= {

  data(){

    return {

      color:"绿色"

    }

  },

  created(){

  // created能获取到methods方法

// $on : 订阅;把bro2的事件放到了eventBus这个实例的事件池中

    eventBus.$on("changeRed",this.changeRed)

  },

  methods:{

  changeRed(){

    this.color="红色";

    }

  },

  template:"<div>{{color}}<button>变绿色</button></div>"

}

new Vue({

el:"#app",

  data:{},

  methods:{},

components:{

  bro1,

    bro2

  },

})

</script>

```

 Vuex:专门解决vue项目的公共数据管理的库

  • store 是一个实例,state:公共数据

  •  创建Vuex的实例,并注入vue实例中,可以在子组件的钩子函数中使用

  • 在vuex中规定,要改state的数据,必须通过commit来提交一个mutation

```

let store=new Vuex.Store({

  state:{

    count:100

  },

  getters:{

    //相当于computed ,根据数据依赖技术,有缓存机制

    str(state){

      //str 执行时,默认会传递进来一个state,第一个参数都是当前store的state

      return state.count%2===0?"偶":"奇"

    }

  },

  mutations:{

    //mutations 是同步事物

    add(state,payload){

      //第一项state 默认是store 中的state

      //payload :调用函数传递的参数

      //vue中唯一改变state的数据方法就是提交mutations

      state.count+=payload;

    }

  },

  actions:{

    //action提交的是mutation, 不直接更改状态

    //action可以异步操作,函数接受一个与 store 实例具有相同方法和属性的 context 对象

    increase(context,option){

      //context === store的实例,当然也可以把{commit}结构出来

      setTimeout(()=>{

        context.commit("add",option);

      },200)

    }

  }

})  

let child={

  data(){

    return{}

  },

  computed:{

    //vuex.mapState 返回值是一个对象

    //组件的计算属性依赖store中的数据变化

    ...Vuex.mapState(["count"]),

    ...Vuex.mapGetters(["str"])

  },

  methods:{

   // mutations中的方法是commit提交

   // addCount(val){

   //     this.$store.commit("add",val);

   // }

   // actions中的方法是dispatch派发

   // addCount(val){

   //通知vuex中add 方法执行

   //     this.$store.dispatch("increase");

   // }

   ...Vuex.mapMutations(["add"])

   /*将store中的add方法映射到自己的methods,

   并且methods这个方法名字叫aaa*/

   // ...Vuex.mapMutations({aaa:"add"})

   ...Vuex.mapActions(["increase"])

  },

  template:"<div>{{count}}<p @click='addCount(2)'>累加</p><div>"

}

// 每个模块独立的state;但是getters  mutations  actions 会注册到全局上;

// 每一个module都可以有自己独立的state getters  mutations  actions 

// 如果私有模块和公有模块存在同样的方法,会把两个方法整合到一起;

let vm=new Vue({

  el:"#app",

  data:{},

  created(){

    //可以在生命周期的任何一个钩子函数中使用vuex

    console.log(this.$store.state.count)

  },

  store //把store注入vm实例中

})

```



【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。