深入了解六种vue组件组件间通信

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


深入了解六种vue组件组件间通信


提示:以下是本篇文章正文内容,下面案例可供参考

一、自定义事件

原生DOM—button可以绑定系统事件—click点击事件等等
非原生DOM节点不能绑定系统事件 (不起作用:因为属于自定义事件)需要添加native修饰符@click.native 可以把自定义事件改为原生DOM事件

// 父组件
<template>
  <div>
    <Event2 @click="handler2" ></Event2>
  </div>
</template>
methods: {
      handler2(params){
       console.log(params);
      }
    }
// 子组件
<template>
  <div >
    <h2>Event2组件</h2>
    <button @click="$emit('click',66666)">分发自定义click事件</button>
  </div>
</template>

二、v-model实现父子组件之间的通信

v-model本质上是一个语法糖 实现原理是v-on绑定msg 然后再通过@input事件修改msg的值

<!--父组件-->
<template>
  <div>
    <h2>深入v-model</h2>
    <input type="text" v-model="msg">
    <span>{{msg}}</span>
    <br>
    <h2>深入v-model原理</h2>
    <!-- 原生DOM当中是有oninput事件:当表单元素发生文本的变化的时候就会立即出发 -->
    <input type="text" :value="msg" @input=" msg = $event.target.value"/>
    <span>{{msg}}</span>
    <!--并非原生DOM:自定义组件-->
    <!-- <CustomInput :value="msg" @input="msg = $event"></CustomInput>    
    <CustomInput v-model="msg"></CustomInput> -->
    <CustomInput :value="msg" @input="msg = $event"/>
    <hr>
  </div>
</template>
 export default {
    name: 'ModelTest',
    data() {
      return {
         msg:"我爱塞北的大雪呀"
      }
    },
    components: {
      CustomInput
    }
  }
  //子组件
  <template>
  <div style="background: #ccc; height: 50px;">
    <h2>input包装组件----{{value}}</h2>
    <input :value="value" @input="$emit('input',$event.target.value)"/>
  </div>
</template>

sync实现父子组件通信 和v-model类似 可以实现父子组件数据同步

代码如下(示例):

父组件
<template>
  <div>
    小明的爸爸现在有{{ money }}<h2>不使用sync修改符</h2>
    // @upadata:money="money=$event"属于自定义事件
    <Child :money="money" @update:money="money = $event"></Child>
    <h2>使用sync修改符</h2>
    <!--  -->
    <Child :money.sync="money"></Child>
    <h2>使用v-model修改符</h2>
    <hr />
  </div>
</template>

<script type="text/ecmascript-6">
import Child from './Child.vue'
import Child2 from './Child2.vue'
export default {
  name: 'SyncTest',
  data() {
    return {
      money: 10000
    }
  },
  components: {
    Child,
    Child2
  }
}
</script>
// 子组件Child
<template>
  <div style="background: #ccc; height: 50px;">
    <span>小明每次花100</span>
    <button @click="$emit('update:money',money - 100)">花钱</button>
    爸爸还剩 {{money}}</div>
</template>

<script type="text/ecmascript-6">
  export default {
    name: 'Child',
    props:['money']
  }
</script>

// 子组件Child2 
<template>
  <div style="background: #ccc; height: 50px;">
    <span>小明每次花100</span>
    <button>花钱</button>
    爸爸还剩 ???</div>
</template>

<script type="text/ecmascript-6">
  export default {
    name: 'Child2'
  }
</script>

