zoukankan      html  css  js  c++  java
  • Vue 组件通信的多种方式(props、$ref、$emit、$attr、 $listeners)

    prop和$ref之间的区别:

    prop 着重于数据的传递,它并不能调用子组件里的属性和方法。像创建文章组件时,自定义标题和内容这样的使用场景,最适合使用prop。

    $ref 着重于索引,主要用来调用子组件里的属性和方法,其实并不擅长数据传递。而且ref用在dom元素的时候,能使到选择器的作用,这个功能比作为索引更常有用到。

    props   父组件传值子组件

    父组件传值

    //props示例(vue)
    <template>
        <div id="app">
          <child :message="message"></child> 动态传递
        <child message="传递的内容"></child> 静态传递
        </div>
    </template>
    
    <script>
        import Child from "./Child";
        export default {
          components: {Child},
          name: "main-page",
          data() {
              return {
                message:{
                  type:1,
                  name:'Admin',
                },
                a:2,
                b:4,
                c:'lalal'+Math.random(),
                title:'',
                info:'我是来自父组件',
                msg:'默认'
              }
          },
          created() {},
          mounted(){},
          methods: {}
        }
    
    </script>
    
    <style lang="scss" scoped>
    
    </style>

    子组件接收父组件传值

    <template>
    <div>
    {{message}}
    <!--<slot></slot>-->
    </div>
    </template>
    
    <script>
    export default {
      name: "child",
      props:['message'],
      data() {
        return {
          title:''
        }
      },
      mounted() {},
      methods:{}
    }
    </script>
    
    <style lang="scss" scoped>
    </style>

    父组件code引用子组件,通过props可以实现传值。可以传递string , number , object,表达式。对于子组件接受父组件props,可以直接使用props:[‘xxxx’]格式,为了更严谨,可以使用如下方式:

    <script>
        export default {
          name: "child",
         // props:['message'],
          props:{
            message:{
              type:Object,
              default:function () {
                return {}
              }
            }
          },
          data() {
             return {
                title:''
             }
          },
          mounted() {
             // this.$emit('showMessage','我是来自子组件')
          },
          methods:{
          }
        }
    </script>

    $emit 子组件向父组件传值

    props、ref 实现的都是父组件=>子组件之间的通信,而$emit则可实现子组件向父组件的通信, $emit应用的范围较为广泛。

    子组件传值给父组件

    template>
        <div>
         <input ref="myBtn"></input>
        </div>
    </template>
    <script>
      export default {
          name: "index",
          data() {
             return {
                info:'ref可以获取到元素哦~'
             }
          },
          mounted() {
              this.$emit('showMessage','我是来自子组件')
          },
          methods:{
          }
        }
    </script>

    父组件接收子组件传值

    <template>
        <div id="app">
             <child @showMessage="showMessage"></child>
        </div>
    </template>
    
    <script>
        import Child from "./Child";
        export default {
          components: { Child},
          name: "main-page",
          data() {
              return {
                message:{
                  type:1,
                  name:'Admin',
                },
                fromchildinfo :'我是来自父组件',
                msg:'默认'
              }
          },
          created() {
    
          },
          mounted(){
          },
          methods: {
            showMessage (data) {
              this.fromchildinfo = data
            },
          }
        }
    </script>

     

    $ref  的使用

    说明:vm.$refs 一个对象,持有已注册过 ref 的所有子组件(或HTML元素)
    使用:在 HTML元素 中,添加ref属性,然后在JS中通过vm.$refs.属性来获取
    注意:如果获取的是一个子组件,那么通过ref就能获取到子组件中的data和methods
    添加ref属性

    <div id="app">
      <h1 ref="h1Ele">这是H1</h1>
      <hello ref="ho"></hello>
      <button @click="getref">获取H1元素</button>
    </div>
    
    获取注册过 ref 的所有组件或元素
    methods: {
      getref() {
        // 表示从 $refs对象 中, 获取 ref 属性值为: h1ele DOM元素或组件
        console.log(this.$refs.h1Ele.innerText);
        this.$refs.h1ele.style.color = 'red';// 修改html样式
    
        console.log(this.$refs.ho.msg);// 获取组件数据
        console.log(this.$refs.ho.test);// 获取组件的方法
      }
    }
    <input ref="count" type="text" v-model="active.name" required name="name" value=""> 

      这样在vue中我们可以使用$ref来获取dom节点,进行一些dom的操作

      下面示例:控制input输入框的文字个数

    new Vue({
      el:'#app',
      data:{
      active:{'name':''}
      },
      watch:{
        active:{
          handler:function(){
            var _this = this;
            var _sum = 4; //字数限制为4个
            _this.$refs.count.setAttribute("maxlength",_sum);
          },
          deep:true
        }
      },
    })

    使用在子组件上,可以用来获取子组件的属性值,假设子组件里面都有一个属性news
     <!-- 父组件 -->

    <div id="app">
    <hdnews ref="hdnews"></hdnews>
    <hdinfo ref="hdinfo"></hdinfo>
    </div>
    new Vue({
      el:'#app',
      mounted () {
        console.log(this.$refs.hdnews.news); //获取子组件的值
        console.log(this.$refs.hdinfo.news);

         this.$refs.msg.getMessage('我是子组件一!')  //调用子组件的方法

      }
    })

     <!-- 子组件 -->
    <template>
      <h3>{{message}}</h3>
    </template>
    <script>
      export default {
        data(){
          return{
            news:'我是子组件的数据'
          }
        },
        methods:{
          getMessage(m){
            this.message=m;
          }
        }
      }
    </script>

    $attr、 $listeners
    场景提出:A、B、C三个组件,需要实现A=>B=>C,进行传递(结构较为简单,无需使用vuex)。当然实现方式也可以$emit,一层一层传递下去,但这样代码显得冗余。在vue2.4之后,提出 $attr、 $listeners ,可以实现快速传递。
    组件A code:

    <template>
        <div id="app">
         	<son :info="info" @getData="getData"></son>
         	<div>{{msg}}</div>
        </div>
    </template>
    
    <script>
        import Son from "./son";
    
        export default {
          components: {
            Son,
            Test,
            Child},
          name: "main-page",
          data() {
              return {
                message:{
                  type:1,
                  name:'Admin',
                },
                a:2,
                b:4,
                c:'lalal'+Math.random(),
                title:'',
                info:'我是来自父组件',
                msg:'默认'
              }
          },
          created() {
    
          },
          mounted(){
          },
          methods: {
             getData (val) {
               this.msg = val
            },
          }
    
        }
    
    </script>
    
    <style lang="scss" scoped>
     #app {
        375px;
       height: 100%;
     }
    </style>
    

    b组件

    <template>
        <temp-son v-bind="$attrs" v-on="$listeners"></temp-son>
    </template>
    
    <script>
        import TempSon from "./tempSon";
    
        export default {
          components: {TempSon},
          name: "son",
          props:[]
        }
    </script>
    
    <style scoped>
    
    </style>

    c组件

    <template>
      <div>
        <h1 class="btn">{{this.$attrs.info}}</h1>
      </div>
    </template>
    
    <script>
        export default {
          name: "temp-son",
          mounted() {
            this.$emit('getData','我来自孙子组件')
          }
        }
    </script>
    
    <style scoped>
    
    </style>

    $attr、 $listeners 的TypeScript写法

    A组件

    <template>
      <div class="home">
        <img alt="Vue logo" src="@/assets/images/logo.png" />
        <HelloWorld :info="info" @sunchangedata="getData" :msg="info" />
      </div>
    </template>
    
    <script lang="ts">
    import { Component, Vue } from "vue-property-decorator";
    import HelloWorld from "@/components/HelloWorld.vue"; // @ is an alias to /src
    
    @Component({
      components: {
        HelloWorld
      }
    })
    export default class Home extends Vue {
        info = "你不是好人?";
        getData(val:any){
            this.info = val;
        };
    }
    </script>

    b组件

    <template>
      <div class="hello">
        <h1>{{ msg }}</h1>
        <p>hello hello 我是来自子组件</p>
        <Sun v-bind="$attrs" v-on="$listeners"></Sun>
      </div>
    </template>
    
    <script lang="ts">
    import { Component, Prop, Vue } from "vue-property-decorator";
    import Sun from "./sun.vue"; // @ is an alias to /src
    
    @Component({
        components:{
            Sun
        }
    })
    export default class HelloWorld extends Vue {
        inheritAttrs = false;
        @Prop() private msg!: string;
    }
    </script>
    
    <!-- Add "scoped" attribute to limit CSS to this component only -->
    <style scoped lang="less">
    
    </style>

    c组件

    <template>
        <div>
            <p>sun组件</p>
            <p>来自爷爷辈:{{ $attrs.info }}</p>
            <button @click="$emit('sunchangedata','孙子说爷爷是好人')">点击更改爷爷辈信息</button>
        </div>
    </template>
    
    <script lang="ts">
    import { Component, Prop, Vue } from "vue-property-decorator";
    
    export default class Sun extends Vue {
      
    }
    </script>
    
    <style>
    </style>

      

  • 相关阅读:
    10.26 饮食
    10.25 饮食
    10.24饮食
    关于 wpf 的ICommand 的 CanExecute CanExecuteChanged func action的认识
    2018 10 23
    [Java]先有Class还是先有Object?
    [Java]如何制作一个WordCount-Plus的Plugin
    [java] 软工实践WordCount-Plus
    [java]基本数据类型
    [java]第一个程序
  • 原文地址:https://www.cnblogs.com/mary-123/p/11691599.html
Copyright © 2011-2022 走看看