Web全栈探索,Vue基础系列,组件化开发(三)组件之间的数据交互

一、父组件向子组件传值

步骤1.父组件通过属性将值传递给子组件

//静态传递
<div 属性名="来自父组件的数据"></div>


//动态绑定获取
<div :属性名="存储父组件传递数据的变量"></div>

步骤2.子组件内部通过props接收父组件传递过来的值

Vue.component(‘子组件名称', {
    props: ['属性名'],
    template: '<div>{{ 属性名 }}</div>'
})

示例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
<div id="app">
    <!--父组件使用子组件-->

    <!--纯静态可以使用-->
    <son-component key1='来自父组件的值1' key2="来自父组件的值2"></son-component>
    <!--纯动态可以使用-->
    <son-component :key1='infoOne' :key2='infoTwo'></son-component>
    <!--动态、静态可以结合使用-->
    <son-component key1='来自父组件的值' :key2='infoTwo'></son-component>
</div>
<script type="text/javascript" src="../../js/vue.js"></script>
<script type="text/javascript">

    // 定义子组件
    // 其中 key1、key2 两个属性为父组件的属性,并且这两个属性的值都会被子组件接收
    Vue.component('son-component', {
        props: ['key1', 'key2'],
        data: function() {
            return {
            }
        },
        template: '<div>{{key1 + "-----" + key2}}</div>'
    });

    // vue 的实例本身就是一个组件,并且是一个根组件,因此它可以使用任何自定义组件
    let vm = new Vue({
        el: '#app',
        data: {
            msg: '父组件中内容',
            infoOne: '用于给子组件传递数据的绑定变量',
            infoTwo: 'this is the result'
        }
    });
</script>
</body>
</html>

注意事项:

1.在props中使用驼峰形式,模板中需要使用短横线的形式(dom 元素的属性是不区分大小写的);字符串形式的模板中没有这个限制

Vue.component(‘component-a', {

    // 在 JavaScript 中是驼峰式的
    props: [‘valueData'],
    template: '<div>{{ valueData }}</div>'
})


<!– 在html中是短横线方式的 -->
<menu-item value-data=“测试数据"></menu-item>

2.props属性值类型

  • 字符串 String
  • 数值 Number
  • 布尔值 Boolean
  • 数组 Array
  • 对象 Object

传值的时候,如果采用的是静态传递,则所有的数据都会被当作字符串处理

传值的时候,如果采用的是动态属性绑定,则数据会按照原值类型处理

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
<div id="app">
    <!--动态属性绑定-->
    <component-a :one='one_data' :two='two_data' :three='three_data' :four='four_data' :five='five_data'></component-a>
    <!--静态数据传递-->
    <component-a one='this is the result' two='100' three='true' four='[1, 2, 3, 4, 5]' five="{'id': 1, 'name': 'lanYue'}"></component-a>
</div>
<script type="text/javascript" src="../../js/vue.js"></script>
<script type="text/javascript">
    /*
      父组件向子组件传值-props属性值类型
    */

    Vue.component('component-a', {
        props: ['one', 'two', 'three', 'four', 'five'],
        template: `
            <div>
                <div>{{typeof one}}</div>
                <div>{{typeof two}}</div>
                <div>{{typeof three}}</div>
                <div>{{typeof four}}</div>
                <div>{{typeof five}}</div>
            </div>
        `
    });
    let vm = new Vue({
        el: '#app',
        data: {
            one_data: 'this is the result',
            two_data: 100,
            three_data: true,
            four_data: [1, 2, 3, 4, 5],
            five_data:{'id': 1, 'name': 'lanYue'}
        }
    });
</script>
</body>
</html>

二、子组件向父组件传值

1.props传递数据原则

单向数据流,只允许父组件向子组件传递数据,而不建议子组件直接操作 props 中的数据(虽然允许,但不推荐)

2.子组件向父组件传递数据方法

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

$emit("事件名称")

(2).父组件监听子组件的事件

<子组件名称 v-on:='事件名称'></子组件名称>

(3)举例——子组件向父组件传递已有数据(变更后的)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
<div id="app">
    <div :style='{fontSize: fontSize + "px"}'>{{msg}}</div>
    <!--父组件需要监听事件时,只需要使用 @ 符号 加上事件的名称即可,等号右边为处理逻辑或者监听成功后要执行的函数-->
    <!--父组件为 key 属性绑定值并且传给子组件-->
    <!--父组件监听 enlarge-text 事件-->
    <!--子组件通过 my_key 属性绑定 key_data数据-->
    <component-a :my_key="key_data" @enlarge-text='handle'></component-a>
