vue组件化

Posted 做个机灵鬼

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了vue组件化相关的知识,希望对你有一定的参考价值。

什么是组件化

所谓组件化,就是把页面拆分成多个组件,每个组件依赖的 CSS、JS、模板、图片等资源放在一起开发和维护。 因为组件是资源独立的,所以组件在系统内部可复用,组件和组件之间可以嵌套,如果项目比较复杂,可以极大简化代码量,并且对后期的需求变更和维护也更加友好

组件的使用分成三个步骤:

1.创建组件构造器
2.注册组件
3.使用组件

1Vue.extend():

调用Vue.extend()创建的是一个组件构造器。
通常在创建组件构造器时,传入template代表我们自定义组件的模板。
该模板就是在使用到组件的地方,要显示的html代码。
事实上,这种写法在Vue2.x的文档中几乎已经看不到了,它会直接使用下面我们会讲到的语法糖,但是在很多资料还是会提到这种方式,而且这种方式是学习后面方式的基础。

2.Vue.component():

调用Vue.component()是将刚才的组件构造器注册为一个组件,并且给它起一个组件的标签名称。
所以需要传递两个参数:1、注册组件的标签名 2、组件构造器

3.组件必须挂载在某个Vue实例下,否则它不会生效。

<body>
    <div id="app">
     <my-cpn></my-cpn>
    </div>
    <script type="text/javascript" src="../js/vue.js"></script>
    <script type="text/javascript" >
      //1.创建组件构造器对象
      const cpnC = Vue.extend(
        template: `
        <div>
          <h2>我是标题</h2>
          <h3>我是内容,哈哈哈哈</h3>
          <h3>我是内容,呵呵呵呵</h3>
          </div>
        `
      )
      //注册组件
      // 两个参数 1.组件标签名,2.组件构造器对象
      Vue.component('my-cpn',cpnC)
    const app = new Vue(
      el: '#app',
      data:
    )
    </script>
  </body>

父子组件

<body>
    <div id="app">
       <cpn2></cpn2>
    </div>
    <script type="text/javascript" src="../js/vue.js"></script>
    <script type="text/javascript" >
    // 子组件
    const cpnC1 = Vue.extend(
      template: `
      <div>
          <h2>我是标题1</h2>
          <h3>我是内容,哈哈哈哈</h3>
          <h3>我是内容,呵呵呵呵</h3>
          </div>
      `
    )
    // 父组件
    const cpnC2 = Vue.extend(
      template: `
          <div>
          <h2>我是标题2</h2>
          <h3>我是内容,哈哈哈哈</h3>
          <h3>我是内容,呵呵呵呵</h3>
          <cpn1></cpn1>
          </div>
      `,
      components: 
        cpn1: cpnC1
      
    )
    const app = new Vue(
      el: '#app',
      data:,
      components: 
        cpn2:cpnC2
      
    )
    </script>
  </body>

组件模板分离写法

<body>
    <div id="app">
      <cpn></cpn>
    </div>
    <!-- text/x-template 写法-->
    <!--   <script type="text/x-template" id="cpn">
      <div>
        <h2>我是标题2</h2>
        <h3>我是内容,哈哈哈哈</h3>
        <h3>我是内容,呵呵呵呵</h3>
        <cpn1></cpn1>
     </div>
    </script> -->
    <!-- 使用tmplate写法 -->
    <template id="cpn">
      <div>
        <h2>我是标题2</h2>
        <h3>我是内容,哈哈哈哈</h3>
        <h3>我是内容,呵呵呵呵</h3>
        <cpn1></cpn1>
      </div>
    </template>
    <script type="text/javascript" src="../js/vue.js"></script>
    <script type="text/javascript">
      // 注册一个全局组件
    /*   Vue.component("cpn", 
        template: "#cpn",
      ); */
      const app = new Vue(
        el: "#app",
        components: 
          cpn: 
            template: '#cpn'
          
        
      );
    </script>
  </body>

为什么组件的data必须是一个函数

首先,如果不是一个函数,Vue直接就会报错。
其次,原因是在于Vue让每个组件对象都返回一个新的对象,因为如果是同一个对象的,组件在多次使用后会相互影响。

