Vue基础-第四篇

195 阅读3分钟

组件化

(重点)Vue组件化开发

1、什么是组件化?

面对复杂问题的处理方式,把问题拆解成很多个能处理的小问题,再将其放在整体中,会发现大的问题也会迎刃而解。

  • 组件化开发的优势:可维护性高 可复用性高

Vue组件化思想

  1. 它提供了一种抽象,让我们可以开发出一个个独立可复用的小组件来构造我们的应用。
  2. 任何的应用都会被抽象成一颗组件树。

2、全局组件

通过Vue.component('组件名称', {}),通过这个方法注册的都是全局组件,也就是他们再注册之后可以用在任何新创建的Vue 实例挂载的区域内。

<body>
  <div id="app">
    <my-con></my-con>
    <div>
      <my-con></my-con>
    </div>
  </div>
  <my-con></my-con>
</body>
<script>
  Vue.component('my-con', {
    template: '<section><h3>组件标题</h3><p>组件内容</p></section>'
  })
  const vm = new Vue({
    el: '#app'
  })
</script>

3、局部组件

通过 Vue.component 方式注册的组件,称之为全局组件。任何地方都可以使用。全局注册往往是不够理想的。比如,如果你使用一个像 webpack 这样的构建系统,全局注册所有的组件意味着即便你已经不再使用一个组件了,它仍然会被包含在你最终的构建结果中。这造成了用户下载的 JavaScript 的无谓的增加。

注册局部组件

<body>
  <div id="app">
    <my-con></my-con>
    <div>
      <my-con></my-con>
    </div>
  </div>
  <div id="app1">
    <my-con1></my-con1>
  </div>
</body>
<template id="template1">
  <section>
    <h3>组件标题</h3>
    <p>组件内容</p>
  </section>
</template>
<template id="template2">
  <section>
    <h3>组件标题B</h3>
    <p>组件内容B</p>
  </section>
</template>
<script>
  var componentA = {
    template: '#template1'
  }

  var componentB = {
    template: '#template2'
  }
  const vm = new Vue({
    el: '#app',
    components: {
      'my-con': componentA
    }
  })
  const vm1 = new Vue({
    el: '#app1',
    components: {
      'my-con1': componentB
    }
  })
</script>

父组件和子组件

组件和组件之间存在层级关系,而其中一种最重要的关系就是父子组件关系。
注意: 父组件中定义了title属性,子组件是不能使用的

那组件如果要使用data定义自己属性保存数据要怎么做呢?

  1. 组件对象也有一个data的属性(也有methods等属性,下面我们有用到)
  2. 只是这个data属性必须是一个函数,而且函数返回一个对象 ,对象保存着数据

为什么data在组件中必须是一个函数呢?

原因是在于Vue让每个组件对象都返回一个新的对象,因为如果是同一个对象的,组件在多次使用后会相互影响。

父子组件间的通讯

父级向子级传递

在组件中,使用选项props来声明需要从父级接收到的数据。

props的值有两种方式:

  1. 字符串数组,数组中的字符串就是传递时的名称。
  2. 对象,对象可以设置传递时的类型(String,Number,Boolean,Array, Object,Date,Function,Symbol),也可以设置默认值等。
    <div id='app'>
        <!-- 1 在父组件中,调用子组件的时候,通过标签属性的方式传入子组件内部-->
        <child :num = "fatherNum"></child>
    </div>  

    <template id="tmpl">
        <div>
            <!-- 3 在子组件中 使用这个数据 -->
            <p>{{ num }}</p>
        </div>
    </template>
    <script>
        let child = {
            template:"#tmpl",
            // 2 在子组件中,接收传进来的num属性
            props:["num"]
        }
        new Vue({
            el:'#app',
            data:{
                fatherNum:20
            },
            components:{
                child
            }
        })
    </script>

子级向父级传递

父组件向子组件传递数据,通过自定义事件

    <div id='app'>
        <p>父组件中的fatherNum为:{{fatherNum}}</p>
        <!-- 2 在父组件中,调用子组件的时候, 通过自定义事件的方式,定义事件函数 -->
        <child :num="fatherNum" @fn="chanFatherNum"></child>
    </div>  
    <template id="tmpl">
        <div>
            <p>{{num}}</p>
            <button @click="add">按钮</button>
        </div>
    </template>    
    <script>
        // 单向数据流 父 -> 子  , 子组件无法直接修改父组件数据
        let child = {
            template:"#tmpl",
            props:["num"],
            data(){
                return{
                    step:10
                }
            },
            methods:{
                add(){
                    // 3 在子组件中,触发自定义事件,从而执行chanFatherNum这个函数
                    // $emit(事件名,参数)   专门用来触发自定义事件
                    this.$emit("fn", this.step)
                }
            }
        }
        new Vue({
            el:'#app',
            data:{
                fatherNum:20
            },
            components:{
                child
            },
            // 1 在父组件中,准备一个修改父组件数据的方法
            methods:{
                chanFatherNum(val){
                    this.fatherNum+=val
                }
            }
        })

总结:
什么时候用父传子? 子组件中想要用父组件的数据
什么时候用子传父? 子组件中修改父组件数据的时候

非父子组件通讯

这个之后的vuex会涉及,暂时先不提

实际工作中如果遇到跨组件或者非父组件间的传递数据,那该怎么办?第一个可以使用中央事件总线,也就是一个中介来完成。第二个就是使用 Vuex 提供的功能,学习Vuex之后再进行讨论。