Vue.js-组件系统
vue.js 组件
组件是一个Vue可复用的实例
全局组件
全局注册的组件可以用在其被注册之后的任何 (通过 new Vue
) 新创建的 Vue 根实例,也包括其组件树中的所有子组件的模板中。
组件是可复用的 Vue 实例,且带有一个名字:在这个例子中是 <button-counter>
。我们可以在一个通过 new Vue
创建的 Vue 根实例中,把这个组件作为自定义元素来使用:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./static/vue.js"></script>
</head>
<body>
<div id="app">
<button-counter></button-counter>
<button-counter></button-counter>
<button-counter></button-counter>
</div>
<script>
// 全局组件的注册,使用component实例化一个vue实例
// 因为组件是可复用的 Vue 实例,所以它们与 new Vue 接收相同的选项,例如 data、computed、watch、methods 以及生命周期钩子等。仅有的例外是像 el 这样根实例特有的选项。
Vue.component('button-counter', {
// 一个组件的 data 选项必须是一个函数,因此每个实例可以维护一份被返回对象的独立的拷贝
data: function () {
return {
count: 0
}
},
template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>'
});
// 实例化vue放下面
new Vue({
el: '#app',
});
</script>
</body>
</html>
因为组件是可复用的 Vue 实例,所以它们与 new Vue
接收相同的选项,例如 data
、computed
、watch
、methods
以及生命周期钩子等。仅有的例外是像 el
这样根实例特有的选项。
局部组件
全局注册往往是不够理想的。比如,如果你使用一个像 webpack 这样的构建系统,全局注册所有的组件意味着即便你已经不再使用一个组件了,它仍然会被包含在你最终的构建结果中。这造成了用户下载的 JavaScript 的无谓的增加。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./static/vue.js"></script>
</head>
<body>
<div id="app">
<component-a></component-a>
<component-b></component-b>
<component-c></component-c>
<component-d></component-d>
</div>
<script>
let ComponentA = {
template: '<button >ComponentA</button>',
};
let ComponentB = {
template: '<button >ComponentB</button>',
};
let ComponentC = {
template: '<button >ComponentC</button>',
};
// 如果想在ComponentD用ComponentA需按照以下定义
let ComponentD = {
template: '<button >ComponentD</button>',
components: {
'component-a': ComponentA,
'component-b': ComponentB,
'component-c': ComponentC,
},
};
new Vue({
el: '#app',
// 注册局部组件, key是自定义的名称,value是定义的局部组件
components: {
// 'component-a': ComponentA,
// 'component-b': ComponentB,
// 'component-c': ComponentC,
'component-d': ComponentD,
'component-a': ComponentD.components["component-a"],
'component-b': ComponentD.components["component-b"],
'component-c': ComponentD.components["component-c"],
},
});
</script>
</body>
</html>
组件的注意事项
- is标识 ==》 table里面只认识tr标签不认识你写的组件
- 组件中的data必须是函数!!!保证每个组件内部的数据都是独立的!
vue首页导航栏超简易版
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./static/vue.js"></script>
<style>
.default {
display: none;
}
.active {
display: block;
}
</style>
</head>
<body>
<div id="app">
<pg-header></pg-header>
</div>
<script>
let pgHeader = {
data: function () {
return {
books: [
{
title: "学习",
bookSrc: [
{bookName: "教程", bookAddr: "https://cn.vuejs.org/v2/guide/",},
{bookName: "API", bookAddr: "https://cn.vuejs.org/v2/api/"},
{bookName: "风格指南", bookAddr: "https://cn.vuejs.org/v2/style-guide/"},
]
},
{
title: "支持Vue",
bookSrc: [
{bookName: "一次性赞助", bookAddr: "https://cn.vuejs.org/support-vuejs/#One-time-Donations",},
{bookName: "周期性赞助", bookAddr: "https://cn.vuejs.org/support-vuejs/#Recurring-Pledges"},
]
}
],
isDefault: true,
curIndex: 0,
}
},
template: `
<div><div v-for="(val,index) in books" style="float: left " @mouseenter="mouseEnter(index)" >{{val['title']}}
<ul :class="{default:isDefault, active:index===curIndex} " >
<li v-for="(book,index2) in val['bookSrc']"><a :href="book['bookAddr']">{{book['bookName']}}</a></li>
</ul>
</div></div>
`,
methods: {
mouseEnter: function (index) {
this.curIndex = index;
}
},
};
new Vue({
el: '#app',
components: {
'pg-header': pgHeader,
},
});
</script>
</body>
</html>
父子组件之间的数据传递
父向子传递数据
- 在子组件中通过
props
声明需要被传递的参数 - 在父组件中通过
v-bind:变量名='变量'
传递数据
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./static/vue.js"></script>
</head>
<body>
<div id="app">
<father></father>
</div>
<script>
// 2. 在子组件中使用props接收这个数据
let child = {
template: `<div>{{fatherDate}}</div>`,
props: ['fatherDate']
};
// 1. 在父组件里面的子组件中绑定一个自定义属性l
let father = {
template: `<div><child v-bind:fatherDate="msg"></child></div>`,
data: function () {
return {
msg: 'hahahahahahaha',
}
},
components: {
'child': child,
}
};
new Vue({
el: '#app',
components: {
'father': father,
},
});
</script>
</body>
</html>
子向父传递数据
- 子组件中通过
$emit
('自定义事件名')向外抛出自定义事件 - 父组件中用过
v-on:自定义事件名=动作函数
监听子组件抛出的事件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./static/vue.js"></script>
</head>
<body>
<div id="app">
<father></father>
</div>
<script>
let child = {
template: `<div><button v-on:click="changeSize">点击修改父组件的字体大小</button></div>`,
methods: {
changeSize: function () {
this.$emit("change-size");
}
}
};
// 1. 在父组件的子组件中绑定一个自定义事件
let father = {
template: `<div><child v-on:change-size="fontSize++"></child>
<span :style="{fontSize: fontSize + 'px'}">233</span></div>`,
data: function () {
return {
fontSize: 20,
}
},
components: {
'child': child,
}
};
new Vue({
el: '#app',
components: {
'father': father,
}
});
</script>
</body>
</html>
组件间传值
借助一个独立的Vue对象实现组件间通信
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="./static/vue.js"></script>
</head>
<body>
<div id="app">
<my-component-a></my-component-a>
<hr>
<my-component-b></my-component-b>
</div>
<script>
/*
* 简介
* 两个独立的组件,A,B(data),B中修改数据data,A中实时获取B中修改的数据data
*
* */
// 借助一个空的Vue对象实现组件间通信
let bus = new Vue(); // 大项目用这个VueX
let A = {
template: `
<div>
<h1>这是子组件:my-component-a</h1>
<p>my-component-a被选中的次数:{{num}}</p>
</div>
`,
data() {
return {
num: 0,
}
},
mounted() {
// 在文档准备就绪之后就要开始监听bus是否触发了 dianwo 的事件
/*
bus.$on('dianwo', function (val) {
console.log(val);
// this.num++; // 这个 this 是谁?
console.log(this); // this 并不是组件A
})
*/
bus.$on('dianwo', (val) => {
this.num++; // 这个 this 是谁?
console.log(this); // this 是组件A
})
},
};
let B = {
template: `
<div>
<h1>这是子组件:my-component-b</h1>
<button v-on:click="add">点我</button>
</div>
`,
data() {
return {
num: 0,
}
},
methods: {
add() {
this.num++;
// 利用bus对象抛出一个自定义事件
bus.$emit('dianwo', this.num);
}
}
};
let app = new Vue({
el: '#app',
data: {
totalNum: 0,
},
components: {
'my-component-a': A,
'my-component-b': B,
}
});
</script>
</body>
</html>
混入
提高代码重用性
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./static/vue.js"></script>
</head>
<body>
<div id="app">
<aaa></aaa>
<bbb></bbb>
</div>
<script>
let xxx = {
methods: {
show: function (name) {
console.log(`${name}`)
},
hide: function (name) {
console.log(`${name}`)
}
}
};
let aaa = {
template: `<div>
<button v-on:click="show('233')">233</button>
<button v-on:click="hide('233')">233</button>
</div>`,
mixins: [xxx]
};
let bbb = {
template: `<div>
<button v-on:click="show('666')">666</button>
<button v-on:click="hide('666')">666</button>
</div>`,
mixins: [xxx]
};
new Vue({
el: '#app',
components: {
'aaa': aaa,
'bbb': bbb,
}
})
</script>
</body>
</html>
插槽
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./static/vue.js"></script>
<style>
* {
padding: 0;
margin: 0;
}
.box {
height: 200px;
width: 200px;
background-color: red;
float: left;
margin-left: 20px;
text-align: center;
line-height: 100px;
}
</style>
</head>
<body>
<div id="app">
<global-component>
<template slot="header">这里是header</template>
<template slot="body">哈哈哈哈</template>
</global-component>
<!--如果没有值将会采用默认值-->
<global-component></global-component>
</div>
<script>
Vue.component('global-component', {
// <slot></slot> 可以使上面插入233,也就是说可以在html中插入数据
// <slot name="body">666</slot> 具名插槽
template: `<div><div class="box">
<strong><slot name="header">header</slot></strong>
<br>
<slot name="body">body</slot>
</div></div>`
});
new Vue({
el: '#app',
})
</script>
</body>
</html>
element-ui
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="./static/vue.js"></script>
<!-- 引入样式 -->
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
<!-- 引入组件库 -->
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
<style>
.el-carousel__item h3 {
color: #475669;
font-size: 14px;
opacity: 0.75;
line-height: 150px;
margin: 0;
}
.el-carousel__item:nth-child(2n) {
background-color: #99a9bf;
}
.el-carousel__item:nth-child(2n+1) {
background-color: #d3dce6;
}
</style>
</head>
<body>
<div id="app">
<template>
<div class="block">
<el-carousel height="">
<el-carousel-item v-for="(val,index) in images" :key="index">
<img :src="val" alt="" style="width: 100%">
</el-carousel-item>
</el-carousel>
</div>
</template>
</div>
<script>
new Vue({
el: '#app',
data: {
images: ['./images/1.png', './images/2.png', './images/3.png', './images/4.png', './images/5.png'],
}
})
</script>
</body>
</html>