Vue.js学习记录-5-Vue进阶:组件

6.组件 - 计数器Demo为例

  • 组件使用细节

    • 全局组件 and 局部组件

      全局组件:

        	// 全局组件(子组件)
            Vue.component('row', {
                template: '<tr><td>{{ content }}</td></tr>',
                // 2. 子组件中的data必须是函数方法形式返回唯一的数据对象
                data: function () {
                    return {
                        content: 'this is content'
                    }
                }
            }),
      

      局部组件: 在根组件中需要声明局部组件

        	var counter = {
        		template: '<tr><td>{{ content }}</td></tr>',
                // 2. 子组件中的data必须是函数方法形式返回唯一的数据对象
                data: function () {
                    return {
                        content: 'this is content'
                    }
                }
        	}
      
        	var vm = new Vue({
                el: "#root",
                // 声明局部组件
                components: {
                    counter: counter
                },
        	)}
      
    • 组件复用:组件进行任意次数的复用

        	<!-- 计数器Demo -->
            <counter @change="handleChange" ref="one"></counter>
            <counter @change="handleChange" ref="two"></counter>
      
    • 组件中 data 必须是一个函数,每个组件实例可以维护一份被返回对象的独立拷贝。

  • 父子组件传值

  • 父组件通过属性props向子组件进行传值

     	<div id="root">
             <!-- 父组件通过属性向子组件进行传值 -->
             <counter :count="0" @inc="handleIncrease"></counter>
             <counter :count="0" @inc="handleIncrease"></counter>
             <div>{{ total }}</div>
     	</div>
    

    可以看出,上述代码通过:count,绑定了count属性,并添加了@inc自定义事件。

    父组件(根组件)通过**:count**,对子组件进行传值。此时,子组件通过props对父组件传值进行获取。

     	// 定义局部组件
         var counter = {
             // 子组件通过props获取父组件传过来的值。注意:子组件不可直接对props中的数据进行更改,单向数据流原理。
             props: ['count'],
             // 对父组件传递过来的值,子组件进行备份后进行更改
             data: function () {
                 return {
                     number: this.count
                 }
             },
             // 下文待填充
         }
    
  • 子组件通过事件$emit向父组件进行传值

    通过上述操作,子组件可以对父组件的数据进行获取,并由于单项数据流原理进行了备份

    接下来,根据备份的父组件数据number进行模板渲染

     	template: "<div @click='handleCilck'>{{ number }}</div>",
    

    此时,在子组件渲染的<div>中添加了click事件,当块级元素被点击时,向父组件进行传值。

     	methods: {
             handleCilck: function () {
                 this.number ++
                 // 向父组件传递已更改的值,触发事件
                 this.$emit('inc', 1)
             }
         }
    

    点击该块级元素时,备份数据number执行自增操作,之后,通过$emit方法进行自定义事件inc声明,以及参数传递

     上述提到的**@inc="handleIncrease"**,在父组件接收子组件的触发事件,并获取事件携带参数。
    
     	var vm = new Vue({
             el: "#root",
             // 声明局部组件
             components: {
                 counter: counter
             },
             data: {
                 total: 0
             },
             methods: {
                 // 接收子组件触发事件,获取事件携带参数
                 handleIncrease: function (step) {
                     this.total += step
                 }
             }
         })
    

    自定义方法inc所对应的 handleIncrease 方法触发后,响应式更新数据 total 的值

  • 组件的参数校验与非Props特性

    • Prop验证:组件的 prop 指定验证要求,对格式、长度等方面进行参数验证。

        <child content="hello "></child>
      

      子组件中添加Prop验证:

        Vue.component('child', {
            props: {
                content :{
                    // 类型验证,数组可包含多个数据类型
                    type: [String, Number],
        			// 是否必需
                    required: false,
        			// 默认值
                    default: 'default value',
        			// 参数长度判断
                    validator: function (value) {
                        return (value.length > 5)
                    }
                }
            },
            template: '<div>{{content}}</div>',
        })
      
    • Props特性和非Props特性

      Props特性:常规配置,父组件传值、子组件接值、DOM内直接使用。
      在这里插入图片描述
      非Pros特性:

        1. 子组件未通过props接收,因此不能显示在DOM上。
        2. 子组件模板内直接写入内容而非插值表达式,会显示在DOM最外层标签上。
      

    在这里插入图片描述

  • 组件绑定原生事件

    在组件的根元素上直接进行原生事件的监听,此时可以使用v-on的.native修饰符

      <div id="root">
      	<!-- 子组件中绑定原生的点击事件 -->
          <child @click.native="handleCilck"></child>
      </div>
    
      <script>
          Vue.component('child', {
              template: '<div>Child</div>'
          })
    
          var vm = new Vue({
              el: "#root",
              methods: {
                  handleCilck: function () {
                      alert("组件绑定原生事件")
                  }
              }
          })
      </script>
    
  • 非父子组件间传值(Bus/总线/发布订阅模式/观察者模式)

    业务场景如下,图片取自Vue.js官网文档,非父子组件进行传值的几种形式。
    在这里插入图片描述

    举例: 兄弟组件之间的传值问题,页面如下:

      <div id="root">
          <child content="Tom"></child>
          <child content="Jerry"></child>
      </div>
    

    组件中的设置:

      // 对Vue中prototype的bus属性添加vue实例
      Vue.prototype.bus = new Vue()
    
      // 全局组件
      Vue.component('child', {
          // 组件模板
          template: "<div @click='handleClick'>{{selfContent}}</div>",
          // 父组件通过props进行数据传递
          props: {
              content: {
                  // 数据传递约束
                  type: String,
                  required: true
              }
          },
          // 应对单项数据流问题,建立数据副本
          data: function () {
              return {
                  selfContent: this.content
              }
          },
          methods: {
              handleClick: function () {
                  // 由于bus属性是一个vue实例,因此可以使用$emit进行事件的声明,携带参数,当前数据副本
                  this.bus.$emit('change',  this.selfContent)
              }
          },
          // 生命周期钩子函数
          mounted() {
              // 防止this作用域发生变化,创建保存副本
              var this_ = this
      		// 使用$on进行自定义事件change的处理
              this.bus.$on('change', function (msg) {
                  this_.selfContent = msg
              })
          },
      })	
    

    TIPS:采用 $emit 和 $on 实现非父子组件的传值操作,需要注意的是:$emit 和 $on 事件必须在一个公共实例上,才能触发。(本例中,公共实例为:bus )

  • v-once指令和动态组件

    动态组件场景,页面中需要通过按钮进行组件的切换

    页面:针对组件添加v-if,进行组件判断

      <div id="root">
          <child-one v-if="type === 'child-one'"></child-one>
          <child-two v-if="type === 'child-two'"></child-two>
          <button @click="handleBtnClick">change</button>
      </div>
    

    组件配置: 在handleBtnClick方法中,根实例进行三元表达式判断,通过data中的type进行组件切换

      <script>
          Vue.component('child-one', {
              template: '<div>child-one</div>'
          })
    
          Vue.component('child-two', {
              template: '<div>child-two</div>'
          })
    
          var vm = new Vue({
              el: '#root',
              data: {
                  type: 'child-one'
              },
              methods: {
                  handleBtnClick: function () {
                      this.type = this.type === 'child-one' ? 'child-two' : 'child-one'
                  }
              }
          })
      </script>
    

    改造上述代码:

    1. component为动态组件,属性is绑定组件名称(对应根实例中data中的type)。

       <!-- component标签为动态组件 属性is绑定组件名称 -->
       <component :is="type"></component>	
      
    2. 采用v-once指令,提高静态数据内容的渲染效率。

       template: '<div v-once>child-one</div>'
      

    TIPS:本篇内容关于Vue中is特性以及ref和$refs的使用将在后续博文中补充说明。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

编程小透明

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值