组件化开发
01-组件化开发
01-组件化开发的基本使用
组件使用的三个步骤:
- 创建组件构造器
- 注册组件
- 使用组件
<div id="app">
<!-- 3 使用组件-->
<my-cpn></my-cpn>
<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>
<p>我是内容 123</p>
</div>`
})
//2 注册组件
Vue.component('my-cpn',cpnC)
const app = new Vue({
el:'#app',
data:{
message:'你好啊!'
}
})
</script>
02-全局组件和局部组件
使用Vue.component()进行组件注册,此时注册的为全局组件;
而在Vue中components下注册的则是局部组件;
<!-- 组件的使用 -->
<div id="app">
<cpn></cpn>
<cpn></cpn>
<cpn></cpn>
</div>
<script src="../js/vue.js"></script>
<script>
const cpnC = Vue.extend({
template:`
<div>
<h2>我是标题</h2>
<p>我是内容 12323456</p>
</div>
`
})
// 注册组件是全局组件,可以在多个vue实例下面使用
Vue.component('cpn',cpnC)
const app = new Vue({
el:'#app',
data:{
message:'你好啊!'
},
components:{
// 局部组件的注册
cpn: cpnC //cpn 使用组件的标签名 cpnC 组件构造器
}
})
</script>
03-父组件和子组件
<!-- 组件的使用-->
<div id="app">
<cpn2></cpn2>
<cpn1></cpn1>
</div>
<script src="../js/vue.js"></script>
<script>
//1 创建第一个组件(子组件)
const cpnC1 = Vue.extend({
template:`
<div>
<h2>我是标题1</h2>
<p>我是内容123456</p>
</div>
`
})
//创建第二个组件(父组件)
const cpnC2 = Vue.extend({
template:`
<div>
<h2>我是标题2</h2>
<p>我是内容,abcdef</p>
<cpn1></cpn1>
</div>
`,
components: {
//注册组件cpn1为cpn2的子组件
cpn1: cpnC1
}
})
//root组件
const app = new Vue({
el:'#app',
data:{
message:'你好啊!'
},
components:{
//注册组件cpn2,cpn1
cpn2: cpnC2,
cpn1: cpnC1
}
})
</script>
将组件cpn1注册为cpn2的子组件,在cpn2的组件创建时可以使用组件cpn1;
将cpn1和cpn2都在vue中注册,则在组件使用时这两个组件均可使用。
04-组件的语法糖注册方式
组件的语法糖注册方式中将不再使用Vue.extend()来创建组件,而是将注册组件和创建组件都放在Vue.component()下。
<!--组件的使用-->
<div id="app">
<cpn1></cpn1>
<cpn2></cpn2>
</div>
<script src="../js/vue.js"></script>
<script>
// 全局组件(语法糖方式):
// 1 创建组件构造器
//2 注册组件
Vue.component('cpn1',{
template:`
<div>
<h2>我是标题1</h2>
<p>我是内容123456</p>
</div>
`
})
const app = new Vue({
el:'#app',
data:{
message:'你好啊!'
},
components:{
'cpn2':{
template:`
<div>
<h2>我是标题2</h2>
<p>我是内容123456</p>
</div>
`
}
}
})
</script>
05-组件模块的分离写法
在注册时template仅声明id序号,组件模板写在注册外面。
1、通过script标签
<script type="text/x-template" id="cpn">
<div>
<h2>我是标题</h2>
<p>我是内容 123456</p>
</div>
</script>
2、通过template标签
<template id="cpn">
<div>
<h2>我是标题</h2>
<p>我是内容 12345</p>
</div>
</template>
完整代码:
<div id="app">
<cpn></cpn>
<cpn></cpn>
<cpn></cpn>
</div>
<!--1 通过script 标签 -->
<script type="text/x-template" id="cpn1">
<div>
<h2>我是标题</h2>
<p>我是内容 123456</p>
</div>
</script>
<!--2 template标签-->
<template id="cpn2">
<div>
<h2>我是标题</h2>
<p>我是内容 12345</p>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
// 1 注册一个全局组件
Vue.component('cpn1',{
template:'#cpn1'
})
Vue.component('cpn2',{
template:'#cpn2'
})
const app = new Vue({
el:'#app',
data:{
message:'你好啊!'
}
})
</script>
06-组件中的数据存放问题
组件中数据存放,需要写在注册组件时,即Vue.component()中,其data是函数,需要返回值。
<script>
// 1 注册一个全局组件
Vue.component('cpn',{
template:'#cpn',
//组件数据存放
data(){
return {
title:'123'
}
}
})
</script>
完整代码:
<!-- 组件使用-->
<div id="app">
<cpn></cpn>
</div>
<!-- 组件内容-->
<template id="cpn">
<div>
<h2>{
{title}}</h2>
<p>我是内容 12345</p>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
// 1 注册一个全局组件
Vue.component('cpn',{
template:'#cpn',
//组件数据存放
data(){
return {
title:'123'
}
}
})
const app = new Vue({
el:'#app',
data:{
message:'你好啊!'
}
})
</script>
07-组件通信-父组件向子组件传递参数
通过props向子组件传递数据,props声明在Vue.component()中,是一个对象;
<div id="app">
<cpn v-bind:cmovies="movies" :cmessage="message"></cpn>
</div>
<template id="cpn">
<div>
<h2>{
{cmessage}}</h2>
<ul>
<li v-for="item in cmovies">{
{item}}</li>
</ul>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
//父传子:props
const cpn = {
template:'#cpn',
//1 类型的限制
// props:['cmovies','cmessage'],
props:{
cmovies: {
type: Array,
default(){
return []
}
},
cmessage: {
type: String,
default: '123456',
required: true
},
},
data(){
return{
}
},
methods:{
}
}
const app = new Vue({
el:'#app',
data:{
message:'你好啊!',
movies:['123','456','789']
},
components:{
cpn
}
})
</script>
08-组件通信-子组件向父组件传递事件
通过事件,子组件向父组件传送信息。
<!--父组件模板-->
<div id="app">
<cpn @item-click="cpnClick"></cpn>
</div>
<!--子组件模板-->
<template id="cpn">
<div>
<button @click="btnClick(item)" v-for="item in categories">{
{item.name}}</button>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
//子组件
const cpn = {
template:'#cpn',
data(){
return{
categories:[
{
id: 'aaa',name: '热门推荐'},
{
id: 'bbb',name: '手机数码'},
{
id: 'ccc',name: '家用家电'},
{
id: 'ddd',name: '电脑办公'}
]
}
},
methods:{
btnClick(item){
//子组件发射事件
this.$emit('item-click',item)
}
}
}
//父组件
const app = new Vue({
el:'#app',
data:{
message:'你好啊!'
},
components:{
cpn,
},
methods: {
//父组件接受
cpnClick(item){
console.log('cpnClick',item)
}
}
})
</script>
【界面交互展示】
数据保存在父组件中,按钮为子组件,点击按钮,监听按钮的事件传到父组件中,父组件接受事件,通过在控制台打印,证明父组件确实接收到了来自子组件的信息。
09-组件访问-父访问子-children-refs
1、使用children进行访问,此访问只能通过下标获取数据;
2、使用refs来访问,通过定义refs来获取数据;
<div id="app">
<cpn ref="aaa"></cpn>
<cpn ref="bbb"></cpn>
<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',
data:{
message:'你好啊!'
},
methods: {
btnClick(){
//1 $children
// console.log(this.$children);
// this.$children[0].showMessage();
// 2 $refs
console.log(this.$refs.aaa);
console.log(this.$refs.bbb)
}
},
components:{
cpn:{
template:'#cpn',
methods: {
showMessage(){
console.log('showMessage');
}
}
},
}
})
</script>
10-组件访问-子访问父-parent-root
1、parent访问父组件(上一级);
2、root访问根组件;
<div id="app">
<cpn></cpn>
</div>
<template id="cpn">
<div>
<h2>我是cpn组件</h2>
<ccpn></ccpn>
</div>
</template>
<template id="ccpn">
<div>
<h2>我是子组件</h2>
<button @click="btnClick">按钮</button>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el:'#app',
data:{
message:'你好啊!'
},
components:{
cpn:{
template:'#cpn',
components: {
ccpn:{
template: '#ccpn',
data(){
return {
name: '我是子组件cpn的name'
}
},
methods:{
btnClick(){
//1 访问父组件$parent
// console.log(this.$parent);
// console.log(this.$parent.name);
//2 访问根组件$root
console.log(this.$root);
console.log(this.$root.message)
}
}
}
},
},
}
})
</script>
02-插槽slot
01-插槽的基本使用
预留插槽,使用时在自定义标签中添加标签来替代预留插槽,若不再添加标签,则预留插槽会显示默认标签;
<div id="app">
<cpn><button>按钮</button></cpn>
<cpn><span>哈哈哈</span></cpn>
<cpn></cpn>
<cpn></cpn>
</div>
<template id="cpn">
<div>
<h2>我是组件</h2>
<p>我是组件123456</p>
<!-- 预留插槽-->
<slot><button>按钮</button></slot>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el:'#app',
data:{
message:'你好啊!'
},
components:{
cpn:{
template:'#cpn',
}
}
})
</script>
【页面分析】
02-具名插槽的使用
在slot标签中添加name属性,用来表明替换位置;
<div id="app">
<cpn><span slot="center">标题</span></cpn>
<cpn><button slot="left">返回</button></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>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el:'#app',
data:{
message:'你好啊!'
},
components:{
cpn:{
template:'#cpn',
}
}
})
</script>
【界面分析】
03-作用域插槽
<div id="app">
<cpn></cpn>
<cpn>
<template slot-scope="slot">
<span v-for="item in slot.data">{
{item}}-</span>
</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',
data:{
message:'你好啊!'
},
components:{
cpn:{
template:'#cpn',
data(){
return {
pLanguages:['JavaScript','C++','Java','Python','Go','Swift']
}
}
}
}
})
</script>
03-ES6模块化开发
aaa.js
var name = '小明'
var age = 18
var flag = true
function sum(num1,num2) {
return num1 + num2
}
if(flag){
console.log(sum(20,30))
}
// 导出方式1
export {
flag,sum
}
// 导出方式2
export var num1 = 1800
export var height = 1.88
// 导出函数/类
export function mul(num1,num2) {
return num1 * num2
}
export class Person {
run(){
console.log('在奔跑');
}
}
//export default
//某些情况下,一个模块中包含某个功能,我们并不希望给这个功能命名,而是让导入者可以自己来命名,这个时候就可以使用export default
// const address = '北京市';
// export default address;
export default function (argument) {
console.log(argument);
}
bbb.js
import {
sum}from'./aaa.js'
var name = '小红'
var flag = false
console.log(sum(20, 50));
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script src="aaa.js" type="module"></script>
<script src="bbb.js" type="module"></script>
<script src="mmm.js" type="module"></script>
</body>
</html>
mmm.js
import {
flag,sum} from "./aaa.js";
if(flag){
console.log('小明是天才,哈哈哈');
console.log(sum(20, 30));
}
import {
num1,height} from "./aaa.js";
console.log(num1);
console.log(height);
import {
mul,Person} from "./aaa.js";
console.log(mul(12,23));
p.run();
//导入export default的内容
import addr from './aaa.js'
addr('你好啊!');
//导入全部内容
import * as aaa from './aaa.js'
console.log(aaa.flag);
console.log(aaa.height);