您的位置:首页 > 产品设计 > UI/UE

vue.js component 学习手记

2016-10-09 00:00 253 查看

1 global register

2 local register

3 template parsing caveats

4 data 必须是函数

5 props down, events up

6 dynamic props

7 数值传递和字串传递

8 自定义事件

9 scope

10 dynamic component

1 global register

<div id="example">
<my-component></my-component>
</div>

Vue.component('my-component',{
template:'<div>A custom component!</div>'
});

new Vue({
el:'#example'
});

ps: 需要注意的是,component会重新绘制#example元素,所以,渲染后,#example就不存在了,第一层div就是component

2 local register

使用components option

<div id="local-component">
<h1>local component</h1>
<my-local-component></my-local-component>
</div>

let Child = {
template:'<div>A local component!</div>'
};

new Vue({
el:'#local-component',
components:{
'my-local-component':Child
}
});


3 template parsing caveats

invalid content

<table>
<my-row>...</my-row>
</table>

valid content 使用 is

<table>
<tr is="my-row"></tr>
</table>


4 data 必须是函数

let data = {
message:'hello'
};

let Child = {
template:'<div>{{message}}</div>',
data:function () {
return {message:'hello'};
}
};

new Vue({
el:'#local-component',
components:{
'my-local-component':Child
}
});


5 props down, events up

ps:父属性的变化会引起子component属性的变化,反正不然



<div id="props-example">
<child message="hello"></child>
</div>

let child = {
template:'<span>{{message}}</span>',
props:['message']
}
new Vue({
el:'#props-example',
components:{
'child':child
}
});

这里有两种情况需要子component 去改变prop

这个prop只是传递过来一个初始值,子component会使用它创建一个新的属性

prop是粗糙的原始值,需要经过处理子component才可以使用

上述两个case对应的方法:

子component定义一个local data property,使用父传递的prop作为初始值

子component定义一个computed property, 使用父传递的prop计算

当prop是Array 或 Object时,传递的就是reference, 所以子component对prop的操作,会影响到父的数据

6 dynamic props

不使用component

<div id="dynamic-props">
<input v-model="parentMsg" />
<span>{{parentMsg}}</span>
</div>

new Vue({
el:'#dynamic-props',
data:{
parentMsg:'pengqin'
}
});

使用component

<div id="dynamic-props">
<input v-model="parentMsg" />
<dynamic-child v-bind:message="parentMsg"></dynamic-child>
</div>

let dynamicChild = {
template:'<span>{{message}}</span>',
props:['message']
};

new Vue({
el:'#dynamic-props',
data:{
parentMsg:'hello'
},
components:{
'dynamic-child':dynamicChild
}
});


7 数值传递和字串传递

<!-- this passes down a plain string "1" -->
<comp some-prop="1"></comp>

使用v-bind,传递数值属性值为number

<!-- this passes down an actual number -->
<comp v-bind:some-prop="1"></comp>

7 prop validation 属性验证

属性值的类型可以限制,加以验证

下面的例子就要求component的message属性值必须是Number类型

<div id="validation">
<validation-component v-bind:message="propA"></validation-component>
</div>

let validationComponent = {
template:'<div class="validation-component">{{message}}</div>',
props:{
message:Number
}
};

new Vue({
el:'#validation',
data:{
propA:123
},
components:{
'validation-component':validationComponent
}
});

下面是多种validation的组合,有默认值设置default, 必须项required,还有自定义的validator function

Vue.component('example', {
props: {
// basic type check (`null` means accept any type)
propA: Number,
// multiple possible types
propB: [String, Number],
// a required string
propC: {
type: String,
required: true
},
// a number with default value
propD: {
type: Number,
default: 100
},
// object/array defaults should be returned from a
// factory function
propE: {
type: Object,
default: function () {
return { message: 'hello' }
}
},
// custom validator function
propF: {
validator: function (value) {
return value > 10
}
}
}
})

type可以为6类:Number, String, Boolean, Function, Array, Object

如果是自定义的构造函数,使用instanceof

8 自定义事件

