JavaScript的MVVM库Vue.js入门学习笔记
一、v-bind缩写
<!--完整语法--> <av-bind:href="url"></a> <!--缩写--> <a:href="url"></a> <!--完整语法--> <buttonv-bind:disabled="someDynamicCondition">Button</button> <!--缩写--> <button:disabled="someDynamicCondition">Button</button>
二、v-on缩写
<!--完整语法--> <av-on:click="doSomething"></a> <!--缩写--> <a@click="doSomething"></a>
三、过滤器
{{message|capitalize}}
四、条件渲染
v-if <h1v-if="ok">Yes</h1> <h1v-else>No</h1> <divv-if="Math.random()>0.5"> Sorry </div> <divv-else> Notsorry </div> template-v-if <templatev-if="ok"> <h1>Title</h1> <p>Paragraph1</p> <p>Paragraph2</p> </template> v-show <h1v-show="ok">Hello!</h1>
五、列表渲染for
v-for
<ulid="example-1">
<liv-for="iteminitems">
{{item.message}}
</li>
</ul>
varexample1=newVue({
el:'#example-1',
data:{
items:[
{message:'Foo'},
{message:'Bar'}
]
}
});
<ulid="example-2">
<liv-for="iteminitems">
{{parentMessage}}-{{$index}}-{{item.message}}
</li>
</ul>
varexample2=newVue({
el:'#example-2',
data:{
parentMessage:'Parent',
items:[
{message:'Foo'},
{message:'Bar'}
]
}
});
数组变动检测
Vue.js包装了被观察数组的变异方法,故它们能触发视图更新。被包装的方法有:push(),pop(),shift(),unshift(),splice(),sort(),reverse()
example1.items.push({message:'Baz'});
example1.items=example1.items.filter(function(item){
returnitem.message.match(/Foo/);
});
template-v-for
<ul>
<templatev-for="iteminitems">
<li>{{item.msg}}</li>
<liclass="divider"></li>
</template>
</ul>
对象v-for
<ulid="repeat-object"class="demo">
<liv-for="valueinobject">
{{$key}}:{{value}}
</li>
</ul>
newVue({
el:'#repeat-object',
data:{
object:{
FirstName:'John',
LastName:'Doe',
Age:30
}
}
});
值域v-for
<div>
<spanv-for="nin10">{{n}}</span>
</div>
六、方法与事件处理器
方法处理器
<divid="example">
<buttonv-on:click="greet">Greet</button>
</div>
varvm=newVue({
el:'#example',
data:{
name:'Vue.js'
},
//在`methods`对象中定义方法
methods:{
greet:function(event){
//方法内`this`指向vm
alert('Hello'+this.name+'!')
//`event`是原生DOM事件
alert(event.target.tagName)
}
}
})
//也可以在JavaScript代码中调用方法
vm.greet();//->'HelloVue.js!'
内联语句处理器
<divid="example-2">
<buttonv-on:click="say('hi')">SayHi</button>
<buttonv-on:click="say('what')">SayWhat</button>
</div>
newVue({
el:'#example-2',
methods:{
say:function(msg){
alert(msg)
}
}
});
有时也需要在内联语句处理器中访问原生DOM事件。可以用特殊变量$event把它传入方法
<buttonv-on:click="say('hello!',$event)">Submit</button>
methods:{
say:function(msg,event){
//现在我们可以访问原生事件对象
event.preventDefault()
}
};
##事件修饰符
<!--阻止单击事件冒泡--> <av-on:click.stop="doThis"></a> <!--提交事件不再重载页面--> <formv-on:submit.prevent="onSubmit"></form> <!--修饰符可以串联--> <av-on:click.stop.prevent="doThat"> <!--只有修饰符--> <formv-on:submit.prevent></form>
##按键修饰符
<!--只有在keyCode是13时调用vm.submit()--> <inputv-on:keyup.13="submit"> <!--同上--> <inputv-on:keyup.enter="submit"> <!--缩写语法--> <input@keyup.enter="submit">
全部的按键别名:enter,tab,delete,esc,space,up,down,left,right
##其他实例
newVue({
el:'#demo',
data:{
newLabel:'',
stats:stats
},
methods:{
add:function(e){
e.preventDefault()
if(!this.newLabel){
return;
}
this.stats.push({
label:this.newLabel,
value:100
});
this.newLabel='';
},
remove:function(stat){
if(this.stats.length>3){
this.stats.$remove(stat);//注意这里的$remove
}else{
alert('Can\'tdeletemore!')
}
}
}
});
七、过渡
CSS过渡
<divv-if="show"transition="expand">hello</div>
然后为.expand-transition,.expand-enter和.expand-leave添加CSS规则:
/*必需*/
.expand-transition{
transition:all.3sease;
height:30px;
padding:10px;
background-color:#eee;
overflow:hidden;
}
/*.expand-enter定义进入的开始状态*/
/*.expand-leave定义离开的结束状态*/
.expand-enter,.expand-leave{
height:0;
padding:010px;
opacity:0;
}
你可以在同一元素上通过动态绑定实现不同的过渡:
<divv-if="show":transition="transitionName">hello</div>
newVue({
el:'...',
data:{
show:false,
transitionName:'fade'
}
}
另外,可以提供JavaScript钩子:
Vue.transition('expand',{
beforeEnter:function(el){
el.textContent='beforeEnter'
},
enter:function(el){
el.textContent='enter'
},
afterEnter:function(el){
el.textContent='afterEnter'
},
enterCancelled:function(el){
//handlecancellation
},
beforeLeave:function(el){
el.textContent='beforeLeave'
},
leave:function(el){
el.textContent='leave'
},
afterLeave:function(el){
el.textContent='afterLeave'
},
leaveCancelled:function(el){
//handlecancellation
}
});
八、组件
1.注册
//定义
varMyComponent=Vue.extend({
template:'<div>Acustomcomponent!</div>'
});
//注册
Vue.component('my-component',MyComponent);
//创建根实例
newVue({
el:'#example'
});
<divid="example">
<my-component></my-component>
</div>
或者直接写成:
Vue.component('my-component',{
template:'<div>Acustomcomponent!</div>'
});
//创建根实例
newVue({
el:'#example'
});
<divid="example">
<my-component></my-component>
</div>
2.使用prop传递数据
实例一:
Vue.component('child',{
//声明props
props:['msg'],
//prop可以用在模板内
//可以用`this.msg`设置
template:'<span>{{msg}}</span>'
});
<childmsg="hello!"></child>
实例二:
Vue.component('child',{
//camelCaseinJavaScript
props:['myMessage'],
template:'<span>{{myMessage}}</span>'
});
<!--kebab-caseinHTML-->
<childmy-message="hello!"></child>
3.动态props
<div> <inputv-model="parentMsg"> <br> <childv-bind:my-message="parentMsg"></child> </div>
使用v-bind的缩写语法通常更简单:
<child:my-message="parentMsg"></child>
4.Prop绑定类型
prop默认是单向绑定:当父组件的属性变化时,将传导给子组件,但是反过来不会。这是为了防止子组件无意修改了父组件的状态——这会让应用的数据流难以理解。不过,也可以使用.sync或.once绑定修饰符显式地强制双向或单次绑定:
比较语法:
<!--默认为单向绑定--> <child:msg="parentMsg"></child> <!--双向绑定--> <child:msg.sync="parentMsg"></child> <!--单次绑定--> <child:msg.once="parentMsg"></child> 其他实例: <modal:show.sync="showModal"> <h3slot="header">customheader</h3> </modal> </div>
5.Prop验证
组件可以为props指定验证要求。当组件给其他人使用时这很有用,因为这些验证要求构成了组件的API,确保其他人正确地使用组件。此时props的值是一个对象,包含验证要求:
Vue.component('example',{
props:{
//基础类型检测(`null`意思是任何类型都可以)
propA:Number,
//必需且是字符串
propB:{
type:String,
required:true
},
//数字,有默认值
propC:{
type:Number,
default:100
},
//对象/数组的默认值应当由一个函数返回
propD:{
type:Object,
default:function(){
return{msg:'hello'}
}
},
//指定这个prop为双向绑定
//如果绑定类型不对将抛出一条警告
propE:{
twoWay:true
},
//自定义验证函数
propF:{
validator:function(value){
returnvalue>10
}
},
//转换函数(1.0.12新增)
//在设置值之前转换值
propG:{
coerce:function(val){
returnval+''//将值转换为字符串
}
},
propH:{
coerce:function(val){
returnJSON.parse(val)//将JSON字符串转换为对象
}
}
}
});
其他实例:
Vue.component('modal',{
template:'#modal-template',
props:{
show:{
type:Boolean,
required:true,
twoWay:true
}
}
});
6.注册
//定义
varMyComponent=Vue.extend({
template:'<div>Acustomcomponent!</div>'
});
//注册
Vue.component('my-component',MyComponent);
//创建根实例
newVue({
el:'#example'
});
<divid="example">
<my-component></my-component>
</div>
或者直接写成:
Vue.component('my-component',{
template:'<div>Acustomcomponent!</div>'
});
//创建根实例
newVue({
el:'#example'
});
<divid="example">
<my-component></my-component>
</div>
7.使用prop传递数据
实例一:
Vue.component('child',{
//声明props
props:['msg'],
//prop可以用在模板内
//可以用`this.msg`设置
template:'<span>{{msg}}</span>'
});
<childmsg="hello!"></child>
实例二:
Vue.component('child',{
//camelCaseinJavaScript
props:['myMessage'],
template:'<span>{{myMessage}}</span>'
});
<!--kebab-caseinHTML-->
<childmy-message="hello!"></child>
8.动态props
<div> <inputv-model="parentMsg"> <br> <childv-bind:my-message="parentMsg"></child> </div>
使用v-bind的缩写语法通常更简单:
<child:my-message="parentMsg"></child>
9.Prop绑定类型
prop默认是单向绑定:当父组件的属性变化时,将传导给子组件,但是反过来不会。这是为了防止子组件无意修改了父组件的状态——这会让应用的数据流难以理解。不过,也可以使用.sync或.once绑定修饰符显式地强制双向或单次绑定:
比较语法:
<!--默认为单向绑定--> <child:msg="parentMsg"></child> <!--双向绑定--> <child:msg.sync="parentMsg"></child> <!--单次绑定--> <child:msg.once="parentMsg"></child>
其他实例:
<modal:show.sync="showModal"> <h3slot="header">customheader</h3> </modal> </div>
10.Prop验证
组件可以为props指定验证要求。当组件给其他人使用时这很有用,因为这些验证要求构成了组件的API,确保其他人正确地使用组件。此时props的值是一个对象,包含验证要求:
Vue.component('example',{
props:{
//基础类型检测(`null`意思是任何类型都可以)
propA:Number,
//必需且是字符串
propB:{
type:String,
required:true
},
//数字,有默认值
propC:{
type:Number,
default:100
},
//对象/数组的默认值应当由一个函数返回
propD:{
type:Object,
default:function(){
return{msg:'hello'}
}
},
//指定这个prop为双向绑定
//如果绑定类型不对将抛出一条警告
propE:{
twoWay:true
},
//自定义验证函数
propF:{
validator:function(value){
returnvalue>10
}
},
//转换函数(1.0.12新增)
//在设置值之前转换值
propG:{
coerce:function(val){
returnval+''//将值转换为字符串
}
},
propH:{
coerce:function(val){
returnJSON.parse(val)//将JSON字符串转换为对象
}
}
}
});
其他实例:
Vue.component('modal',{
template:'#modal-template',
props:{
show:{
type:Boolean,
required:true,
twoWay:true
}
}
});
11.使用slot分发内容
<slot>元素作为组件模板之中的内容分发插槽。这个元素自身将被替换。
有name特性的slot称为命名slot。有slot特性的内容将分发到名字相匹配的命名slot。
例如,假定我们有一个multi-insertion组件,它的模板为:
<div> <slotname="one"></slot> <slot></slot> <slotname="two"></slot> </div>
父组件模板:
<multi-insertion> <pslot="one">One</p> <pslot="two">Two</p> <p>DefaultA</p> </multi-insertion>
渲染结果为:
<div> <pslot="one">One</p> <p>DefaultA</p> <pslot="two">Two</p> </div>