vue笔记----组件

组件是vue.js最强大的功能之一。组件可以扩展HTML元素,封装可重用的代码。
在较高层面上,组件是自定义元素,vue.js的编译器为它添加特殊功能。在有些情况下,
组件页可以是原生HTML元素的形式,以is特性扩展。




组件使用


#注册
之前说过,我们可以通过一下方式创建一个Vue实例
new Vue({
el:'#some-element',
//选项
})
要注册一个全局组件,你可以使用Vue.component(tagName,option)。例如:
Vue.component('my-conponent',{
//选项
})
对于自定义标签名,Vue.js不强制要求遵循w3c规则(小写,并且包含一个短杠),
尽管遵循这个规则比较好。


组件在注册之后,便可以在父实例的模块总以自定义元素<my-component>
</my-component>的形式使用。要确保在初始化根实例之前注册了组件:
<div id="example">
  <my-component></my-component>
</div>
注册
Vue.component('my-component',{
  template:'<div>A custom component! </div>'
})
创建根实例
new Vue({
  el:'#example'
})


渲染为:
<div id="example">
  <div>A custom component!</div>
</div>


#局部注册
不必在全局注册每个组件。通过使用组件实例选项注册,可以是组件仅在另一个实例/组件
的作用域中可用:
var Child = {
template:'<div>A custom component!</div>'
}
new Vue({
//...
components:{
'my-component':Child
}
})
这种封装也适用于其他可注册的Vue功能,如指令。
当使用DOM作为模板时(例如,将el选项挂载到一个已存在的元素上),你会收到HTML
的一些限制因为Vue只有在浏览器解析和标准化HTML后才能获取模板内容。尤其像
这些元素<ul>,<ol>,<table>,<select>限制了被它包裹的元素,<option>只能
出现在其他元素内部。
在自定义组件中使用这些受限制的元素时会导致一些问题,例如:
<table>
  <my-row>...<my-row>
</table>
自定义组件<my-row>被认为是无效的内容,因此在渲染的时候会导致错误。变通的方案
是使用特殊的is属性:
<table>
  <tr is="my-row"></tr>
</table>
注意:如果您使用来自一下来源之一的字符串模板,这些限制将不适用:
1.<script type="text/x-template">
2.JAvaScript内联模板字符串
3..vue组件
因此,有必要的话使用字符串模板


#data必须是函数
使用组件时,大多数恶意传入到Vue构造器中国的选项可以在注册组件时使用,
有一个例外:data必须是函数。如果这样:
Vue.component('my-component',{
  template:'<span>{{message}}</span>',
  data:{
  message:'hello'
  }
})
那么 Vue会在控制台发出警告,告诉你在组件中data比武时一个函数。更好理解这种规则的存在含义。
<div id="example-2">
  <simple-counter></simple-counter>
  <simple-counter></simple-counter>
  <simple-counter></simple-counter>
</div>


var data = {counter:0}
Vue.component('simple-counter',{
template:'<button v-on:click="counter+=1">{{}}</button>',
data:function(){
return data
}
})
new Vue({
el:'#example-2'
})


由于这三个组件共享了同一个data,因此增加一个couter会影响所有的组件!
我们可以通过为每个组件返回新的data对象来解决这个问题:
data:function(){
return {
counter:0
}
}


构成组件
组件意味着协同工作,通常父子组件也是这样的关系:组件A在它的模版中使用了组件B.
他们之间必然余姚相互通信:父组件要给子组件专递数据,子组件余姚将它内部发生
的事情告诉父组件。然而,在一个良好定义的接口中尽可能将父子组件解耦是很重要的。
这保证了每个组件可以在相对隔离的环境中书写和理解,也大幅提高了组件的可维护
性和可重用性。


在vue.js中,父子组件的关系可以总结为props down,events up。父组件通过props
乡下传递数据给子组件,子组件通过events给父组件发送消息。


prop
#使用Prop传递数据
组件实例的作用域是孤立的。这意味这不能并且不应该在自组建的模版内直接引用
父组件的数据。可以使用props把数据传给子组件。
prop是父组件用来传递数据的一个自定义属性。自组件需要显示地用prop选项声名
”prop“:
Vue.component('child'{
//声名props
  prop:['message'],
  //就像data一样,prop可以用在模版内
  //同样也可以在vm事例中像this.message这样使用
  template:'<span>{{message}}</span>'
})


