[聚合文章] 组件(1)

vue.js 2017-11-30 16 阅读

组件

  • 定义组件
  • 组件通信
  • 插槽slot实现分发内容
  • 高级组价

组件定义

全局注册组件

Vue.compoment('组件名称',{
组件内容,最外层只能被一个元素包围;
template:组件模板,内容为组件文档内容
});

 Vue.component('my-com', {
    template: `
      <div>
        <h3>全局组件</h3>
        <div>
          <p>内容1</p>
          <p>内容2</p>
        </div>
      </div>
    `
  });

局部组件

跟全局组件定义一样,局部组件就是把全局组件内部的{}抽离开来,然后赋值给一个变量,再将赋值后的变量注册到new vue中的components下,这样定义的组件就是一个简单的局部组件了。

 var child_com = {
    template: `
      <div>
        <h3>局部组件</h3>
        <div>
          <p>局部组件内容</p>
        </div>
      </div>
    `
  };
  var vm = new Vue({
    el: '#app',
    components: {
      child_com
    }
  });

组件通信

一般的组件通信方式有一下三种:

  • 父子组件
  • 兄弟组件、跨级组件

示意图:

父子组件通信

<body>
  <div id="app">
    <child-com :info="info" @say="childSay"></child-com>
  </div>
  <script>
    var childCom = {
      template: `
      <div>
        <h3>{{info.title}}</h3>
        <div>
          <p>{{info.desc}}</p>
        </div>
        <button @click='say'>通知父组件</button>
      </div>
    `,
      props: {
        info: {
          type: Object
        }
      },
      methods: {
        say() {
          this.$emit('say', '我被点击了');
        }
      }
    };
    var vm = new Vue({
      el: '#app',
      data() {
        return {
          info: {
            title: '头部内容',
            desc: '展示内容'
          }
        }
      },
      components: {
        'child-com': childCom
      },
      methods: {
        childSay(params) {
          alert(params);
        }
      }
    });
  </script>
</body>

父子通信如上所述:
父组件通过:info="info"向下传递给子组件childCom,子组件通过props接受来自父组件信息,
然后子组件又通过this.$emit('say', '我被点击了');中的$emit向父组件提交一个say,父组件
通过 @say="childSay",拿到子组件传的通信,这样一个简单的父子组件通信就完成了。
注意:这里需要注意的是:

  • 子组件通过props接受父组件信息时,props的对应属性值一定要跟父组件传过来的一样,比如上式的info
  • 父组件接受来自子组件信息时,也一样,绑定的事件要跟子组件的一样,如上述中的@say="childSay"中的say要跟子组件this.$emit('say', '我被点击了');中的say一样。

兄弟组件、跨级组件

对于简单的兄弟组件,可以采用事件中间件形式,也通过一个创建一个空的Vue实例,并通过这个实例信息。
如下:

<body>
  <div id="app">
    <child-a></child-a>
    <child-b></child-b>
  </div>
  <script>
    var bus = new Vue();
    var childA = {
      template: `
        <div>
          <h3>组件1</h3>
          <button @click='childAMethos'>兄弟组件通信</button>
        </div>
      `,
      methods: {
        childAMethos() {
          bus.$emit("aInfo", '组件A给你传递信息了');
        }
      }
    }
    var childB = {
      template: `
        <div>
          <h3>组件2</h3>
        </div>
      `,
      mounted () {
        bus.$on('aInfo', function (id) {
          alert(id);
        })
      }
    }
    var vm = new Vue({
      el: '#app',
      components: {
        'child-a': childA,
        'child-b': childB,
      }
    });
  </script>
</body>

组件childA通过 bus.$emit("aInfo", '组件A给你传递信息了');给组件childB传递数据aInfo,
组件childB通过 bus.$on('aInfo', function (id) {alert(id);})接受来及组件childA的数据.

更复杂的组件通信可以使用vuex做状态管理,关于vuex接下来会专门写一篇文章单独介绍。
想了解的可以移步到状态管理模式

插槽slot实现分发内容

实现组件的内容分发主要是通过slot插槽的方式进行。

  • 单个插槽
  • 具名插槽
  • 作用域插槽
1.单个插槽
<body>
  <div id="app">
    <child-a>
      <h3>标题</h3>
      <p>文本内容</p>
    </child-a>
  </div>
  <script>
    var bus = new Vue();
    var childA = {
      template: `
        <div>
          <slot>33333333333</slot>
        </div>
      `,
    }
    var vm = new Vue({
      el: '#app',
      components: {
        'child-a': childA,
      }
    });
  </script>
</body>

只有一个slot插槽的称为单个插槽,使用slot时注意:

  • 当slot存在内容时,若调用组件的父组件存在内容,则slot的内容会被覆盖掉,

如上述的 child-a的内容会覆盖childA中slot下的内容只显示,<div><h3>标题</h3><p>文本内容</p></div>
如图:

2.具名插槽
<body>
  <div id="app">
    <child-a>
      <h3 slot="header">标题</h3>
      <p slot="cont">文本内容</p>
    </child-a>
  </div>
  <script>
    var bus = new Vue();
    var childA = {
      template: `
        <div>
          <h3>
            <slot name="header"></slot>
          </h3>
          <section>
            <slot name="cont"></slot>
          </section>
        </div>
      `,
    }
    var vm = new Vue({
      el: '#app',
      components: {
        'child-a': childA,
      }
    });
  </script>
</body>

具名插槽主要是,组件中在slot标签中定义一个name的属性,这个属性的名称就是引用此组件时对应的属性slot中的名称。
比如上述中的childA组件中的插槽<slot name="header"></slot><slot name="cont"></slot>中name的名称分别是引用组件<child-a><h3 slot="header">标题</h3><p slot="cont">文本内容</p></child-a>中slot对应的名称。

3.作用域插槽
<body>
  <div id="app">
    <child-a>
      <template slot-scope="scope">
         <h3>作用域插槽</h3>
         <p>{{scope.desc}}</p>
      </template>
    </child-a>
  </div>
  <script>
    var bus = new Vue();
    var childA = {
      template: `
        <div>
          <h3>
            <slot desc="这是作用域插槽内容"></slot>
          </h3>
        </div>
      `,
    }
    var vm = new Vue({
      el: '#app',
      components: {
        'child-a': childA,
      }
    });
  </script>
</body>

作用域插槽主要是用在可重用模板中

上述中的在子组件childA中定义<slot desc="这是作用域插槽内容"></slot>,name在父组件中调用子组件childA时,就可以通过设定作用域template的slot-scope属性来获取子组件childA内desc的信息。

源码地址:https://github.com/wqb2017/my...

注:本文内容来自互联网,旨在为开发者提供分享、交流的平台。如有涉及文章版权等事宜,请你联系站长进行处理。