Vue 常见组件通信

目录

1.props 父组件向子组件传值

2.$emit $on  子组件向父组件传值

3.$bus 非父子组件传值

4.$children  $parent   非响应式   作为访问组件的应急方法

5.ref

6.$attrs  $listeners

7.  .sync属性修饰符

8.$event 事件

9.v-model 双向数据绑定

10.  mixin混入  插槽  vuex...


1.props 父组件向子组件传值

1.在子组件标签上绑定一个自定义属性 自定义属性值为要传递的数据

<child :zdy='user' :good='goods'></child>

2.在子组件对象中使用 prop属性 来接收父组件传递过来的自定义属性

 props: {
            num: Object,
            // 验证多个数据类型
            str: {
                type: [String, Number]
            })

3.使用props属性接收的自定义属性使用方式和data中数据使用方式一样

当需要验证自定义属性数据时,props可以为一个对象 当props属性为一个数组时,表示可以接收任意数据类型 当props属性为一个对象时,表示需要对接收的自定义属性进行数据类型校验

父组件  完整代码

   <div id="app">
        <!-- 在子组件标签上绑定一个自定义属性  自定义属性值为要传递的数据 -->
        <child :zdy='user' :good='goods'></child>
    </div>
    <template id="child">
        <div class="cc">
            <h1>我是子组件</h1>
            <h3>props接收的自定义属性 {{zdy}} {{good}}</h3>
            <mya :nums='num'></mya>
        </div>
    </template>

    <template id="a">
        <div>
            <h1>我是a组件{{nums}}</h1>
        </div>
    </template>
</body>
<script src="../vue.js"></script>
<script>
    let a = {
        template: "#a",
        props: ["nums"]
    }
    let child = {
        template: '#child',
        props: ['zdy', 'good'],
        components: {
            "mya": a
        },
        data() {
            return {
                num: 0
            }
        }
    }

    new Vue({
        el: "#app",
        data: {
            user: "roy",
            goods: {
                name: "水杯",
                price: 12
            }
        },
        components: {
            child
        },
    })
</script>

子组件  完整代码

<body>
    <div id="app">
        <child :num='num' :str='str'></child>
    </div>
    <template id="child">
        <div>
            <h1>我是子组件 {{num}} {{str}} {{like}}</h1>
        </div>
    </template>
</body>
<script src="../vue.js"></script>
<script>
    let child = {
        template: '#child',
        props: {
            num: Object,
            // 验证多个数据类型
            str: {
                type: [String, Number]
            },
            // 若props接收不到属性时,可以设置一个默认值
            like: {
                type: String,
                // 设置默认值
                default: function () {
                    return "打篮球"
                }
            }
        }
    }

    Vue.component('child', child);
    new Vue({
        el: "#app",
        data: {
            num: {
                user: "张三"
            },
            str: '1',
            like: ""
        }
    })
</script>

2.$emit $on  子组件向父组件传值

使用$emit属性向父组件发送一个自定义事件   参数一自定义事件名称 参数二要传递的数据 参数三要传递的数据.... 参数可以是任意数据类型

 this.$emit('getmsg', this.msg, this.name, this.goods)

在父组件中 绑定一个子组件发送过来的自定义事件 自定义事件不可以有大写字母

  <child @getobj='getmsg'></child>

父组件  完整代码

<body>
    <div id="app">
        <my-parent></my-parent>
    </div>
    <!-- 子组件 -->
    <template id="par">
        <!-- 在组件模板中有且只能有一个根元素 -->
       <div>
            <h2>评论人:</h2>
            <input type="text" v-model='name'>
            <h2>评论内容:</h2>
            <textarea  rows="10" v-model='content'></textarea>
            <button @click='send()'>发表</button>
       </div>
    </template>
    <!-- 父组件 -->
    <template id="child">
        <div>
            <!--1. 子组件 绑定自定义事件接受参数  @getobj='getmsg' -->
            <child @getobj='getmsg'></child>
            <h1>留言板</h1>
            <div>
                <div v-for='(item,index) in list' class="list">
                    <div>
                        作者:{{item.name}}
                    </div>
                    <div>
                        内容:{{item.content}}
                        <button class="remove" @click='remove(index)'>删除</button>
                        <div style="clear: both;"></div>
                    </div>
                </div>
                <p v-show='list.length==0'>
                    暂无数据~~~
                </p>
            </div>
        </div>
    </template>