<body>
    <div id="app">
       <cpn></cpn>
       <cpn></cpn>
       <cpn></cpn>
    </div>
    <template id="cpn">
    <!-- template模板 组件模板应该只包含一个根元素 定义一个div把所有元素放进去-->
      <div>
        <h2>计数器: counter</h2>
        <button @click="increment">+</button> 
        <button @click="decrement">-</button> 
      </div>
    
      
    </template>
    <script type="text/javascript" src="../js/vue.js"></script>
    <script type="text/javascript" >
      // 注册一个全组件
      Vue.component('cpn',
        template: '#cpn',
        // data属性必须是一个函数,并且返回一个对象
        // data为什么必须是一个函数呢
        /* 
        因为函数每次被调用时 都会返回一个新的对象,那么在组件复用时 就不会引起数据的连锁反应
        比如一个组件实例需要对data的数据进行修改,如果data是一个对象,那么组件复用时,都是引用了同一个对象(传递地址),对其中一个组件中的data进行修改时,会造成其他的数据也被修改
        data是一个函数就不会有这种连锁反应,因为每个组件复用时都会生成一个新的对象
        */
        data()
          return 
            counter: 0
          
        ,
        methods: 
          increment()
            return this.counter++
          ,
          decrement()
            return this.counter--
          
        
      )
    const app = new Vue(
      el: '#app'
    )
    </script>
  </body>

组件间的通信

在开发中,往往一些数据确实需要从上层传递到下层:
比如在一个页面中,我们从服务器请求到了很多的数据。
其中一部分数据,并非是我们整个页面的大组件来展示的,而是需要下面的子组件进行展示。
这个时候,并不会让子组件再次发送一个网络请求,而是直接让大组件(父组件)将数据传递给小组件(子组件)。
如何进行父子组件间的通信呢?Vue官方提到
通过props向子组件传递数据
通过自定义事件向父组件发送消息

父组件向子组件传递

在组件中,使用选项props来声明需要从父级接收到的数据。
props的值有两种方式:
方式一:字符串数组,数组中的字符串就是传递时的名称。
方式二:对象,对象可以设置传递时的类型,也可以设置默认值等。

  <body>
    <!-- 组件通信 父传子 父组件:根组件vue实例,子组件cpn -->
    <div id="app">
      <cpn :cmessage="message" :cmovies="movies"></cpn>
    </div>
    <template id="cpn">
     <div>
       <h2>cmessage</h2>
       <ul>
         <li v-for="item in cmovies">item</li>
       </ul>
     </div>
        
      
    </template>
    <script type="text/javascript" src="../js/vue.js"></script>
    <script type="text/javascript" >
    Vue.component('cpn',
      template: '#cpn',
      // props:['cmessage','cmovies']
      props: 
     /*    //1.类型限制
        cmessage: String,
        cmovies: Array */
        //提供一些默认值 必传值
        cmessage: 
          typeof: String,
          // 当组件实例中没有绑定cmessage 默认输出值
          default: 'aaaaa',
          // 必传值,当组件实例没有传入cmessage值 将会报错
          required: true
        ,
        // 数组和对象的默认值 必须是函数
        cmovies: 
          typeof: Array,
          default()
            return []
          
        
      
    )
    const app = new Vue(
      el: '#app',
      data:
        message: '你好呀',
        movies: ['海贼王','海尔兄弟','斗罗大陆']
      
    )
    </script>
  </body>

子组件向父组件传递

这个时候,我们需要使用自定义事件来完成。
什么时候需要自定义事件呢?
当子组件需要向父组件传递数据时,就要用到自定义事件了。
我们之前学习的v-on不仅仅可以用于监听DOM事件,也可以用于组件间的自定义事件。
自定义事件的流程:
在子组件中,通过$emit()来触发事件。
在父组件中,通过v-on来监听子组件事件。

<body>
    <!-- 父组件 -->
    <div id="app">
       <!-- 监听一个自定义事件 -->
      <cpn @item-click="cpnclick"></cpn>
    </div>
    <!-- 子组件 -->
    <template id="cpn">
      <div>
       
        <button v-for="item in categories" @click="btnclick(item)">item.name</button>
      </div>
    </template>
    <script type="text/javascript" src="../js/vue.js"></script>
    <script type="text/javascript" >
    const cpn = 
      template: '#cpn',
      data()
        return 
          categories: [
            id:'aaa',name:'热门推荐',
            id:'bbb',name:'手机数码',
            id:'ccc',name:'电脑办公',
            id:'ddd',name:'家用电器'
          ]
        
      ,
      methods: 
        btnclick(item)
          // 发射事件$emit
          this.$emit('item-click',item)
        
      
    
    const app = new Vue(
      el: '#app',
      data: ,
      components: 
        cpn
      ,
      methods: 
        cpnclick(item)
          console.log('cpnclick',item);
        
      
    )
    </script>

注意
在组件通信引用的时候,动态绑定自定义事件时,事件名不能存在驼峰命名,可以使用 - 代替

以上是关于vue组件化的主要内容,如果未能解决你的问题,请参考以下文章

vue 组件属性props,特性驼峰命名,连接线使用

Vue父子组件通信之$emit(基于vue2.5,ES6)

Vue——自定义组件 & 自定义事件$emit & 插槽slot

Vue.js——6.创建组件

Vue.js中的组件通信

Vue.js中的组件通信