第一章 组件化
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 模板的分离写法
- 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>
- 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 数据的存放
- 子组件不能访问父组件
- 子组件有自己的 data,而且必须是一个函数
Vue.component(`cpn`, {
template: `#cpn1`,
data() {
return {
counter: 0
}
}
- 为什么是一个函数?
目的:让每一个控件独立的存在,不发生多个绑定在一起
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 父子组件的访问
- 父组件 访问 子组件
- $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>
- 子组件 访问 父组件 (不常用)
- $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')