</body>
<script src="../vue.js"></script>
<script>
     let child = {
        template:"#par",
        
        data() {
            return {
                name:"",
                content:"",
                obj:{}
            }
        },
        methods: {
            send(){
                this.obj = {
                    name:this.name,
                    content:this.content
                }
                
                //2. 发送自定义事件
                this.$emit('getobj', this.obj);
                this.name='';
                this.content = ''
            }
        },
    }
    let parent = {
        template:"#child",
        components:{
            child
        },
        data() {
            return {
                list:[
                   {
                       name:"小明",
                       content:"小明是个帅哥"
                   },{
                       name:"小红",
                       content:"小红是个美女"
                   }
                ],
            }
        },
        methods: {
            // 3. 接收信息
            getmsg(value){
                console.log(value)
                this.list.push(value)

            },
            remove(index){
                this.list.splice(index,1)
            }
        },
    }
   
    // 小驼峰命名的组件名称使用时大写变小写并用-连接
    Vue.component("myParent",parent)
    new Vue({
        el:"#app",
        data:{
           
        },
       
    })
</script>

3.$bus 非父子组件传值

1.创建一个新的vue实例  bus.js

    let bus = new Vue();

2.在组件中使用新的vue实例$emit发送自定义事件

 bus.$emit("getobj",this.obj)

3.在要接受数据的组件中使用新的vue实例$on方法监听自定义事件调用

  bus.$on("getobj",(value)=>{
                console.log(value)
                this.list.push(value)
            })

 非父子  完整代码

<body>
    <div id="app">
        <my-parent></my-parent>
        <child></child>
    </div>
    <template id="par">
        <!-- 在组件模板中有且只能有一个根元素 -->
       <div>
            <h2>评论人:</h2>
            <input type="text" v-model='name'>
            <h2>评论内容:</h2>
            <textarea  rows="10" v-model='content'></textarea>
            <button @click='send()'>发表</button>
       </div>
    </template>
    <template id="child">
        <div>
            <h1>留言板</h1>
            <div>
                <div v-for='(item,index) in list' class="list">
                    <div>
                        作者:{{item.name}}
                    </div>
                    <div>
                        内容:{{item.content}}
                        <button class="remove" @click='remove(index)'>删除</button>
                        <div style="clear: both;"></div>
                    </div>
                </div>
            </div>
        </div>
    </template>
</body>
<script src="../vue.js"></script>
<script>
   // 1.定义一个新的vue实例
    let bus = new Vue();
    let child = {
        template:"#child",
        props:["msg"],
        data() {
            return {
                list:[
                   {
                       name:"小明",
                       content:"小明是个帅哥"
                   },{
                       name:"小红",
                       content:"小红是个美女"
                   }
                ],
            }
        },
        created() {
           // 3. $on监听自定义事件
            bus.$on("getobj",(value)=>{
                console.log(value)
                this.list.push(value)
            })
        },
        methods: {
            remove(index){
                this.list.splice(index,1)
            }
        },
    }
    let parent = {
        template:"#par",
        data() {
            return {
                name:"",
                content:"",
                obj:{}
            }
        },
        methods: {
            send(){
                this.obj = {
                    name:this.name,
                    content:this.content
                };
                // 2. $emit发送自定义事件
                bus.$emit("getobj",this.obj)
            }
        },
    }
    // 小驼峰命名的组件名称使用时大写变小写并用-连接
    Vue.component("myParent",parent)
    Vue.component("child",child)
    new Vue({
        el:"#app",
        data:{ 
        },  
    })
</script>

4.$children  $parent   非响应式   作为访问组件的应急方法

$children 获取当前组件的所有子组件,以数组形式存在,从而可以操作子组件数据

 this.$children.属性名 = ...

$parent 获取当前组件的父组件,从而可以操作父组件数据

如果组件没有父组件,他的$parent为undefined,App组件(根组件)的$parent不是undefined,也不是App本身。

如果组件有多个父亲,$parent只能找到一个

 this.$parent.属性名 = ...

父组件

<template>
  <div style="background-color: #999">
    <h2>儿子金钱:{{ sonMoney }}</h2>
    <button @click="giveFatherMoney(100)">给父亲100</button>
  </div>
</template>
 
<script>
export default {
  name: "Son",
  props: ["fatherMoney"],
  data() {
    return {
      sonMoney: 20000,
    };
  },
  methods: {
    giveFatherMoney(money) {
      this.$parent.fatherMoney += money;
      this.sonMoney -= money;
    },
  },
};
</script>
 
<style>
</style>

5.ref

ref 被用来给元素或子组件注册引用信息,引用信息将会注册在父组件的 $refs 对象上

组件元素只能通过 ref 获取的标签方法、变量、....  ;

普通的元素标签可以使用 ref或者id或者... 获取标签 ;

使用方法:this.$refs.名称

<button ref="qw">  //子组件 
this.$refs.qw = ...  // 父组件

6.$attrs  $listeners

$attrs$listeners的主要应用是实现多层嵌套传递。

1.$attrs 组件的一个属性,可以获取到父组件传递过来的props数据,和props作用一样

console.log(this.$attrs)  ==  props:["数据"]

