vue 组件数据交互

父组件向子组件传值

组件内部通过props接受传递过来的值

可以同时传递多个值,在props中添加多个值即可

Vue.component('menu-item',{
  props: ['title'],
  template: '<div>{{ title }}</div>'
})

父组件通过属性将值传递给子组件

//通过属性将值传递给子组件
<menu-item title="来自父组件的数据"></menu-item>
//通过v-bind将值传给子组件 <menu-item :title="title"></menu-item>

props属性名规则

  • 在prop中使用驼峰形式,模板中需要使用短横线的形式
  • 字符串形式的模板中没有这个限制
Vue.component('menu-item',{
  //在JavaScript中是驼峰式的   props: ['title'],   template: '<div>{{ menuTitle }}</div>' })
<!-- 在html中是短横线形式的 但是 -->
<menu-item menu-title="你好"><menu-item>

如果我们在使用时使用的是驼峰形式的

<menu-item menuTitle="你好"><menu-item>

虽然浏览器不会报错但是会给出以下警告

 但是在字符串模板中使则用不会出现这种情况

props属性值类型

  • 字符串String
  • 数值number
  • 布尔值Boolean
  • 数组Array
  • 对象Object
<div id="app">
    <div>{{pmsg}}</div>
    <menu-item :pstr='pstr' :pnum='12' :pboo='true' :parr='parr' :pobj='pobj'></menu-item>
  </div>
Vue.component('menu-item', {
      props: ['pstr','pnum','pboo','parr','pobj'],
      template: `
        <div>
          <div>{{pstr}}</div>
          <div>{{12 + pnum}}</div>
          <div>{{pboo}}</div>
          <ul>
            <li :key='index' v-for='(item,index) in parr'>{{item}}</li>
          </ul>
            <span>{{pobj.name}}</span>
            <span>{{pobj.age}}</span>
          </div>
        </div>
      `
    });
    var vm = new Vue({
      el: '#app',
      data: {
        pstr: 'hello',
        parr: ['apple','orange','banana'],
        pobj: {
          name: 'lisi',
          age: 12
        }
      }
    });

通过props将值传递给子组件,最后运行的结果是

但是这里需要注意的是数值(Number)和布尔值(Boolean)类型的值,如果我们使用的不是v-bind传值,而是属性传值的话,我们可以通过typeof查看一下它传递过来值的类型。

<div id="app">
    <div>{{pmsg}}</div>
    <menu-item :pstr='pstr' pnum='12' pboo='true'></menu-item>
  </div>
Vue.component('menu-item', {
      props: ['pstr','pnum','pboo','parr','pobj'],
      template: `
        <div>
          <div>{{pstr}}</div>
          <div>{{typeof pnum}}</div>
          <div>{{typeof pboo}}</div>
        </div>
      `
    });

运行得到结果

我们可以看到最终得到的是string类型,所以在传值时我们还是使用v-bind进行传值

子组件向父组件传值

首先我们来看一个例子

<div id="app">
        <menu-item :parr='parr'></menu-item>
    </div>
Vue.component('menu-item', {
            props: ['parr'],
            template: `
        <div>
          <ul>
            <li :key='index' v-for='(item,index) in parr'>{{item}}</li>
          </ul>
          <button @click='parr.push("d")'>点击</button>
        </div>
      `
        });
        var vm = new Vue({
            el: '#app',
            data: {
                parr: ['a', 'b', 'c'],
            }
        });

看运行的结果:

当我们点击按钮之后可以看到页面的变化,同时我们通过控制台来查看data中parr的数据变化 

 可以看到页面和data中的数据都变化了,并且保持着一致,说明传值成功了,但是我们并不推荐这么做,因为porps 传递数据原则是单项数据流===>只允许父组件可以直接将值传递给子组件,不允许子组件直接操作父组件数据

那么我们如果向父组件传值呢?

1、子组件通过自定义事件向父组件传递信息

//自定义的事件必须通过$emit定义 
<button @click='$emit("enlarge-text")'>扩大字体</button>
//携带参数的事件
<button @click='$emit("enlarge-text",0.5)'>扩大字体</button>

2、父组件监听子组件的事件

//监听无传递值的事件
<menu-item @enlarge-text='fontSize += 0.1'></menu-item>
//监听有传递值的事件 传递过来的值必须以$event表示
//如果组件函数是写在Vue组件中,也必须用$event表示接收的传递值
<menu-item @enlarge-text='fontSize += $event'></menu-item>

非父子组件间传值

1、单独的事件中心管理组件的通信

 

通过事件中心进行值的传递,需要单独new一个Vue实例作为事件中心

var eventHub = new Vue()

2、监听事件与销毁事件

eventHub.$on('add-todo',addTodo)
eventHub.$off('add-todo')

3、触发事件

eventHub.$emit('add-todo',id)

这里的id是你要传递的参数

我们通过一个实例来验证一下

<div id="app">
        <div>父组件</div>
        <div>
            <button @click='handle'>销毁事件</button>
        </div>
        <test-a></test-a>
        <test-b></test-b>
    </div>

// 提供事件中心
        var hub = new Vue();
        Vue.component('test-a', {
            data: function() {
                return {
                    num: 0
                }
            },
            template: `
        <div>
          <div>a:{{num}}</div>
          <div>
            <button @click='handle'>点击</button>
          </div>
        </div>
      `,
            methods: {
                handle: function() {
                    hub.$emit('b-event', 2);
                }
            },
            mounted: function() {
                // 监听事件
                hub.$on('a-event', (val) => {
                    this.num += val;
                });
            }
        });
        Vue.component('test-b', {
            data: function() {
                return {
                    num: 0
                }
            },
            template: `
        <div>
          <div>b:{{num}}</div>
          <div>
            <button @click='handle'>点击</button>
          </div>
        </div>
      `,
            methods: {
                handle: function() {
                    // 触发兄弟组件的事件
                    hub.$emit('a-event', 1);
                }
            },
            mounted: function() {
                // 监听事件
                hub.$on('b-event', (val) => {
                    this.num += val;
                });
            }
        });
        var vm = new Vue({
            el: '#app',
            data: {

            },
            methods: {
                handle: function() {
                    hub.$off('a-event');
                    hub.$off('b-event');
                }
            }
        });

运行之后,当我们点击a按钮时,b的值会增加2,点击b按钮时,a的值会增加1,这里我们a按钮和b按钮都点击了3次

 

posted @ 2020-12-17 16:12  黎沐不吃香菜  阅读(288)  评论(0)    收藏  举报