组件基础
组件基础
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>组件基础</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
<div id="components-demo1">
<!-- 组件是可复用的Vue实例 -->
<button-counter></button-counter>
<button-counter></button-counter>
<button-counter></button-counter>
</div>
<script>
// Vue.component 全局注册组件
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)
new Vue({
el: '#components-demo1'
})
</script>
</body>
</html>
向子组件传递数据
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>向子组件传递数据</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
<div id="components-demo2">
<!-- title2 自定义的attribute -->
<!-- 将数据传递到自定义component中 -->
<blog-post1 title2="title-2"></blog-post1>
<!-- 通过v:bind动态传递prop -->
<blog-post2 v-for="post in posts"
v-bind:key="post.id"
v-bind:post="post"></blog-post2>
</div>
<script>
Vue.component('blog-post1', {
// 使用prop自定义一个attribute
props: ['title2'],
// 在模版中使用通过prop传递的数据
template: `<h3>{{ title2 }}</h3>`
})
Vue.component('blog-post2', {
props: ['post'],
// 模版只能有一个根元素(使用div标签包裹内容)
template: `
<div>
<h3>{{ post.title }}</h3>
<p>{{ post.content }}</p>
</div>`
})
new Vue({
el: '#components-demo2',
data: {
posts: [
{id: 1, title: 'title-aaa', content: 'content-aaa'},
{id: 2, title: 'title-bbb', content: 'content-bbb'},
{id: 3, title: 'title-ccc', content: 'content-ccc'},
]
}
})
</script>
</body>
</html>
监听子组件事件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>监听子组件事件</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
<div id="components-demo3" :style="{fontSize: postFontSize + 'em'}">
<!-- 使用v-on来监听子组件定义的任意事件 -->
<!-- 在组件实例中实现具体的事件逻辑 -->
<!-- 使用$event访问模版中提供的特定值 -->
<blog-post1 title="title-1"
v-on:enlarge-text="postFontSize +=0.1"
v-on:reduce-text="postFontSize -=$event"
v-on:reset-text="onResetText($event)">
</blog-post1>
<!-- 在组件上使用v-model -->
<p>{{text1}}</p>
<blog-post2 v-model="text1"></blog-post2>
</div>
<script>
Vue.component('blog-post1', {
props: ['title'],
template: `
<div>
<h3>{{ title }}</h3>
<!-- 模版中定义出发方式与调用方法-->
<!-- 调用内建的$emit方法并传入事件名称来触发事件 -->
<button v-on:click="$emit('enlarge-text')">
Enlarge Text
</button>
<!-- $emit方法第二个参数为定义的事件提供特定值 -->
<button v-on:click="$emit('reduce-text', 0.1)">
Reduce Text
</button>
<button v-on:click="$emit('reset-text', 1)">
Reset Text
</button>
</div>`
})
Vue.component('blog-post2', {
// 在组件上使用v-model需要使用如下代码
// 将其 value attribute 绑定到一个名叫 value 的 prop 上
// 在其 input 事件被触发时,将新的值通过自定义的 input 事件抛出
props: ['value'],
template: `
<input
v-bind:value="value"
v-on:input="$emit('input', $event.target.value)"/>
`
})
new Vue({
el: '#components-demo3',
data: {
postFontSize: 1,
text1: "123"
},
methods: {
onResetText: function (resetValue) {
this.postFontSize = resetValue;
}
}
})
</script>
</body>
</html>
通过插槽分发内容
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>通过插槽分发内容</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<style>
.demo-alert-box {
padding: 10px 20px;
background: #eac0ba;
border-style: solid;
border-width: 1px;
border-color: #e29c9a;
}
</style>
</head>
<body>
<div id="components-demo4">
<alert-box>{{msg}}</alert-box>
</div>
<script>
Vue.component('alert-box', {
template: `
<div class="demo-alert-box">
<strong>Error!</strong>
<!-- 使用Vue自定义的<slot>元素来加入插槽(替换成组件实例的内容) -->
<slot></slot>
</div>`
})
new Vue({
el: '#components-demo4',
data: {
msg: 'Something bad happened.'
}
})
</script>
</body>
</html>
动态组件
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>动态组件</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<style>
.tab-button {
padding: 6px 10px;
border-top-left-radius: 3px;
border-top-right-radius: 3px;
border: 1px solid #ccc;
cursor: pointer;
background: #f0f0f0;
margin-bottom: -1px;
margin-right: -1px;
}
.tab-button:hover {
background: #e0e0e0;
}
.tab-button.active {
background: #e0e0e0;
}
.tab {
border: 1px solid #ccc;
padding: 10px;
}
</style>
</head>
<body>
<div id="dynamic-component-demo1" class="demo">
<button v-for="tab in tabs"
v-bind:key="tab"
v-bind:class="['tab-button', { active: currentTab === tab }]"
v-on:click="currentTab = tab">
{{ tab }}
</button>
<!-- 使用v-bind:is指定已注册组件的名字 -->
<component v-bind:is="currentTabComponent" class="tab"></component>
</div>
<br/>
<div id="dynamic-component-demo2" class="demo">
<button v-for="tab in tabs"
v-bind:key="tab.name"
v-bind:class="['tab-button', { active: currentTab.name === tab.name }]"
v-on:click="currentTab = tab">
{{ tab.name }}
</button>
<!-- 使用v-bind:is指定组件的选项对象 -->
<component v-bind:is="currentTab.component" class="tab"></component>
</div>
<script>
// 使用已注册组件名示例
Vue.component("tab-home", {
template: "<div>Home component</div>"
});
Vue.component("tab-posts", {
template: "<div>Posts component</div>"
});
Vue.component("tab-archive", {
template: "<div>Archive component</div>"
});
new Vue({
el: "#dynamic-component-demo1",
data: {
currentTab: "Home",
tabs: ["Home", "Posts", "Archive"]
},
computed: {
currentTabComponent: function () {
return "tab-" + this.currentTab.toLowerCase();
}
}
});
// 使用组件的选项对象示例
var tabs = [
{
name: "Home",
component: {
template: "<div>Home component</div>"
}
},
{
name: "Posts",
component: {
template: "<div>Posts component</div>"
}
},
{
name: "Archive",
component: {
template: "<div>Archive component</div>"
}
}
];
new Vue({
el: "#dynamic-component-demo2",
data: {
tabs: tabs,
currentTab: tabs[0]
}
});
</script>
</body>
</html>
组件注册
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>组件注册</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
<div id="app1">
<!-- 全局注册的组件能用在任何Vue实例的模版中 -->
<component-a></component-a>
<component-b></component-b>
<component-c></component-c>
</div>
<br/>
<div id="app2">
<!-- 全局注册的组件能用在任何Vue实例的模版中 -->
<component-a></component-a>
<component-b></component-b>
<component-c></component-c>
<!-- 局部注册的组件只能用在被注册的Vue实例模版中 -->
<component-d></component-d>
<component-e></component-e>
<component-f></component-f>
</div>
<script>
// 建议使用kebab-case(短横线分隔命名)定义一个组件
Vue.component('component-a', {template: "<div>Component A</div>"})
Vue.component('component-b', {template: "<div>Component B</div>"})
Vue.component('component-c', {template: "<div>Component C</div>"})
new Vue({el: '#app1'})
var ComponentD = {template: "<div>Component D</div>"}
var ComponentE = {template: "<div>Component E</div>"}
var ComponentF = {template: "<div>Component F</div>"}
new Vue({
el: '#app2',
components: {
'component-d': ComponentD,
'component-e': ComponentE,
'component-f': ComponentF
}
})
</script>
</body>
</html>