内容简介:1.注册组件就是利用Vue.component()方法2.可以理解为一个vue文件就是一个组件组件的模板中只能有一个根元素
组件的基本使用
注册组件
1.注册组件就是利用Vue.component()方法
2.可以理解为一个vue文件就是一个组件
模板要求
组件的模板中只能有一个根元素
组件中的data必须是函数
var app = new Vue({
data () {
return {
message: 'hello world'
}
}
})
组件的属性和事件
例,一个父组件:
<my-component v-bind:foo="baz" v-on:event-a="doThis(arg1,...arg2)"></my-component>
上面代码
-
foo是<my-component>组件内部定义的一个prop属性,baz是父组件的一个data属性, -
event-a是子组件定义的一个事件,doThis是父组件的一个方法
执行过程应该是这样的:
-
父组件把
baz数据通过prop传递给子组件的foo; -
子组件内部得到
foo的值,就可以进行相应的操作; -
当子组件内部发生了一些变化,希望父组件能知道时,就利用代码触发
event-a事件,把一些数据发送出去 -
父组件把这个事件处理器绑定为
doThis方法,子组件发送的数据,就作为doThis方法的参数被传进来 - 然后父组件就可以根据这些数据,进行相应的操作
属性Props
Vue组件通过 props
属性来声明一个自己的属性,然后父组件就可以往里面传递数据。
Vue.component('mycomponent',{
template: '<div>这是一个自定义组件,父组件传给我的内容是:{{myMessage}}</div>',
props: ['myMessage'],
data () {
return {
message: 'hello world'
}
}
})
然后调用该组件
<div id="app">
<mycomponent my-message="hello"></mycomponent>
</div>
注意,由于HTML特性是不区分大小写的,所以传递属性值时, myMessage
应该转换成 kebab-case (短横线隔开式) my-message="hello"
。
v-bind绑定属性值
<div attr="message">hello</div>
上面这样, div
元素的 attr
特性值就是 message
。而这样
<div v-bind:attr="message">hello</div>
这里的 message
应该是Vue实例的data的一个属性,这样 div
元素的 attr
特性值就是 message
这个属性的值。
之所以说是一般情况,是因为 class
和 style
特性并不是这样。用 v-bind:class
和 class
传入正常的类名,效果是一样的,因为对于这两个特性,Vue采用了合并而不是替换的原则。
子组件希望对传入的prop进行操作
根据上面,想要把父组件的属性绑定到子组件,应该使用 v-bind
,这样,父组件中数据改变时能反映到子组件。
注意在子组件中最好不要更改父组件传入的值,如果非要更改的话,加上 .sync
修饰符
例父组件
<my-component :child-array.sync="parentArray"></my-component>
子组件
methods: {
changeArray () {
this.counter++
this.$emit('update:childArray', this.counter)
}
}
给子组件传递正确类型的值
同样是上面的原因,静态的给子组件的特性传递值,它都会把他当做一个字符串。
<!-- 传递了一个字符串 "1" --> <comp some-prop="1"></comp>
子组件中,特性的值是字符串 "1" 而不是 number 1。如果想传递正确的数值,应该使用v-bind传递,这样就能把传递的值当做一个表达式来处理,而不是字符串。
<!-- 传递实际的 number 1 --> <comp v-bind:some-prop="1"></comp>
Prop验证
我们可以给组件的 props
属性添加验证,当传入的数据不符合要求时,Vue会发出警告。
Vue.component('example', {
props: {
// 基础类型检测 (`null` 意思是任何类型都可以)
propA: Number,
// 多种类型
propB: [String, Number],
// 必传且是字符串
propC: {
type: String,
required: true
},
// 数字,有默认值
propD: {
type: Number,
default: 100
},
// 数组/对象的默认值应当由一个工厂函数返回
propE: {
type: Object,
default: function () {
return { message: 'hello' }
}
},
// 自定义验证函数
propF: {
validator: function (value) {
return value > 10
}
}
}
})
type
可以是下面原生构造器:
- String
- Number
- Boolean
- Function
- Object
- Array
- Symbol
type
也可以是一个自定义构造器函数
自定义事件
通过prop属性,父组件可以向子组件传递数据,而自定义事件就是用来将子组件的内部数据报告给父组件的。
例
<div id="app3">
<my-component2 v-on:myclick="onClick"></my-component2>
</div>
<script>
Vue.component('my-component2', {
template: `<div>
<button type="button" @click="childClick">点击我触发自定义事件</button>
</div>`,
methods: {
childClick () {
this.$emit('myclick', '这是我暴露出去的数据', '这是我暴露出去的数据2')
}
}
})
new Vue({
el: '#app3',
methods: {
onClick () {
console.log(arguments)
}
}
})
</script>
如上所示,共分为以下步骤:
-
子组件在自己的方法中将自定义事件以及需要发出的数据通过以下代码发送出去
this.$emit('myclick', '这是我暴露出去的数据', '这是我暴露出去的数据2')第一个参数是自定义事件的名字 后面的参数是依次想要发送出去的数据
-
父组件利用
v-on为事件绑定处理器<my-component2 v-on:myclick="onClick"></my-component2>
这样,在Vue实例的
methods方法中就可以调用传进来的参数了
注意: 在使用 v-on
绑定事件处理方法时,不应该传进任何参数,而是直接写 v-on:myclick="onClick"
,不然,子组件暴露出来的数据就无法获取到了
绑定原生事件
如果想在某个组件的根元素上监听一个原生事件。可以使用 .native
修饰 v-on
探究 v-model
v-model
可以对表单控件实现数据的双向绑定,它的原理就是利用了绑定属性和事件来实现的。比如 input
控件。不使用 v-model
,可以这样实现数据的双向绑定:
<div id="app4">
<input type="text" v-bind:value="text" v-on:input="changeValue($event.target.value)">
{{text}}
</div>
<script>
new Vue({
el: '#app4',
data: {
text: '444'
},
methods: {
changeValue (value) {
this.text = value
}
}
})
</script>
上面的代码同样实现了数据的双向绑定。其本质就是:
-
把
input的value特性绑定到Vue实例的属性text上,text改变,input中的内容也会改变 -
然后把表单的
input事件处理函数设置为Vue实例的一个方法,这个方法会根据输入参数改变Vue中text的值 -
相应的,在
input中输入内容时,触发了input事件,把event.target.value传给这个方法,最后就实现了改变绑定的数据的效果。
而 v-model
就是上面这种方式的语法糖,也就是把上面的写法封装了一下,方便我们使用。
使用slot分发内容
单个slot
上面用到的很多组件的使用方式是这样的:
<component></component>
也就是说组件中是空的,没有放置任何文本或元素。但是原生的html元素都是可以进行嵌套的, div
里面放 table
什么的。自定义组件开闭标签之间也可以放置内容,不过需要在定义组件时使用 slot
。
slot
相当于子组件设置了一个地方,如果在调用它的时候,往它的开闭标签之间放了东西,那么它就把这些东西放到 slot
中。
- 当子组件中没有slot时,父组件放在子组件标签内的东西将被丢弃;
- 子组件的slot标签内可以放置内容,当父组件没有放置内容在子组件标签内时,slot中的内容会渲染出来;
- 当父组件在子组件标签内放置了内容时,slot中的内容被丢弃
子组件的模板:
<div>
<h2>我是子组件的标题</h2>
<slot>
只有在没有要分发的内容时才会显示。
</slot>
</div>
父组件模板:
<div>
<h1>我是父组件的标题</h1>
<my-component>
<p>这是一些初始内容</p>
</my-component>
</div>
渲染结果:
<div>
<h1>我是父组件的标题</h1>
<div>
<h2>我是子组件的标题</h2>
<p>这是一些初始内容</p>
</div>
</div>
具名slot
slot
可以有很多个。那么子组件对于父组件放置的多余的内容如何放到各个 slot
中呢?方法就是子组件给每个 slot
起一个名字 name
,父组件放置多余的元素时,给每个元素的 slot
属性分配一个代表 slot
的名字。到时候,多余的内容就会根据自己的 slot
属性去找具有对应名字的 slot
元素。
注意:
- 子组件可以有一个匿名的slot,当分发的多余内容找不到对应的slot时,就会进入这里面
- 如果子组件没有匿名的slot,当分发的多余内容找不到对应的slot时,就会被丢弃
例如,假定我们有一个 app-layout 组件,它的模板为:
<div class="container">
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
父组件模版:
<app-layout> <h1 slot="header">这里可能是一个页面标题</h1> <p>主要内容的一个段落。</p> <p>另一个主要段落。</p> <p slot="footer">这里有一些联系信息</p> </app-layout>
渲染结果为:
<div class="container">
<header>
<h1>这里可能是一个页面标题</h1>
</header>
<main>
<p>主要内容的一个段落。</p>
<p>另一个主要段落。</p>
</main>
<footer>
<p>这里有一些联系信息</p>
</footer>
</div>
作用域插槽
作用域插槽也是一个插槽 slot
,但是他可以把数据传递给到父组件的特定元素内,然后有父组件决定如何渲染这些数据。
-
首先,子组件的
slot需要有一些特性(prop)Vue.component('my-component4', { template: `<div> <slot :text="hello" message="world"></slot> </div>`, data () { return { hello: [1,'2'] } } }) -
父组件在调用子组件时,需要在里面添加一个
template元素,并且这个template元素具有scope特性<div id="app7"> <my-component4> <template scope="props"> </template> </my-component4> </div>scope特性的值,就代表了所有子组件传过来的数据组成的对象。相当于props = { text: '', message: '' } -
最后,父组件就可以在
template中渲染子组件传过来的数据了<div id="app7"> <my-component4> <template slot-scope="props"> <span>{{props.text}}</span> <span>{{props.message}}</span> </template> </my-component4> </div>作用域插槽也是插槽,只不过是多加了些特性,然后父组件多进行了些处理。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Web Design Handbook
Baeck, Philippe de 编 / 2009-12 / $ 22.54
This non-technical book brings together contemporary web design's latest and most original creative examples in the areas of services, media, blogs, contacts, links and jobs. It also traces the latest......一起来看看 《Web Design Handbook》 这本书的介绍吧!