a t t r s 与 attrs与 attrslisteners`实现组件间通信

// 父组件
<template>
  <div>
    <h2>自定义带Hover提示的按钮</h2>
    <!-- 二次封装的HintButton按钮的时候,把人家el-button需要的数据传递过去 -->
     <HintButton type="success" icon="el-icon-plus" title="我是中国人" @click="handler"/>
  </div>
</template>

<script type="text/ecmascript-6">
import HintButton from './HintButton';
export default {
  name: 'AttrsListenersTest',
  components:{
     HintButton 
  },
  methods: {
    handler() {
       alert('666');
    },
  },
}
</script>
// 子组件
<template>
  <div>
     <a :title="title">
     <!-- v-bind不能写成:v-on也不能写成@ -->
        <el-button v-bind="$attrs" v-on="$listeners">添加</el-button>
     </a>
  </div>
</template>

<script>
export default {
  name: "",
  props:['title'],
  mounted(){
    //this.$listeners 他也是组件组件实例自身的一个属性 它可以接收到父组件给子组件传输的自定义事件
    //this.$attrs:可以获取到父亲传递的数据【props】
    //this.$attrs是可以获取父亲传递的props数据,如果子组件通过
    //props:[],接受,this.$attrs属性是获取不到的
    console.log(this.$attrs);
    console.log(this.$listeners);
  }
};
</script>

<style scoped></style>

c h i l d r e n 和 children和 childrenparent

可以通过组件实例ref来传递数据
也可容易通过 c h i l d r e n 和 children和 childrenparent组件实例来传递数据

// 父组件
<template>
  <div>
    <h2>BABA有存款: {{ money }}</h2>
    <button @click="JieQianFromXM(100)">找小明借钱100</button><br />
    <button @click="JieQianFromXH(150)">找小红借钱150</button><br />
    <button @click="JieQianAll(200)">找所有孩子借钱200</button><br />
    <button @click="SendInfo">我是baba</button>
    <br />
    <!-- 小明 -->
    <Son ref="xm" />
    <br />
    <!-- 小红 -->
    <Daughter ref="xh"/>
  </div>
</template>

<script>
import Son from "./Son";
import Daughter from "./Daughter";

export default {
  name: "ChildrenParentTest",
  data() {
    return {
      money: 1000,
    };
  },

  methods: {
    //找儿子借钱
    JieQianFromXM(money) {
      //父组件的数据累加100
      this.money += money;
      this.$refs.xm.money -= money;
    },
    JieQianFromXH(money) {
      //父组件的数据累加150
      this.money += money;
      this.$refs.xh.money -= money;
    },
    JieQianAll(money){
      this.money += 2*money;
      this.$children.forEach(item=>item.money-=money);
      //不建议用枚举获取子组件:因为没办法确定到底是那个子组件
      // this.$children[0].money -=money;

    },
    SendInfo(){
      //在父组件中获取到子组件(数据+方法)
      this.$refs.xm.tinghua();
    }
  },

  components: {
    Son,
    Daughter,
  },
};
</script>

<style></style>




// 子组件
<template>
  <div style="background: #ccc; height: 50px;">
    <h3>儿子小明: 有存款: {{money}}</h3>
    <button @click="geiQian(50)">BABA: 50</button>
  </div>
</template>

<script>
export default {
  name: 'Son',
  data () {
    return {
      money: 30000
    }
  },

  methods: {
    tinghua(){
        console.log('我是小明,我听爸爸的话');
    },
    geiQian(money){
       this.money-=money;
       this.$parent.money+=money;
    }
  }
}
</script>

作用域插槽

// 父组件
<template>
  <div>
    <h2>效果一: 显示TODO列表时, 已完成的TODO为绿色</h2>
    <List :todos="todos">
        <!-- 书写template -->
        <template slot-scope="todo">
            <h5 :style="{color:todo.todo.isComplete?'green':'black'}">{{todo.todo.text}}</h5>
        </template>
    </List>
     <List :todos="todos">
        <!-- 书写template -->
        <template slot-scope="todo">
            <a :style="{color:todo.todo.isComplete?'green':'black'}">{{todo.todo.text}}</a>
        </template>
    </List>
    <hr>
    <h2>效果二: 显示TODO列表时, 带序号, TODO的颜色为蓝绿搭配</h2>
    <List1 :data="todos">
         <template slot-scope="{row,index}">
               <h1 :style="{color:row.isComplete?'green':'hotpink'}">索引值{{index}}---------{{row.text}}</h1>
         </template>
    </List1>
  </div>
</template>

<script type="text/ecmascript-6">
  //子组件
  import List from './List'
  import List1 from './List1'
  export default {
    name: 'ScopeSlotTest',
    data () {
      return {
        todos: [
          {id: 1, text: 'AAA', isComplete: false},
          {id: 2, text: 'BBB', isComplete: true},
          {id: 3, text: 'CCC', isComplete: false},
          {id: 4, text: 'DDD', isComplete: false},
        ]
      }
    },

    components: {
      List,
      List1 
    }
  }
</script>



// 子组件
<template>
  <ul>
    <li v-for="(todo,index) in data" :key="index">
       <!-- 坑:熊孩子挖到坑,父亲填坑 -->
       <!-- 数据来源于父亲:但是子组件决定不了结构与外网-->
       <slot :row="todo" :index="index "></slot>
    </li>
  </ul>
</template>

<script>
export default {
  name: 'List1',
  props: {
    data: Array
  }
}
</script>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值