vue组件通信传值

x33g5p2x  于2021-08-23 转载在 Vue.js  
字(6.4k)|赞(0)|评价(0)|浏览(432)

七 组件

7.1 全局组件

<zszxz-componen>就是 自定义标签, 命名格式使用分割符号;需要在组件中添加template 才可以显示内容;

<div id="app">
        <zszxz-component></zszxz-component>
    </div>
    <script type="text/javascript">
        Vue.component('zszxz-component',{
            // 选项
            template: '<div>知识追寻者 </div>'
        })
        var app = new Vue({
            el: '#app',
            data: {
                
               
            }
        })
    </script>

渲染结果

<div id="app">
        <div>知识追寻者 </div>
</div>

7.2 局部组件

在 vue实例中可以使用 components 选项 注入局部组件。

    <div id="app">
        <zszxz-component></zszxz-component>
    </div>
    <script type="text/javascript">
        var child = {
            template: '<div>知识追寻者 </div>'
        }
        var app = new Vue({
            el: '#app',
            components : {
                'zszxz-component' : child
            }
        })
    </script>

7.3 is 挂载组件

在特殊的标签中只能使用特殊的子标签;比如<table> 标签 中只能 存放<th> ,<td> ,<tr> ; 此时就需要使用 is 属性 挂载标签;

<div id="app">
        <table >
            <tbody is='zszxz-component'></tbody>
        </table>
    </div>
    <script type="text/javascript">
        var child = {
            template: '<div>知识追寻者 </div>'
        }
        var app = new Vue({
            el: '#app',
            components : {
                'zszxz-component' : child
            }
        })
    </script>

components 中还可以放 methods, computed, data等; data 必须是个函数;

data: function () {
return {
 count: 0
}
}

7.4 组件复用

三个按钮达到互不影响示例如下,如果data是外部对象则三个按钮都会对一个count进行计数;

 <div id="app">
     <zszxz-component></zszxz-component>
     <zszxz-component></zszxz-component>
     <zszxz-component></zszxz-component>
    </div>
    <script type="text/javascript">
        var child = {
            template: '<button @click="count++">{{count}} </button>',
            data : function(){
                return {
                    count:0
                }
            }
        }
        var app = new Vue({
            el: '#app',
            components : {
                'zszxz-component' : child
            }
        })
    </script>

7.5 props传递数据(父-子)

组件间的通信使用props实现;父组件向子组件正向传递,子组件接受数据进行渲染;子组件使用props 声明从父组件接受到数据,其方式有2种,分别是字符串数组和对象;

  1. 先在props 中声明 接受书的变量
  2. zszxz-component 中 的 content 内容传递给template 的 {{content }}
  <div id="app">
        <zszxz-component content="父级内容"></zszxz-component>
    </div>
    <script type="text/javascript">
        var child = {
            props: ['content'],
            template: '<div>{{content}}</div>',
        }
        var app = new Vue({
            el: '#app',
            components : {
                'zszxz-component' : child
            }
        })
    </script>

渲染结果

<div>父级内容</div>

如果传递的动态数据则需要使用v-bind进行动态绑定props值;

  1. 首先通过input标签输入的值经过 v-model绑定至meassage变量
  2. message变量再通过 v-bind 传递给 content;
  3. content 通过 props 传递给子组件;
 <div id="app">
        <input type="text" v-model="message" placeholder="请输入">
        <zszxz-component :content="message"></zszxz-component>
    </div>
    <script type="text/javascript">
        var child = {
            props: ['content'],
            template: '<div>{{content}}</div>',
        };
        var app = new Vue({
            el: '#app',
            components : {
                'zszxz-component' : child
            },
            data: {
                message: ''
            }
        })
    </script>

单向数据流

在 data 里面再声明一个变量实现 子组件与父组件间变量的解耦关系,之间操作content变量就不会改变init-content的值;

   <div id="app">
        <zszxz-component :init-content="6666"></zszxz-component>
    </div>
    <script type="text/javascript">
        Vue.component('zszxz-component',{
            props: ['initContent'],
            template: '<div>内容:{{content}}</div>',
            data: function() {
                return {
                    content: this.initContent
                }
            },
        });
        var app = new Vue({
            el: '#app',
        })
    </script>

HTML不区分大小写,使用DOM模板时,驼峰命名的props名称要转为分隔符命名

props验证