</div>
<script type="text/javascript" src="../../js/vue.js"></script>
<script type="text/javascript">

    Vue.component('component-a', {
        // 子组件监听 key 属性
        props: ['my_key'],
        // $emit 用于触发自定义事件,参数为事件名称,可以自定义名称
        // 子组件自定义事件,用于向父组件传递数据
        template: `
        <div>
          <button @click='$emit("enlarge-text")'>{{my_key}}</button>
        </div>
      `
    });
    let vm = new Vue({
        el: '#app',
        data: {
            msg: '测试数据',
            key_data: '扩大字体',
            fontSize: 10
        },
        methods: {
            handle: function(){
                // 扩大字体大小
                this.fontSize += 5;
            }
        }
    });
</script>
</body>
</html>

(4)举例——子组件向父组件传递新数据

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
<div id="app">
    <div :style='{fontSize: fontSize + "px"}'>{{msg}}</div>
    <!--父组件通过 $event 获取子组件传递过来的数据-->
    <component-a :my_key="key_data" @enlarge-text='handle($event)'></component-a>
</div>
<script type="text/javascript" src="../../js/vue.js"></script>
<script type="text/javascript">

    /*
      子组件通过 $emit 的第一个参数用于注册事件,第二个参数 用于作为时间的参数向父组件传递数据
    */
    Vue.component('component-a', {
        props: ['my_key'],
        template: `
        <div>
          <button @click='$emit("enlarge-text", 5)'>{{my_key}}</button>
        </div>
      `
    });
    let vm = new Vue({
        el: '#app',
        data: {
            msg: '测试数据',
            key_data: '扩大字体',
            fontSize: 10
        },
        methods: {
            // 父组件得到子组件传递而来的参数
            handle: function(arg){
                // 扩大字体大小
                this.fontSize += arg;
            }
        }
    });
</script>
</body>
</html>

三、非父子组件间传值

非父子组件(一般指兄弟组件)之间传递数据需要用到事件中心,它们之间的关系如下:

1.具体步骤:

1. 单独的事件中心(由新 new 的 vue 实例对象扮演)管理组件间的通信

let 事件中心变量名 = new Vue()

2. 监听事件与销毁事件

事件中心变量名.$on('自定义事件名称', '事件函数')
事件中心变量名.$off('自定义事件名称')

3. 触发事件

事件中心变量名.$emit(‘自定义事件名称', 携带任意参数)

2.示例代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
<div id="app">
    <div>
        <button @click='handle'>销毁事件</button>
    </div>
    <one-component></one-component>
    <two-component></two-component>
</div>
<script type="text/javascript" src="../../js/vue.js"></script>
<script type="text/javascript">

    /*
      兄弟组件之间数据传递
    */
    // 提供事件中心
    let hub = new Vue();

    // 注册组件一
    Vue.component('one-component', {
        data: function () {
            return {
                num: 1
            }
        },
        template: `
            <div>
                <div>组件一:{{num}}</div>
                <div>
                    <button @click='handle'>点击加二</button>
                </div>
            </div>
        `,
        methods: {
            // 组件一自定义 触发组件二变化的 事件二,并传递参数 2
            handle: function () {
                hub.$emit('two-event', 2);
            }
        },
        mounted: function () {
            // 事件中心监听引发 组件一 变动的事件一
            hub.$on('one-event', (val) => {
                this.num += val;
            });
        }
    });


    Vue.component('two-component', {
        data: function () {
            return {
                num: 2
            }
        },
        template: `
            <div>
                <div>组件二:{{num}}</div>
                <div>
                    <button @click='handle'>点击加二</button>
                </div>
            </div>
        `,
        methods: {
            handle: function () {
                // 组件二自定义 触发组件一变化的 事件一,并传递参数 2
                hub.$emit('one-event', 2);
            }
        },
        mounted: function () {
            // 事件中心监听引发 组件二 变动的事件一
            hub.$on('two-event', (val) => {
                this.num += val;
            });
        }
    });

    let vm = new Vue({
        el: '#app',
        data: {},
        methods: {
            handle: function () {

                // 利用事件中心销毁组件一、二的事件
                hub.$off('one-event');
                hub.$off('two-event');
            }
        }
    });
</script>
</body>
</html>
作者:蓝月

-------------------------------------------

个性签名:能我之人何其多,戒骄戒躁,脚踏实地地走好每一步

原文地址:https://www.cnblogs.com/viplanyue/p/13573723.html