案例式驱动,每个案例一个小例子,带领大家领略
基本语法:
<script>
Vue.component('组件名称', {
data: '组件数据',
template: '组件模板内容(HTML 标签)'
})
script>
示例:
我们以一个点击按钮数据累加计算来演示组件的使用
<html>
<head>
<meta charset="utf-8">
<title>组件化开发title>
head>
<body>
<div id="app">
<button-counter>button-counter>
<button-counter>button-counter>
<button-counter>button-counter>
div>
<script src="../vue.js">script>
<script>
// Vue.component('button-counter' 两种方式
Vue.component('ButtonCounter', {
// 使用函数,形成一个闭包的环境,保证每个数据都是独立的。
data() {
return {
count: 0
}
},
// template: '点击了{{count}}次',
template: '点击了{{count}}次',
methods: {
handle: function() {
this.count++;
},
}
})
var app = new Vue({
el: "#app",
data: {
}
})
script>
body>
html>
我们在 Vue 实例中添加 components 属性,在这里我们就可以自定义自己的局部组件,使用方式和全局组件的差别不大
<html>
<head>
<meta charset="utf-8">
<title>局部组件化开发title>
head>
<body>
<div id="app">
<component-a>component-a>
div>
<script src="../vue.js">script>
<script>
let ComponetA = {
data() {
return {
msg: 'Hello World'
}
},
template: '{{msg}}',
methods: {
}
}
var app = new Vue({
el:"#app",
data:{
},
components: {
'component-a': ComponetA
}
})
script>
body>
html>
演示效果
注册基本事项:
但是在普通得模板标签中,必须使用横线的方式使用组件
<html>
<head>
<meta charset="utf-8">
<title>组件数据传递title>
head>
<body>
<div id="app">
<h3>父组件向子组件传递数据h3>
<div>
{{pmsg}}
div>
<h3>二、静态数据传递h3>
<menu-item title="来自父组件的值">menu-item>
<h3>三、动态数据传递h3>
<menu-item :title="ptitle">menu-item>
<menu-item :title="pmsg" content="hello">menu-item>
<h3>四、短横线绑定h3>
<my-menu menu-title="Hello">my-menu>
<h3>五、数组传递h3>
<my-array :arr="parray">my-array>
<h3>六、对象传递h3>
<my-obj :person="person">my-obj>
div>
<script src="../vue.js">script>
<script type="text/javascript">
Vue.component('menu-item', {
// props 接收父组件传过来的内容
props: ['title', 'content'],
data() {
return {
msg: '子组件本身的数据'
}
},
template: '{{msg + "----" + title + "------" + content}}'
});
Vue.component('my-menu', {
props: ['menuTitle'],
template: '{{menuTitle}}'
});
// 遍历数组
Vue.component('my-array', {
props: ['arr'],
template: '{{item}}'
});
Vue.component('my-obj', {
props: ['person'],
template: '{{person.name}} {{person.age}}'
})
var app = new Vue({
el:"#app",
data:{
pmsg: '父组件的内容',
ptitle: '动态绑定属性',
parray: ['apple','orange','banana'],
person: {
name: 'coco',
age: 18
}
}
})
script>
body>
html>
子组件向父组件传值
props 传递数据原则,单向数据流
接下来我们以一个改变字体大小 以及 传递数组的实例来给给大家演示子组件向父最贱传递数据的流程
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>子组件向父组件传递数据</title>
</head>
<body>
<div id="app">
<!-- style 属性绑定 -->
<div :style="{fontSize: fontSize + 'px'}">{{pmsg}}</div>
<!-- 这个监听事件的名称必须和子组件的事件完全一致 -->
<menu-item :parr="parr" @enlarge-text="handle"></menu-item>
</div>
<script src="../vue.js"></script>
<script>
// 子组件向父组件传值 —— 基本用法
Vue.component('menu-item', {
props: ['parr'],
template:`
<div>
<ul>
<li :key="index" v-for="(item, index) of parr">{{item}}</li>
</ul>
<button @click="parr.push('lemon')">点击</button>
<button @click="$emit('enlarge-text')">扩大父组件中字体大小</button>
</div>
`
})
var app = new Vue({
el: "#app",
data: {
pmsg: '我是父组件的信息',
parr: ['orange','apple','banana','watermelen'],
fontSize: 10
},
methods: {
handle: function() {
// 扩大字体大小
this.fontSize += 5;
}
}
})
</script>
</body>
</html>
基本和上面一致
子组件传递的数据,在父组件中要通过 $event 来接收数据
<html>
<head>
<meta charset="utf-8">
<title>子组件向父组件传递数据title>
head>
<body>
<div id="app">
<div :style="{fontSize: fontSize + 'px'}">{{pmsg}}div>
<menu-item :parr="parr" @enlarge-text="handle($event)">menu-item>
div>
<script src="../vue.js">script>
<script>
// 子组件自定义向父组件传值 —— 基本用法
/**
* props 传递数据原则,单向数据流
* 1. 子组件通过自定义事件向父组件传递信息 $emit
* 2. 父组件监听子组件的事件
* 3. 父组件通过 $event 获取值
* */
Vue.component('menu-item', {
props: ['parr'],
template:`
{{item}}
点击
扩大父组件中字体大小
扩大父组件中字体大小
`
})
var app = new Vue({
el: "#app",
data: {
pmsg: '我是父组件的信息',
parr: ['orange','apple','banana','watermelen'],
fontSize: 10
},
methods: {
handle: function(val) {
// 扩大字体大小
this.fontSize += val;
}
}
})
script>
body>
html>
通过事件中心完成交互
使用方式:
// 单独创建时间中心管理组件间的通信
var eventHub = new Vue();
// 监听事件和销毁事件
eventHub.$on('add-todo',addTodo); // 自定义事件名称 事件函数
eventHub.$off('add-tod');
// 触发事件
eventHub.$emit('add-todo',id);
示例
<html>
<head>
<meta charset="utf-8">
<title>组件化开发title>
head>
<body>
<div id="app">
<div>事件销毁div>
<div>
<button @click="handle">点击button>
div>
<test-tom>test-tom>
<test-jerry>test-jerry>
div>
<script src="../vue.js">script>
<script>
/**
* 兄弟组件传值
* */
// 提供事件中心
var eventHub = new Vue();
Vue.component('test-tom', {
data() {
return {
num: 0
}
},
template: `
TOM:{{num}}
点击
`,
methods: {
handle: function() {
// 触发兄弟组件的事件
eventHub.$emit('jerry-event',2);
}
},
mounted() {
// 监听事件, 使用箭头函数,使用 this
eventHub.$on('tom-event', (val)=> {
this.num+=val;
})
}
})
Vue.component('test-jerry', {
data() {
return {
num: 0
}
},
template: `
JERRY:{{num}}
点击
`,
methods: {
handle: function() {
// 触发兄弟组件的事件
eventHub.$emit('tom-event',1);
}
},
mounted() {
// 监听事件, 使用箭头函数,使用 this
eventHub.$on('jerry-event', (val)=> {
this.num+=val;
})
}
})
var app = new Vue({
el: "#app",
data: {
},
methods: {
// 事件销毁
handle: function() {
eventHub.$off('tom-event');
eventHub.$off('jerry-event');
}
}
})
script>
body>
html>
slot 是 vue 提供的 API,使用 slot 在子组件,我们可以在模板中插入我们想要的数据,我们还可以在 slot 中添加默认的数据
<html>
<head>
<meta charset="utf-8">
<title>组件化开发title>
head>
<body>
<div id="app">
<test-box>
<h3>我没有通过 slot,我进不来h3>
test-box>
<hr>
<alert-box>
<h3>我通过 slot 插入进来了h3>
alert-box>
div>
<script src="../vue.js">script>
<script>
Vue.component('test-box',{
template: `
没插槽的时候
`,
})
Vue.component('alert-box', {
template: `
有插槽的时候
`,
})
var app = new Vue({
el: "#app",
data: {
}
})
script>
body>
html>
在一个组件中,我们可以指定多个插槽插入数据,但是为了区分这些数据,我们会设置一个 name 值来标识唯一的插槽
<html>
<head>
<meta charset="utf-8">
<title>组件化开发title>
head>
<body>
<div id="app">
<base-layout>
<p slot="header">标题信息p>
<p>我是主要内容p>
<p>我是主要内容p>
<p slot="footer">底部信息p>
base-layout>
<hr />
<base-layout>
<template slot="header">
<p>标题信息1p>
<p>标题信息2p>
template>
<p>我是主要内容p>
<p>我是主要内容p>
<template slot="footer">
<p>底部信息1p>
<p>底部信息2p>
template>
base-layout>
div>
<script src="../vue.js">script>
<script>
Vue.component('base-layout', {
template: `
`
})
var app = new Vue({
el: "#app"
})
script>
body>
html>
应用场景: 父组件对子组件的内容进行加工处理。
使用方式:
<html>
<head>
<meta charset="utf-8">
<title>作用域插槽title>
head>
<style>
.current {
color: orange;
}
style>
<body>
<div id="app">
<first-fruit :list="list">
<template slot-scope="slotProps">
<strong v-if="slotProps.info.id == 2" class="current">
{{slotProps.info.name}}
strong>
<span v-else>
{{slotProps.info.name}}
span>
template>
first-fruit>
div>
<script src="../vue.js">script>
<script type="text/javascript">
Vue.component('first-fruit',{
props: ['list'],
template: `
{{item.name}}
`
})
var vm = new Vue({
el:"#app",
data: {
list: [{
id: 1,
name: 'apple'
},{
id: 2,
name: 'banana'
},{
id: 3,
name: 'orange'
}]
}
})
script>
body>
html>