8.1 同样使用v-on绑定自定义事件的handler

<div id="counter-event-example">
<p>{{total}}</p>
<button-counter v-on:increment="incrementTotal"></button-counter>
<button-counter v-on:increment="incrementTotal"></button-counter>
</div>

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

new Vue({
el:'#counter-event-example',
data:{
total:0
},
methods:{
incrementTotal:function () {
this.total += 1;
}
}
});

通过自定义事件,将父方法传递给子,子在事件方法里面可以调用父传递过来的方法,从而修改父的数值,是在子中修改父数据的一种方法

8.2 form input comoponents 使用 自定义事件

通过input的事件绑定,看一下v-model的原理

<input v-model="something">

其实,拆分成事件,就是如下的样子

<input v-bind:value="something" v-on:input="something = $event.target.value">

可以看出,使用了value props, 触发了input 事件

总结就是,要模仿v-model,需要满足下面两个条件

accept a
value
prop

emit an
input
event with the new value

<div id="v-model-example">
<p>{{ message }}</p>
<my-input label="Message" v-model="message"></my-input>
</div>

Vue.component('my-input',{
template:`<div class="form-group">
<label v-bind:for="randomId">{{ label }}:</label>
<input v-bind:id="randomId" v-bind:value="value" v-on:input="onInput" />
</div>`,
props:['label','value'],
data:function () {
return {
randomId:'input-' + Math.random()
};
},
methods:{
onInput:function (event) {
this.$emit('input',event.target.value);
}
}
});
new Vue({
el: '#v-model-example',
data: {
message: 'hello'
}
});


9 scope

金句:

Everything in the parent template is compiled in parent scope;

everything in the child template is compiled in child scope.

下面的例子中,message是父数据

work!

<child-component>
{{ message }}
</child-component>

下面的例子v-show应该绑定父数据

not work!

<child-component v-show="someChildProperty"></child-component>

绑定子数据,需要在子模板中

Vue.component('child-component', {
// this does work, because we are in the right scope
template: '<div v-show="someChildProperty">Child</div>',
data: function () {
return {
someChildProperty: true
}
}
})

9.1 slot 可以用来放fallback

my-component

<div>
<h1>I'm the parent title</h1>
<my-component>
<p>This is some original content</p>
<p>This is some more original content</p>
</my-component>
</div>

a parent that use my-component

<div>
<h2>I'm the child title</h2>
<slot>
This will only be displayed if there is no content
to be distributed.
</slot>
</div>

rendered

<div>
<h1>I'm the parent title</h1>
<div>
<h2>I'm the child title</h2>
<p>This is some original content</p>
<p>This is some more original content</p>
</div>
</div>

9.2 named slot可以组合app layout

app-layout template

<div class="container">
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>

parent use

<app-layout>
<h1 slot="header">Here might be a page title</h1>
<p>A paragraph for the main content.</p>
<p>And another one.</p>
<p slot="footer">Here's some contact info</p>
</app-layout>

rendered

<div class="container">
<header>
<h1>Here might be a page title</h1>
</header>
<main>
<p>A paragraph for the main content.</p>
<p>And another one.</p>
</main>
<footer>
<p>Here's some contact info</p>
</footer>
</div>


10 dynamic component

炫酷的动态组件切换,利用保留的<component>和绑定is属性(v-bind:is='someComponentName')

keep-alive 可以记录组件的状态,避免重新渲染

<div id="dynamic-component">
<keep-alive>
<component v-bind:is="currentView"></component>
</keep-alive>
</div>

let Home = {
template:'<p>home</p>'
};

let Posts = {
template:'<p>posts</p>'
};

new Vue({

el:'#dynamic-component',
data:{
currentView:'posts'
},

components:{
home:Home,
posts:Posts
}
});


11 child component refs

<div id="parent">
<user-profile ref="profile"></user-profile>
</div>

var parent = new Vue({ el: '#parent' })
// access child component instance
var child = parent.$refs.profile

ps: $ref 只有当component render后才会计算,并且不会react,所以避免在template 和 computed中使用
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  vue.js