VueJS 基础部分-组件化(2)

第一章 组件化

1.1 认识组件化

组件化就是将一个页面拆分成一个个小的功能模块,每个功能模块完成属于自己这部分独立的功能,使得整个页面的管理和维护变得非常容易

1.2 组件的基本使用过程

<div id="app">
    <!-- 3. 使用组件 -->
    <my-cpn></my-cpn>
    <my-cpn></my-cpn>
    <my-cpn></my-cpn>
</div>

<script src="../js/vue.js"></script>
<script>
    // 1. 创建组件构造对象
    const cpnC = Vue.extend({
        template: `
      <div>
        <h2>标题</h2>
        <p>内容:哈哈哈哈~~~~~</p>
      </div>`,
    })

    // 2. 注册组件
    // Vue.component(`组件的标签名`,cpnC)
    Vue.component(`my-cpn`, cpnC)

    const app = new Vue({
        el: '#app',
    })
</script>

1.3 全局组件和局部组件

全局组件

// 注册组件(全局组件, 可以在多个Vue的实例下面使用)
Vue.component(`my-cpn`, cpnC)

局部组件

const app2 = new Vue({
    el: '#app2',
    /* 1. 局部组件 */
    components: {
        cpn: cpnC,
    },
})

1.4 父组件和子组件

const childC = Vue.extend({
    // 子组件
    template: `
        <div>
          <h2>I am son component</h2>
          <p>i has any money</p>
        </div>
      `,
})
const parentC = Vue.extend({
    // 父组件
    template: `
        <div>
          <h2>I am father component</h2>
          <p>I have many son</p>
          <child></child>
        </div>
      `,
    components: {
        /* 建立子组件 */
        child: childC,
    },
})

const app = new Vue({
    el: '#app',
    components: {
        parent: parentC,
    },
})

1.5 组件注册的语法糖

// 全局组件
Vue.component(`my-cpn`, {
    template: `
        <div>
          <h2>全局组件</h2>
          <p>内容:哈哈哈哈~~~~~</p>
        </div>
      `,
})

// 局部组件
const app = new Vue({
    el: '#app',
    data: {
        message: 'hello',
    },
    components: {
        cpn1: {
            template: `
            <div>
              <h2>局部组件</h2>
              <p>内容:哈哈哈哈~~~~~</p>
            </div>
          `,
        },
    },
})

1.6 模板的分离写法

  1. script(不常用)
<!-- 1. script标签,类型必须是 text/x-template -->
<script type="text/x-template" id="cpn">
    <div>
      <h2>{{title}}</h2>
      <p>{{message}}</p>
    </div>
</script>

<script src="../js/vue.js"></script>
<script>
    Vue.component(`cpn`, {
        template: `#cpn`,
        data() {
            return {
                title: '全局组件',
                message: '内容:我是全局组件 哈哈哈哈~~~~~',
            }
        },
    })
    const app = new Vue({
        el: '#app',
        components: {
            cpn1: {
                template: `#cpn`,
            },
        },
    })
</script>
  1. template(如果内部的标签大于 1 ,则需要有一个根 div 来包含内容)
<template id="cpn1">
    <div>
        <h2>局部组件</h2>
        <p>内容:哈哈哈哈~~~~~</p>
    </div>
</template>

<script src="../js/vue.js"></script>
<script>
    const app = new Vue({
        el: '#app',
        components: {
            cpn1: {
                template: `#cpn1`,
            },
        },
    })
</script>

1.7 数据的存放

  1. 子组件不能访问父组件
  2. 子组件有自己的 data,而且必须是一个函数