Vue.component('my-component', {
  props: {
    // 基础的类型检查 (`null` 和 `undefined` 会通过任何类型验证)
    propA: Number,
    // 多个可能的类型
    propB: [String, Number],
    // 必填的字符串
    propC: {
      type: String,
      required: true
    },
    // 带有默认值的数字
    propD: {
      type: Number,
      default: 100
    },
    // 带有默认值的对象
    propE: {
      type: Object,
      // 对象或数组默认值必须从一个工厂函数获取
      default: function () {
        return { message: 'hello' }
      }
    },
    // 自定义验证函数
    propF: {
      validator: function (value) {
        // 这个值必须匹配下列字符串中的一个
        return ['success', 'warning', 'danger'].indexOf(value) !== -1
      }
    }
  }
})

7.6 自定义事件(子-父)

vue.1.x ; v-on 除了 监听事件之外还可以自定义组件之间的事件;子组件使用$emit() 触发事件(子组件通向父组件),父组件使用$on来监听子组件事件;

  1. 点击 +1 按钮时会触发发addCount 函数;
  2. 进入addCount函数后 counter 加1,并通过 $emit 触发 父组件increase事件;
  3. increase 监听 getTotal函数,实现数量+1显示;
  <div id="app">
        <p>总数 : {{total}} </p>
        <zszxz-component @increase="getTotal" @reduce="getTotal"></zszxz-component>
    </div>
    <script type="text/javascript">
        Vue.component('zszxz-component',{
            template: '<div><button @click="addCount"> +1 </button> \
                      <button @click="subCount"> -1 </button> </div>',
            data: function() {
                return {
                    counter: 0
                }
            },
            methods: {
                addCount: function() {
                    this.counter++;
                    this.$emit('increase',this.counter);
                },
                subCount: function() {
                    this.counter--;
                    this.$emit('reduce',this.counter);
                }
            }
        });
        var app = new Vue({
            el: '#app',
            data: {
                total: 0
            },
            methods:{
                getTotal: function(total){
                    this.total = total;
                }
            }
        })
    </script>

如果想监听原生事件可以使用v-on.native 修饰符

<base-input v-on:focus.native="onFocus"></base-input>

7.7使用v-model实现自定义事件

vue.2.x 可以使用 v-model 实现 组件自定义事件;

<div id="app">
        <p>总数 : {{total}} </p>
        <zszxz-component v-model="total"></zszxz-component>
    </div>
    <script type="text/javascript">
        Vue.component('zszxz-component',{
            template: '<div><button @click="addCount"> +1 </button></div>',
            data: function() {
                return {
                    counter: 0
                }
            },
            methods: {
                addCount: function() {
                    this.counter++;
                    this.$emit('input',this.counter);
                }
            }
        });
        var app = new Vue({
            el: '#app',
            data: {
                total: 0
            },
        })
    </script>

7.8 消息总线bus

使用bus 可以实现 组件间通讯;如买房租房,bus就是第三方中介;

  1. 新建空vue实例做为bus,在钩子函数mounted中调用$on用于监听事件;
  2. 点击 按钮时会触发handleEvent事件,调用$emit触发 on-message事件;
  3. 事件触发后bus会监听到事件内容;
<div id="app">
        <p>消息 : {{message}} </p>
        <zszxz-component></zszxz-component>
    </div>
    <script type="text/javascript">
        var bus = new Vue();
        Vue.component('zszxz-component',{
            template: '<div><button @click="handleEvent"> 事件处理 </button></div>',
            methods: {
                handleEvent: function() {
                    bus.$emit('on-message','来自组件的内容');
                }
            }
        });
        var app = new Vue({
            el: '#app',
            data: {
                message: ''
            },
            mounted: function(){
                var _this = this;
                bus.$on('on-message', function(msg){
                    _this.message = msg;
                })
            }
        })
    </script>

7.9 子组件索引

当组件较多时,可以通过 ref 属性为每个组件指定索引名称;父组件通过$refs来访问子组件;

 <div id="app">
        <p>内容:{{content}}</p>
        <button @click="handleRef">点击</button>
        <zszxz-component ref="zszxz"></zszxz-component>
    </div>
    <script type="text/javascript">
        Vue.component('zszxz-component',{
            template: '<div>子组件 </div>',
            data: function(){
                return {
                    message: '知识追寻者'
                }
            }
        });
        var app = new Vue({
            el: '#app',
            data: {
                content: ''
            },
            methods: {
                handleRef : function(){
                    // 通过 $refs访问指定实例
                    var msg = this.$refs.zszxz.message;
                    this.content = msg;
                }
            }
        })
    </script>

相关文章