深入了解Vue的组件化开发

二、组件化开发

组件使用的三个步骤:

  • 创建组件的构造器 Vue.extend()方法创建组件的构造器
  • 注册组件 Vue.component()注册组件
  • 使用组件在Vue的实力范围内使用组件(el指定的范围内进行使用)

在开发中基本使用的是局部组件很少使用全局组件

2.1 创建局部组件与全局组件

<script src="../js/vue.js"></script>
    <div id="app">
      <span>{{message}}</span>
      <!-- <my-cpn></my-cpn> -->
      <!-- 只能够在Vue管理的范围内进行使用 -->

      <cpn1></cpn1>
    </div>
    <div id="app1">
      <cpn1></cpn1>
    </div>
    <!-- <my-cpn></my-cpn> -->
    <!--无效不在Vue的管理实例的范围内-->
    <script>
      //ES6
      const a = `a
      ab`; //能够实现自动换行  特殊的引号

      //创建组件构造器对象
      const cpnConstractor = Vue.extend({
        template: `
          <div>
            <h2>我是1</h2>
            <span>我是2</span>
            </div>`,
        //template是自定义组件的模板
      });
      //注册组件
      // Vue.component("组件的标签名",'定义的组件构造器');
      // Vue.component("my-cpn", cpnConstractor); //这种定义的全局组件只要是vue管理的实例内都可以进行引用

      const app = new Vue({
        el: "#app",
        data: {
          message: "李加喜",
        },
        components: {
          cpn1: cpnConstractor,
        },
        //局部的组件 只能够在这个定义的容器里面进行使用
      });
    </script>

2.2 创建父子组件

 <div id="app">
      <cpn2></cpn2>
      <!--<cpn1></cpn1>  这个里面已经不能在使用cpn1了 因为在这个容器里面只定义了cpn2-->
    </div>

    <script src="../js/vue.js"></script>
    <script>
      // 1.创建第一个组件构造器(子组件)
      const cpnC1 = Vue.extend({
        template: `
          <div>
            <h2>我是标题1</h2>
            <p>我是内容, 哈哈哈哈</p>
          </div>
        `,
      });

      // 2.创建第二个组件构造器(父组件)
      const cpnC2 = Vue.extend({
        template: `
          <div>
            <h2>我是标题2</h2>
            <p>我是内容, 呵呵呵呵</p>
            <cpn1></cpn1>
          </div>
        `,
        // 在这里引入了子组件 那么就可以调用子组件
        components: {
          cpn1: cpnC1,
        },
      });

      // root组件
      const app = new Vue({
        el: "#app",
        data: {
          message: "你好啊",
        },
        components: {
          cpn2: cpnC2,
        },
      });
    </script>

2.3 组件的语法糖

创建全局组件与局部组件

//使用语法糖注册组件
      //创建全局组件
<script>
      Vue.component("cpn1", {
        template: `
          <div>
            <h2>123</h2>
            <h2>456</h2>
          </div>
        `,
      });
      //创建局部组件
      const app = new Vue({
        el: "#app",
        data: {
          message: "你好啊",
        },
        components: {
          cpn2: {
            template: `
            <div>
            <h2>456</h2>
            <h2>123</h2>
          </div>
            `,
          },
        },
      });
    </script>

2.4 模板组件的分离式写法

<div id="app">
      <span>{{message}}</span>
      <cpn1></cpn1>
      <!-- <cpn2></cpn2> -->
    </div>
    <!-- <script type="text/x-template" id="mycpn">
      <div>
        <h3>1</h3>
        <h3>2</h3>
        <h3>3</h3>
      </div>
    </script> -->
    <!--或者-->
    <template id="mycpn">
      <div>
          //最好引入一个根
        <h3>{{title}}</h3>
        <h3>2</h3>
        <h3>3</h3>
      </div>
    </template>
    <script>
      Vue.component("cpn1", {
        template: "#mycpn",
        data() {
          return {
            title: "456",
          };
        },
      });

      const app = new Vue({
        el: "#app",
        data() {
          return {
            message: "你好啊",
          };
        },
        components: {
          cpn2: {
            template: "#mycpn",
          },
        },
      });
    </script>

2.5 父组件与子组件之间的通信

父组件向子组件传递数据使用props

子组件向父组件通过事件

在子组件里面定义props

<!-- 
      通过props向子组件传递数据   将props定义在子组件里面
      通过事件向父组件传递数据
     -->
    <div id="app">
      <cpn :cmessage="message" :cmovies="movies"></cpn>
    </div>
    <template id="cpn">
      <div>
          //必须要有一个根
        <ul>
          <li v-for="item in cmovies">{{item}}</li>
        </ul>
        <h2>{{cmessage}}</h2>
      </div>
    </template>

    <script src="../js/vue.js"></script>
    <script>
      // 父传子: props
      const cpn = {
        template: "#cpn",
        // props: ["cmovies", "cmessage"],
        //可以自定义props的类型   有很多种定义的方式
        props: {
          cmessage: {
            type: String,
            default: "aaaaaaaa",
            required: true,
            //这个属性是必须要进行传递的
          },
          cmovies: {
            type: Array,
            default() {
              return [];
            },
          },
        },
      };

      const app = new Vue({
        el: "#app",
        data: {
          message: "你好啊",
          movies: ["海王", "海贼王", "海尔兄弟"],
        },
        components: {
          cpn,
        },
      });
    </script>