Vue.component(`cpn`, {
      template: `#cpn1`,
      data() {
        return {
          counter: 0
        }
      }
  1. 为什么是一个函数?

    目的:让每一个控件独立的存在,不发生多个绑定在一起

1.8 父子组件的通信

父传子 : props

/* v-bind 目前不支持驼峰,或者写成 c-movies */
const cpn = {
    template: '#cpn',
    /* 1. 数组形式 */
    // props: ['c-movies', 'c-message'],
    props: {
        /* 2. 类型限制 */
        // c-movies: Array,
        // c-message: String

        /* 3. 提供一些默认值(以及必传值) */
        c-message: {
            type: String,
            default: '没有信息', // 没有传值时则显示默认值
        },
        c-movies: {
            type: Array,
            default() {
                return ['没有发现']
            },
            required: true, // 表示必须传该数组 否则报错
        },
    },
    data() {
        return {}
    },
}

子传父 : $emit

<!-- 父组件模板 -->
<div id="app">
    <!-- 父组件监听子组件发送的请求 -->
    <cpn @itemclick="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>
    /* 子组件 */
    const cpn = {
      template: '#cpn',
      data() {
        return {
          categories: [
            {id: 'a1', name: '热门推荐'},
            {id: 'a2', name: '手机数码'},
            {id: 'a3', name: '家用家电'},
          ]
        }
      },
      methods: {
        btnClick(item) {
          // 发射事件: 自定义事件
          /* itemclick 表示事件的名称 */
          this.$emit('itemclick', item){
            console.log();
          }
        }
      }
    }

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

第二章 组件化开发

2.1 父子组件的访问

  1. 父组件 访问 子组件
  • $children (不常用)
<div id="app">
    <cpn></cpn>
    <button @click="btnClick">按钮</button>
</div>

<template id="cpn">
    <div>我是子组件</div>
</template>

<script src="../js/vue.js"></script>
<script>
    const app = new Vue({
        el: '#app',
        methods: {
            btnClick() {
                console.log(this.$children)
                this.$children[0].name
                for (let c of this.$children) {
                    console.log(c.name)
                }
            },
        },
        components: {
            cpn: {
                template: '#cpn',
                data() {
                    return {
                        name: '我是子组件的name',
                    }
                },
            },
        },
    })
</script>
  • $refs
<div id="app">
    <cpn ref="aaa"></cpn>
    <button @click="btnClick">按钮</button>
</div>

<template id="cpn">
    <div>我是子组件</div>
</template>

<script src="../js/vue.js"></script>
<script>
    const app = new Vue({
        el: '#app',
        methods: {
            btnClick() {
                console.log(this.$refs.aaa.name)
            },
        },
        components: {
            cpn: {
                template: '#cpn',
                data() {
                    return {
                        name: '我是子组件的name',
                    }
                },
            },
        },
    })
</script>
  1. 子组件 访问 父组件 (不常用)
  • $parent <访问父组件>
<div id="app">
    <cpn></cpn>
</div>

<template id="cpn">
    <div>
        <h3>我是子组件</h3>
        <button @click="btnClick">按钮</button>
    </div>
</template>

<script src="../js/vue.js"></script>
<script>
    const app = new Vue({
        el: '#app',
        components: {
            cpn: {
                template: '#cpn',
                methods: {
                    btnClick() {
                        // 访问父组件
                        console.log(this.$parent)
                    },
                },
            },
        },
    })
</script>
  • $root <访问根组件>
<div id="app">
    <cpn></cpn>
</div>

<template id="cpn">
    <div>
        <h3>我是子组件</h3>
        <button @click="btnClick">按钮</button>
    </div>
</template>

<script src="../js/vue.js"></script>
<script>
    const app = new Vue({
        el: '#app',
        components: {
            cpn: {
                template: '#cpn',
                methods: {
                    btnClick() {
                        // 访问根组件 $root
                        console.log(this.$root)
                    },
                },
            },
        },
    })
</script>

2.2 插槽(slot)的使用

  • 基本使用
<div id="app">
    <!-- 1. 未设置插槽的标签 -->
    <cpn></cpn>

    <!-- 2. 设置一个插槽的值 -->
    <cpn><i>我是i标签</i></cpn>

    <!-- 3. 设置多个插槽的值 -->
    <cpn>
        <div>我是div标签</div>
        <a>我是a标签</a>
    </cpn>
</div>

<template id="cpn">
    <div>
        <h3>我是h3标签</h3>
        <p>我是p标签</p>
        <!-- slot 中设置默认标签, 如果没有替换的标签, 显示默认的标签 -->
        <slot>
            <button>我是btn按钮</button>
        </slot>
    </div>
</template>
  • 具名插槽
<div id="app">
    <!-- 定位替换 确定好插槽的名字 -->
    <cpn>
        <span slot="center">我是新的span标签</span>
    </cpn>
</div>

<template id="cpn">
    <div>
        <!-- 写入每个插槽的名字 -->
        <slot name="left"><span>左边</span></slot>
        <slot name="center"><span>中间</span></slot>
        <slot name="right"><span>右边</span></slot>
    </div>
</template>
  • 编译的作用域
<div id="app">
    <!-- 1. 直接显示 -->
    <cpn></cpn>

    <cpn>
        <!-- 2. 转换显示方式 -->
        <template slot-scope="slot">
            <p v-for="item in slot.data">{{item}} -</p>
            <p>{{slot.data.join(' - ')}}</p>
            <p>{{slot.data.join(' * ')}}</p>
        </template>
    </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',
        components: {
            cpn: {
                template: '#cpn',
                data() {
                    return {
                        pLanguages: [
                            'JavaScript',
                            'Python',
                            'C++',
                            'C#',
                            'Swift',
                        ],
                    }
                },
            },
        },
    })
</script>
  • 作用域插槽

第三章 前端模块化

3.1 为什么使用模块化

  • 简单写 js 代码带来的问题
  • 闭包引起代码不可复用
  • 自己实现了简单的模块化
  • AMD/CMD/CommonJS

3.2 ES6 中模块化的使用

  • export (导出)
// 1. CommonJS 模块化 导出
module.export = {
    add,
    mul,
}

// 2. ES6 模块化 导出
export const name = 'Tom'
export const age = 18
export const height = 1.88
  • import (导入)
/* 1. CommonJs 模块化 导入 */
const { add, mul } = require('./js/mathUtils.js')

/* 2. ES6 模块化导入 */
import * as info from './js/info.js'

// 例外
/* 3. 依赖 文件 导入 */
require('./css/normal.css')
上一篇:vue中的插槽


下一篇:Vue父子组件的相互调用方法与参数