Vue组件基本示例
组件是可复用的实例,且带有一个名字,下面的例子中,button-counter就是一个实例.我们可以在一个通过 new Vue 创建的 Vue 根实例中,把这个组件作为自定义元素来使用
因为组件是可复用的 Vue 实例,所以它们与 new Vue 接收相同的选项,例如 data、computed、watch、methods 以及生命周期钩子等。仅有的例外是像 el 这样根实例特有的选项。
<div id="components-demo">
<button-counter></button-counter>
</div>
Vue.component('button-counter',{
data:function () {
return{
count:0
}
},
template: '<button v-on:click="count++">You clicked me {**加粗文字**{count}}times</button>'
})
new Vue({
el:'#components-demo'
})
注意:要先注册组件(Vue.component),再创建vue的实例,否则会出现以下的报错:
vue.js:634 [Vue warn]: Unknown custom element: <button-counter> - did you register the component correctly? For recursive components, make sure to provide the "name" option.(found in <Root>)
一个组件的 data 选项必须是一个函数,因此每个实例可以维护一份被返回对象的独立的拷贝。用一次组件,就会有一个它的新实例被创建。
组件注册
Vue.component('my-component-name', {
// ... 选项 ...
})
组件名 (W3C:字母全小写且必须包含一个连字符)
组件名定义方式有两种:使用 kebab-case或 PascalCase
也就是说 <my-component-name> 和 <MyComponentName> 都是可接受的。
组件注册分为全局注册和局部注册
全局注册
全局注册的组件可以用在其被注册之后的任何 (通过 new Vue) 新创建的 Vue 根实例,也包括其组件树中的所有子组件的模板中。
<div id="global">
<component-a></component-a>
<component-b></component-b>
<component-c></component-c>
</div>
Vue.component('component-a',{
data:function () {
return{
clicked:0
}
},
template:'<button v-on:click="clicked++">You clicked me {{clicked}}times</button>'
})
Vue.component('component-b',{
data:function () {
return{
clicked:0
}
},
template:'<button v-on:click="clicked++">You clicked me {{clicked}}times</button>'
})
Vue.component('component-c',{
data:function () {
return{
clicked:0
}
},
template:'<div><span>You have clicked</span><input type="button" v-model="clicked" v-on:click="clicked++"><span>times.</span></div>'
})
new Vue({
el:'#global'
})
局部注册
局部注册的组件在其子组件中不可用
<div id="part">
<component-a></component-a>
<component-b></component-b>
<component-c></component-c>
</div>
var ComponentA = {
data:function () {
return {
clicked:0
}
},
template:'<button v-on:click="clicked++">You clicked me {{clicked}}times</button>'
}
var ComponentB = {
data:function () {
return {
clicked:0
}
},
template:'<button v-on:click="clicked++">You clicked me {{clicked}}times</button>'
}
var ComponentC = {
data:function () {
return {
clicked:0
}
},
template:'<button v-on:click="clicked++">You clicked me {{clicked}}times</button>'
}
new Vue({
el:'#part',
components:{
'component-a':ComponentA,
'component-b':ComponentB,
'component-c':ComponentC,
}
})
对于 components 对象中的每个属性来说,其属性名就是自定义元素的名字,其属性值就是这个组件的选项对象。
通过 Prop 向子组件传递数据
Prop 是你可以在组件上注册的一些自定义特性。Prop 是你可以在组件上注册的一些自定义特性。一个组件默认可以拥有任意数量的 prop,任何值都可以传递给任何 prop。一个 prop 被注册之后,你就可以像这样把数据作为一个自定义特性传递进来
<div id="prop-demo">
<blog-post title="prop just like data"></blog-post>
</div>
//给prop传递一个静态值
<div id="blog-post-demo">
<blog-post v-for="post in posts" v-bind:key="post.id" v-bind:title="post.title"></blog-post>
</div>
//给prop传递一个动态值
Vue.component('blog-post', {
props: ['likes','title'],
template: '<div><strong>{{likes}}</strong><span>{{title}}</span></div>'
})
new Vue({
el: '#prop-demo'
})
new Vue({
el: '#blog-post-demo',
data: {
posts: [
{likes:'1',title: 'My journey with Vue'},
{likes:'2',title: 'Blogging with Vue'},
{likes:'3',title: 'Why vue is so fun'}
]
}
})
<div id="blog-post-demo">
<blog-post v-for="post in posts" v-bind:post="post" v-bind:key="post.id" ></blog-post>
</div>
Vue.component('blog-post', {
props: ['post'],
template: '<div><span>{{post.title}}</span></div>'
})
//接受一个单独的 post prop
new Vue({
el: '#blog-post-demo',
data: {
posts: [
{id:'1',title: 'My journey with Vue'},
{id:'2',title: 'Blogging with Vue'},
{id:'3',title: 'Why vue is so fun'}
]
}
})
传入一个数字:用 v-bind 绑定
<blog-post v-bind:likes="42"></blog-post>
传入一个布尔值:用 v-bind 绑定
<blog-post v-bind:is-published="false"></blog-post>
传入一个数组:用 v-bind 绑定
<blog-post v-bind:comment-ids="[234, 266, 273]"></blog-post>
传入一个对象:用 v-bind 绑定
<blog-post
v-bind:author="{
name: 'Veronica',
company: 'Veridian Dynamics'
}"
></blog-post>
传入一个对象的所有属性:可以用一个不带参数的v-bind来绑定
<blog-post v-bind="post"></blog-post>
post: {
id: 1,
title: 'My Journey with Vue'
}
单项数据流
所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外改变父级组件的状态。
额外的,每次父级组件发生更新时,子组件中所有的 prop 都将会刷新为最新的值。这意味着你不应该在一个子组件内部改变 prop。
监听子组件事件
<!--监听子组件事件-->
<div id="blog-posts-events-demo">
<div :style="{ fontSize: postFontSize + 'em' }">
<blog-post
v-for="post in posts"
v-bind:key="post.id"
v-bind:post="post"
v-on:enlarge-text="postFontSize += 0.1"
></blog-post>
</div>
</div>
Vue.component('blog-post', {
props: ['post'],
template: `
<div class="blog-post">
<h3>{{ post.title }}</h3>
<button v-on:click="$emit('enlarge-text')">
Enlarge text
</button>
<div v-html="post.content"></div>
</div>
`
})
new Vue({
el: '#blog-posts-events-demo',
data: {
posts: [{title:'I want to be bigger'}],
postFontSize: 1
}
})
使用$emit抛出一个值,在组件上使用v-model
接受一个value属性。再有新的value时触发input事件
<!--在组件上使用v-model-->
<div id="model-demo">
{{value}}
<my-com v-model="value"></my-com>
<button @click="valueMinus">-1</button>
</div>
Vue.component('my-com', {
props:{
value:{
type:Number
}
},
template: '<div>{{currentValue}}<button @click="handleClick">+1</button></div>',
data: function () {
return {
currentValue: this.value
}
},
watch: {
value(val) {
this.currentValue = val;
}
},
methods: {
handleClick: function () {
this.currentValue++;
this.$emit('input', this.currentValue);
}
}
})
new Vue({
el: '#model-demo',
data: {
value: 1
},
methods:{
valueMinus:function () {
return this.value--
}
}
})
将原生的事件绑定到组件中,需要加上.native
.sync修饰符
通过插槽分发内容
Slot是父组件与子组件的通讯方式,可以将父组件的内容显示在子组件中。
demo实例
<div id="slot-demo">
<say-to pname="Kayee">
欢迎学习vue.js 的 组件之slot插槽。
</say-to>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
<script>
Vue.component('say-to',{
props:['pname'],
template:'<div>' +
'您好<strong>{{pname}}</strong>' +
'<slot></slot>' +
'</div>'
})
new Vue({
el:'#slot-demo',
})
</script>
Slot组合
<div id="slot-couple">
<welcome a="嘉仪">
<<span slot="Kayee">Kayee</span>
<<span slot="Crystal">Crystal</span>
<<span slot="Jiayi">Jiayi</span>
</welcome>
</div>
Vue.component('welcome',{
props: ['a'],
template: '<div>' +
'<p>您好{{a}}</p>'+
'<p>您好<slot name="Kayee"></slot> </p>'+
'<p>您好<slot name="Crystal"></slot> </p>'+
'<p>您好<slot name="Jiayi"></slot> </p>'+
'</div>'
})
new Vue({
el:'#slot-couple'
})
具名插槽
<div id="app">
<base-layout>
<template v-slot:header>
This is hedaer.
</template>
<template v-slot:main>
This is main.
</template>
<template v-slot:footer>
This is footer.
</template>
</base-layout>
</div>
Vue.component('base-layout',{
template:'<div class="container">\n' +
' <header>\n' +
' <slot name="header"></slot>\n' +
' </header>\n' +
' <main>\n' +
' <slot name="main"></slot>\n' +
' </main>\n' +
' <footer>\n' +
' <slot name="footer"></slot>\n' +
' </footer>\n' +
' </div>'
})
name用来定义额外的插槽,一个不带 name 的 <slot> 出口会带有隐含的名字“default”(即为默认的插槽)。<template> 元素中的所有内容都将会被传入相应的插槽。任何没有被包裹在带有 v-slot 的 <template> 中的内容都会被视为默认插槽的内容。
与已经废弃的slot特性不同,新版本使用v-slot: 来代替 slot=" "
注意 v-slot 只能添加在一个 <template> 上 (只有一种例外情况),这一点和已经废弃的 slot 特性不同。
后备内容
Vue.component('submit-button',{
template:'<button type="submit">\n' +
' <slot>Submit</slot>\n' +
' </button>'
})
<submit-button></submit-button> //按钮内文字为Submit
<submit-button>POST</submit-button> //按钮内文字为POST
作用域插槽
<div id="app2">
<comp v-slot="user">
{{user.username}}
</comp>
</div>
var CompA =Vue.component('comp', {
template:'<div>' +
'<slot :username="usernameA"></slot>' +
'</div>',
data(){
return {
usernameA:'Kayee'
}
}
})
子组件中的usernameA传到父组件中,绑定在 <slot> 元素上的特性被称为插槽 prop
插槽的缩写 v-slot:xxx 等价于#xxx
动态插槽名v-slot:[dynamicSlotName]
动态组件
<div id="app1">
<div id="title">
<button @click="changeTab('tab1')">Tab01</button>
<button @click="changeTab('tab2')">Tab02</button>
</div>
<keep-alive>
<component v-bind:is="currentTab"></component>
</keep-alive>
</div>
Vue.component('tab1',{
data:function () {
return{
count:0
}
},
template:'<div class="tab">' +
'{{count}}' +
'<button @click="addCounter">+1</button>' +
'</div>',
methods: {
addCounter(){
this.count++
}
}
})
Vue.component('tab2',{
data:function () {
return{
count:100
}
},
template:'<div class="tab">' +
'{{count}}' +
'<button @click="subCounter">-1</button>' +
'</div>',
methods: {
subCounter(){
this.count--
}
}
})
new Vue({
el:'#app1',
data:{
currentTab:'tab1'
},
methods:{
changeTab(tabName){
this.currentTab = tabName
}
}
})
1.关于is特性来切换tab组件
2.keep-alive 来使数据得到缓存记录
异步组件
Vue.component('async-example',function (resolve,reject) {
setTimeout(function () {
// 向 `resolve` 回调传递组件定义
resolve({
template:'<div>I am async!</div>'
})
},1000)
})
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。