#camelCase vs.kebab-case
HTML特性不区分大小写。但使用非字符串模版时,prop的名字形式慧聪camelCase
转为kebab-case(短横线隔开):
Vue.component('child',{
prop:['myMassage'],
template:'<span>{{myMyssage}}</span>'
})
<child my-message="hello"></child>
如果使用字符串模版,不用在意这些限制。


#动态Prop
在模版中,要动态的绑定父组件的数据到自模版的props,与绑定到任何普通的HTML特性
相类似,就是用v-bind。每当父组件的数据变化时,该变化也会传导给子组件
<div>
  <input v-model="parentMsg">
  <br/>
  <child v-bind:my-message="parentMsg"></child>
</div>
使用v-bind的缩写语法通常更简单
<child :my-message="parentMsg"></child>




#字面量语法
初学者常犯的一个错误是使用字面量语法传递数值
//----------传递了一个字符串1
<comp some-prop="1"></comp>
因为它是一个字面prop,它的值是字符串“1”而不是number。如果像传递一个实际的
number。如果想传递一个实际的number,需要使用v-bind,com会儿让他的值被当做
JavaScript表达式计算:
//--------传递实际的number
<comp v-bind:some-prop="1"></comp>




#单向数据流
prop是单向绑定的:当夫元素的属性变化时,将传导给自组建,但是不会反过来。这是
为了防止组件无意改了自组建的状态--这会让应用的数据流难以理解。
另外,每次父组件更新时,自组建的所有prop都会更新为最新值。这意味着你不应该
在自组件内部改变prop。如果你这么做了,vue会在控制台给出警告。
为什么我们会有修改prop中数据的冲动呢?通常就是两种原因:
1.prop作为初始值插入后,自组建想把它当作局部数据来用
2.prop作为数十只传入,由子组件处理成其他苏剧输出。
对这两种原因,正确的应对方式是:
1.定义一个局部变量,并用prop的值初始化它:
prop:['initailCounter'],
data:function(){
return{couter:this.initailCouter}
}
2.定义一个计算属性,处理prop的值病返回。
prop:['size'],
computed:{
normalizedSize:function(){
return this.size.trim().toLowerCase()
}
}
注意在JavaScript中对象和数组是饮用类型,指向同一个内存空间,如果prop是一个对象或数组,
在子组件内部改变它会影响父组件的状态。


#prop验证
我们可以为组件的prop指定验证规格。如果传入的数据不符合规格,Vue会发出警告
。当组件给其他人使用时,这很有用。要制定验证规格,余姚用对象的影视,而不是
用字符串数组:
Vue.component('example',{
props:{
//----基础类型检测(null意思时什么类型都可以)
propA:number,
//----多种类型
propB:[String,Number],
//--必传且是字符串
propC:{
type:Number,
required:true
}
//---数组/对象的默认应当由一个工厂函数返回
propE:{
type:Object,
default:function(){
retutn{message:'hello'}
}
},
//--自定义验证函数
propF:{
validator:function(value){
reutrn value > 0
}
}
}
})




type可以是下面原生构造器:
String
Number
Boolean
Function
Object
Array


自定义事件
我们知道,父组件时使用props传递数据给子组件没如果组件要把数据传递过去,应该
自定义事件!


#使用v-on绑定自定义事件
每个Vue实例都实现了时间借口,即:
使用$on(eventName)监听事件
使用$emit(eventNAme)触发事件


另外,父组件可以使用子组件的地方直接用v-on来坚挺子组件触发事件。


注意:不能用$on侦听子组件抛出的事件,而必须在模版里直接用v-on绑定,就像以
下例子:
<div id="couter-event-example">
<p>{{total}}</p>
<button-couter v-on:increment="incrementTotal"></button-couter>
<button-couter v-on:increment="incrementTotal"></button-couter>
</div>


Vue.component('button-couter',{
template:'<button v-on:click="increment">{{}}</button>',
data:function(){
return{
couter:0
}
},
methods:{
increment:function(){
this.couter+=1;
this.$emit('increment')
}
},
})


new Vue({
el:'#couter-event-examole',
data:{
total:0
},
methods:{
increatTotal:function(){
this.total+=1
}
}
})
本例子中,子组件已经和它外部完全解耦了。它所做的只是报告自己的内部事件,至
于父组件是否关心则与他无关。留意到这一点很重要。






给组件绑定原生事件
有时候,你可能想在某个组件的根元素上监听一个原生事件。可以使用.native修饰v-on
例如:
<my-component v-on:click.native="doTheThing"></my-component>

















评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值