处理props的驼峰

<script src="../js/vue.js"></script>
    <div id="app">
      <span>{{message}}</span>
      <cpn :cmessage="message" :c-movies="movies"></cpn>
    </div>
    <template id="mycpn">
      <div>//必须要有一个根
        <ul>
          <li v-for="item in cMovies">{{item}}</li>
        </ul>
        <h2>{{cmessage}}</h2>
      </div>
    </template>
    <script>
      const cpn = {
        template: `#mycpn`,
        props: {
          cmessage: {
            type: String,
          },
          cMovies: {
            type: Array,
            default() {
              return [];
            },
          },
        },
      };
      const app = new Vue({
        el: "#app",
        data: {
          message: "你好",
          movies: ["海王", "海贼王", "海尔兄弟"],
        },
        components: {
          cpn,
        },
      });
    </script>

子组件向父组件传递数据

步骤

  1. 创建子组件的模板
  2. 创建子组件来引用子组件模板
  3. 设置子组件要传递的数据以及自定义子组件的触发的事件
  4. 在父组件模板里面引用子组件以及子组件的自定义事件
  5. 在父组件里面设置对应的方法
<!--父组件模板-->
<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 src="../js/vue.js"></script>
<script>

  // 1.子组件
  const cpn = {
    template: '#cpn',
    data() {//这个是要响应给父组件的数据
      return {
        categories: [
          {id: 'aaa', name: '热门推荐'},
          {id: 'bbb', name: '手机数码'},
          {id: 'ccc', name: '家用家电'},
          {id: 'ddd', name: '电脑办公'},
        ]
      }
    },
    methods: {
      btnClick(item) {
        // 发射事件 $emit: 自定义事件  并且传递了item参数
        this.$emit('item-click', item)
      }
    }
  }

  // 2.父组件
  const app = new Vue({
    el: '#app',
    data: {
      message: '你好啊'
    },
    components: {
      cpn
    },
    methods: {
      cpnClick(item) {
        console.log('cpnClick', item);
      }
    }
  })
</script>

2.6 插槽的基本使用

包含有名字的插槽和没有名字的插槽

<script src="../js/vue.js"></script>
    <div id="app">
      <cpn></cpn>
      <cpn>
        <span>我来取代插槽的内容</span>
      </cpn>
      <cpn>
        <button value="点击">按钮</button>
      </cpn>
      <hr />
      <cpn>
        <span slot="ljx">取代有名字的插槽</span>
      </cpn>
    </div>
    <template id="cpn">
      <div>
        <span>我是不会被取代的</span><br />
        <slot>我是一个没有名字的插槽</slot><br />
        <slot name="ljx">我是一个有名字的插槽</slot>
      </div>
    </template>
    <script>
      Vue.component("cpn", {
        template: "#cpn",
      });

      let app = new Vue({
        el: "#app",
        data: {
          message: "李加喜",
        },
      });
    </script>

编译的作用域

  1. 在vue实例里面使用的就是引用vue实例的data数据,如果是在子组件里面里面使用的就是子组件的data值

官方准则:父组件模板的所有东西都会在父级作用域内进行编译,子组件模板的所有东西都会在子组件的作用域内进行编译

<div id="app">
      <span>{{message}}</span>
      <cpn></cpn>
      <cpn v-show="isShow"></cpn>
      <!-- 关联的是vue实例的数据 -->
    </div>
    <template id="cpn">
      <div>
        <h2>我是子组件</h2>
        <button v-show="isShow">按钮</button>
        <!-- 关联的是子组件的data -->
        <!--这个不会被显示  因为设置的是false-->
      </div>
    </template>
    <script>
      const app = new Vue({
        el: "#app",
        data: {
          message: "你好",
          isShow: true,
        },
        components: {
          cpn: {
            template: "#cpn",
            data() {
              return {
                isShow: true,
              };
            },
          },
        },
      });
    </script>

2.作用域插槽

父组件替换插槽的标签,但是由子组件来进行提供内容

<div id="app">
      <cpn></cpn>

      <cpn>
        <!--目的是获取子组件中的pLanguages   使用slot-scope来获取插槽里面设置的数据-->
        <template slot-scope="a">
          <!--<span v-for="item in slot.data"> - {{item}}</span>-->
          <span>{{a.data.join(' - ')}}</span>
        </template>
      </cpn>

      <cpn>
        <!--目的是获取子组件中的pLanguages   通过slot_scope来获取绑定的数据-->
        <template slot-scope="slot">
          <!--<span v-for="item in slot.data">{{item}} * </span>-->
          <span>{{slot.data.join(' * ')}}</span>
        </template>
      </cpn>
      <!--<cpn></cpn>-->
    </div>

    <template id="cpn">
      <div>
        <!-- 在定义插槽的时候为这个插槽绑定数据 -->
        <slot :data="pLanguages">
          <ul>
            <li v-for="item in pLanguages">{{item}}</li>
          </ul>
        </slot>
      </div>
    </template>
    <script src="../js/vue.js"></script>
    <script>
      const app = new Vue({
        el: "#app",
        data: {
          message: "你好啊",
        },
        components: {
          cpn: {
            template: "#cpn",
            data() {
              return {
                pLanguages: [
                  "JavaScript",
                  "C++",
                  "Java",
                  "C#",
                  "Python",
                  "Go",
                  "Swift",
                ],
              };
            },
          },
        },
      });
    </script>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值