Vue核心基础(三)

71 阅读2分钟

组件

什么是组件

组件是可复用的 Vue 实例,且带有一个名字,可以把组件作为自定义元素来使用。

组件的出现就是为了拆分Vue实例的代码量,能够让我们以不同的组件来划分不同的功能模块,需要什么功能就去调用对应的模块即可

//定义一个名为button-counter 的新组件
Vue.component('button-counter', {
    data: function () {
        return {
            count : 0
        }
    },
    template: `<button v-on:click="count++">`
})
  • 为什么在vue组件中data要写成函数而不是对象?
  1. vue组件本质上是一个vue实例对象
  2. 如果data是对象,所有vue组件实例对象都会共享data对象数据,如果A组件改变了数据,B组件会受到影响
  3. 定义成函数,函数有自己的块作用域,每个vue实例都有自己的data块作用域相互不影响

组件化和模块化的区别

  • 组件化

是从UI界面的角度进行划分的,根据封装的思想,把页面上可重用的 UI,结构封装为组件,从而方便项目的开发和维护。

  • 模块化

是从代码的逻辑角度去划分的 方便代码分层开发保证每个功能模块的职能单一

组件之间的父子关系

图像.png

组件通讯

  • 父传子 props

在父组件使用子组件的地方添加属性参数,
<button-counter :num="number" name='小明'></button-counter>
在子组件中定义props选项, 值是一个数组,可以接收多个参数。

  • 子传父$emit+v-on
  1. 在子组件上绑定一个自定义事件@on-counter
  2. vm.$emit('on-counter') //触发名为on-counter的事件
  • 兄弟间传值 Event Bus
  • refs方式

ref加在普通元素和vue组件上做为属性使用,
<button ref="btn1"><button> <todo-list ref="list"></todo-list>

  1. ref 加在普通的元素上,用this.$refs.btn 获取到的是dom元素
  2. ref 加在子组件上,用this.$refs.list 获取到的是组件实例,可以使用组件的所有方法。

实现传参方式:
在父组件使用子组件时,定义ref属性
在父组件内通过this.$refs.name获取子组件实例, 获取子组件数据。

补充

1. 子传组件传递总价到父组件显示

  • 父组件绑定接收总价自定义事件totalEvent
// app父组件
<div id="app">
    <!-- 商品列表数组 product-list  ProudctList -->
    <product-list :book="newBook"  @total-event="showTotalPrice" ></product-list>
    <h2>商品总价:<span class="total-price">{{total}}</span></h2>
</div>


methods: {			
    //接收子组件总价显示到界面
    showTotalPrice(toalPrice){
        this.total = toalPrice
    }
}
  • ProductList子组件created生命周期函数中触发事件

    //子组件ProductLiSt 
    created() {
       this.$emit('totalEvent',this.total) // total总价通过计算属性获取到 
    },
    
  • ProductList子组件深度侦听商品列表数据变化,传递总价给父组件

    watch:{
      //深度侦听商品列表数据变化,传递总价给父组件
      list:{
    	handler(){
    		this.$emit('totalEvent',this.total) //触发自定义事件totalEvent传递总价给父组件
    	},
    	deep:true //深度侦听
      }
    }
    

2. 选中复选框计算总价

computed:{
    // 计算属性方法定义与计算属性值有关的业务
    total(){
        let toalPrice = this.list.reduce( (previous,current) => 
        previous + (current.state?current.price*current.num: 0), 0)
        return toalPrice.toFixed(2)
    }
},