不能获取class、style和事件属性,在嵌套层级比较深的组件中$attrs拿值更加便捷,可以通过 v-bind="$attrs" 传入内部组件


<child-com class="com" name="attr" :foo="foo" :boo="boo" @click="test"></child-com>
...
data() {
  return {
    foo: 'Hello World!',
    boo: 'Hello Javascript!',
  }
},
...

// child-com.vue
 export default {
  name: 'childCom',
  components: {
    childCom2
  },
  created() {
    console.log(this.$attrs)
 // {name: "attr", foo: "Hello World!", boo: "Hello Javascript!"}
  }
}

$attrs只代表的是那些没有被声明为props的属性,如果某个prop被子组件中声明了(就是这个属性已经在子组件的props中了),在子组件中的$attr会把声明的prop剔除


<child-com class="com" name="attr" :foo="foo" :boo="boo" @click="test"></child-com>
...
data() {
  return {
    foo: 'Hello World!',
    boo: 'Hello Javascript!',
  }
},
...
// child-com.vue
 export default {
  name: 'childCom',
  props: ['foo'], // foo被声明
  components: {
    childCom2
  },
  created() {
    console.log(this.$attrs) 
// {name: "attr", boo: "Hello Javascript!"} 
// foo已被props声明,所以$attrs拿不到foo
  }
}

2.$listeners 属于组件的一个属性,可以获取到父组件传递过来的事件(如点击事件等)

包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器

通过在自己的子组件上使用v-on=$listeners”,进一步把值传给自己的子组件。如果子组件已经绑定$listener中同名的监听器,则两个监听器函数会以冒泡的方式先后执行。

父组件  完整代码

 <template>
    <div class="test">
        <child  v-bind="{name, sex, age}" v-on="{changeName,changeAge}"></child>
    </div>
</template>

<script>
import child from './child'

export default {
    data() {
        return {
          name: '张三',
          sex: '男',
          age: 11,
        }
    },
    components: {
        child
    },
    methods: {
        changeName(name) {
            this.name = name
        },
        changeAge(age) {
            this.age = age
        }
    }
}
</script>

子组件  完整代码

<template>
    <div class="child">
        child组件的$attrs {{$attrs}}
         // v-bind v-on 不能替换为 : 和 @
        <child-child v-bind="$attrs" v-on="$listeners" @showAttrs="showAttrs"></child-child>
    </div>
</template>

<script>
import childChild from  './child-child'
export default {
    name: "child",
    props: ['name'],
    inheritAttrs: false,
    created() {
        console.log('child', this.$listeners) 
    },
    components: {
        childChild
    },
    methods: {
        showAttrs() {
            console.log(this.$attrs)
        }
    }
}
</script>

孙组件  完整代码

<template>
    <div class="child-child">
        child-child组件的$attrs {{$attrs}}
    </div>
</template>

<script>
export default {
    name: "child-child",
    inheritAttrs: false,
    created() {
      console.log('child-child',this.$listeners)  
    }
}
</script>

7.  .sync属性修饰符

父组件监听子组件更新props的请求,实现父子组件的数据同步

1.在父组件中的子组件添加: :child-value.sync ='value'

 <table-case
   :child-value.sync ='value'
   // :case-list.sync="solutionInfo.caseListJson"
  />

2.Vue看到 .sync关键字会自动为子组件创建一个叫做 update:childValue或update:child-value的事件,(这两种事件名都可以成功调用) 这个事件可以接受参数,并自动将参数赋给父组件的 value

3.在子组件想要修改时使用$emit触发事件并传入新的值,让父组件进行修改

<button @click="$emit("update:child-value","要改变的数据")"></button>
// this.$emit("update:case-list" , "要改变的数据")

8.$event 事件

获取原生DOM事件的事件对象

在DOM事件的回调函数中传入参数$event(@change="updateProduct($event)"),可以获取到该事件的事件对象

<button data-get="数据按钮" @click="getRvent($event)">获取事件对象</button>


 //script中 获取事件对象event
 getRvent(e){
  console.log(e);
 // e.srcElement.style.background="red";
 }

9.v-model 双向数据绑定

数据改变视图更新,视图更新数据改变

双向数据绑定v-model 只能作用在表单标签中!!!!!!

  v-model实质上就是v-bind和v-on的一个语法糖
  不使用v-model实现双向数据绑定的过程:
​      1.绑定一个value属性(v-bind(:))
​      2.绑定一个input事件(v-on(@))

<body>
    <div id="app">
          <input type="text" v-model="msg">
        <!-- 输入框内容发生改变 改变data中的数据 -->
          <p>{{msg}}</p>
    </div>
</body>
<script src="../vue.js"></script>
<script>
    new Vue({
      el:"#app",
      data:{
          msg:"roy"
      }
    })
</script>

10.  mixin混入  插槽  vuex...

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值