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
valueprop
emit an
inputevent 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 学习手记
- Reactjs学习 -- factory、component和element
- vue.js学习
- Vue.js学习 Item9 – 表单控件绑定
- Vue.js学习 Item13 – 指令系统与自定义指令
- Vue.js学习 Item13 – 指令系统与自定义指令
- JQuery Mobile 开发学习手记(一):JS批量设置按钮动作的问题
- Vue.js学习
- 学习vue-cli时需要引入外部js库文件(如jquery)的问题,百度后解决了,再次备忘一下
- Vue.js学习 Item8 -- 方法与事件处理器
- Vue.js学习 Item15 – 构建大型web应用
- vue.js学习
- Vue.js学习 Item1 --快速入门
- 五个小案例带你学习火热的Vue.js
- Vue.js学习思维导图一览
- Vue.js学习与理解
- Vue.js学习 Item12 – 内部响应式原理探究
- Vue.js学习 Item3 -- 构造器与生命周期
- Vue.js学习 Item11 – 组件与组件间的通信
- Vue.js学习 Item16 – 各种Web流行MV*框架对比