概述
2016年已經結束了。你是否會思考一下,自己在過去的一年里是否錯過一些重要的東西?不用擔心,我們正在回顧那些流行的趨勢。
通過比較過去12個月里Github所增加的star數,我們利用bestof.js.org分析所涉及的項目技術,發現2016最流行項目有以下這些:
圖片
通過比較去年最火的10個項目,你可以總覽2016的web前端技術發展,會發現:
Vue.js在去年獲得了超過25000個star,這意味着每天有72個star,超過了包含React以及Angular在內的其它任何框架。
但是,相信大多數開始接觸Vue.js的學習者和筆者一樣,面對Vue.js如此多的API方法頭暈目,所以筆者為大家整理了一下Vue.js的屬性與方法,
方便大家回顧(目前是第一部分的內容,下篇會將后継的補充完善)!
一、起步
1、v-model(綁定數據)
2、v-for(循環)
3、v-on(綁定事件)
4、data(數據)
5、methods(方法)
6、$index(索引)
二、概述
1、data(綁定 DOM 文本到數據)
2、v-if(不滿足條件的話則不會出現在dom中)
3、v-show(不滿足條件,則樣式會設置成隱藏 display:none;)
4、組件
eg:
<div id="app3">
<app-nav></app-nav> <!--導航-->
<app-view>
<app-sidebar></app-sidebar> <!--側邊欄-->
<app-content></app-content> <!--展示內容-->
</app-view>
</div>
<script type="text/javascript">
var vm2=new Vue({
el:"#app2",
data:data2
});
</script>
三、Vue實例
1、構造器:Vue.extend
2、數據屬性:vm.a
3、實例屬性和方法:
1)vm.$el
2)vm.$data
3)vm.$watch
4)實例生命周期
eg:
var vm4 = new Vue({
data: {
a: 1
},
beforeCreate:function(){
//創建前
},
created: function(){
console.log('a is: ' + this.a); // `this` 指向 vm 實例
},
beforeMount:function(){
//加載前
},
mounted:function(){
//加載后
},
beforeUpdate:function(){
//更新前
},
updated:function(){
//更新后
},
beforeDestroy:function(){
//銷毀前
},
destroyed:function() {
//銷毀后
}
});
四、數據綁定語法
1、文本插值:
{{msg}}
2、單次綁定:
v-once {{msg}}
3、純HTML:
v-html
4、綁定表達式:
{{number+1}}
5、過濾器:
{{ message | filterA | filterB }}、{{ message | filterA 'arg1' arg2 }}
6、指令:
<p v-if="greeting">Hello!</p>
帶參數的指令:
<a v-bind:href="url"></a>
<a v-on:click="doSomething"></a>
帶修飾符的指令:
<a v-bind:href.literal="/a/b/c"></a>
指令縮寫:
<a v-bind:href="url"></a> -> <a :href="url"></a>
<button v-bind:disabled="someDynamicCondition">Button</button> -> <button :disabled="someDynamicCondition">Button</button>
<a v-on:click="doSomething"></a> -> <a @click="doSomething"></a>
五、Vue實例
1、構造器:
var data = { a: 1 };
var vm6 = new Vue({ //每個 Vue.js 應用的起步都是通過構造函數 Vue 創建一個 Vue 的根實例
el: '#example',
data: data,
beforeCreate:function(){}, //創建前
created: function(){ //創建后
console.log('a is: ' + this.a); //`this` 指向 vm 實例
},
beforeMount:function(){}, //加載前
mounted:function(){}, //加載后
beforeUpdate:function(){}, //更新前
updated:function(){}, //更新后
beforeDestroy:function(){}, //銷毀前
destroyed:function() {} //銷毀后
});
2、擴展Vue構造器,從而用預定義選項創建可復用的組件構造器:
var MyComponent = Vue.extend({
//擴展選項
});
var myComponentInstance = new MyComponent(); //所有的 `MyComponent` 實例都將以預定義的擴展選項被創建
3、屬性和方法
console.log( vm6.a === data.a ); //true
//設置屬性也會影響到原始數據
vm6.a = 2;
console.log( data.a ); //2
//反之亦然
data.a = 3;
console.log( vm6.a ); //3
vm6.b=5; //注意:只有這些被代理的屬性是響應的。如果在實例創建之后添加新的屬性到實例上,它不會觸發視圖更新
console.log(data.b); //undefined
4、實例屬性與方法:這些屬性與方法都有前綴$,以便與代理的數據屬性區分
vm6.$data === data //true
vm6.$el === document.getElementById('example'); //true
vm6.$watch('a', function (newVal, oldVal) {}); //$watch 是一個實例方法,這個回調將在 `vm.a` 改變后調用
六、數據綁定語法
1、文本插值:
<span>Message:{{ msg }}</span> //每當這個屬性變化時它也會更新
<span v-once>This will never change:{{ msg }}</span> //一次性綁定
2、純 HTML:
<div v-html="rawHtml"></div> //大括號會將數據解釋為純文本,為了輸出真正的 HTML ,需使用 v-html 指令,你不能使用 v-html 來復合局部模板,組件更適合擔任 UI 重用與復合的基本單元
3、屬性:
<div v-bind:id="dynamicId"></div>
4、綁定表達式:
{{ number + 1 }}
{{ ok ? 'YES' : 'NO' }}
{{ message.split('').reverse().join('') }}
一個限制是每個綁定只能包含單個表達式,因此下面的語句是無效的:
{{ var a = 1 }} //這是一個語句,不是一個表達式
{{ if (ok) { return message } }} //流程控制也不可以,可改用三元表達式
5、過濾器:
{{ message | capitalize }} //這個過濾器其實只是一個 JavaScript 函數,返回大寫化的值
{{ message | filterA | filterB }} //過濾器可以串聯
{{ message | filterA 'arg1' arg2 }} //過濾器也可以接受參數:第一個參數—為過濾器函數,帶引號的參數—為字符串,不帶引號的參數—按表達式計算
6、指令: 職責是—當其表達式的值改變時把某些特殊的行為應用到 DOM 上
<p v-if="greeting">Hello!</p> //v-if 指令將根據表達式 greeting 值的真假刪除/插入 <p> 元素
7、參數:
<a v-bind:href="url"></a> //v-bind 指令,用於響應地更新 HTML 特性,用特性插值 href="{{url}}" 可獲得同樣的結果,但實際上它也是在內部特性插值,轉為 v-bind 綁定
<a v-on:click="doSomething"></a> //v-on 指令,用於監聽 DOM 事件,參數是被監聽的事件的名字
8、修飾符:以半角句號 . 開始的特殊后綴,表示指令應當以特殊方式綁定
<a v-bind:href.literal="/a/b/c"></a>
9、縮寫:
<a v-bind:href="url"></a> //完整語法
<a :href="url"></a> //縮寫
<a v-on:click="doSomething"></a> //完整語法
<a @click="doSomething"></a> //縮寫
七、計算屬性 $watch、computed、計算屬性的getter、setter屬性
1、計算屬性:
var vm = new Vue({
el: '#example',
data: {
a: 1
},
computed: {
b: function () { //一個計算屬性的 getter
return this.a + 1; //`this` 指向 vm 實例
}
}
});
console.log(vm.b); //2
vm.a = 2;
console.log(vm.b); //3
2、計算屬性 $watch與computed對比:
var vm2=new Vue({
el:"#example2",
data:{
firstName:'Foo',
lastName:'Bar',
fullName:'Foo Bar'
}
});
vm2.$watch('firstName',function(val){
this.fullName=val+' '+this.lastName;
});
vm2.$watch('lastName',function(val){
this.fullName=this.firstName+' '+val;
});
var vm3=new Vue({
el:'#example2',
data:{
firstName:'Foo',
lastName:'Bar'
},
computed:{
fullName:function(){
return this.firstName+' '+this.lastName;
}
}
});
3、計算 setter:
var vm = new Vue({
el: '#demo',
data: {
firstName: 'Foo',
lastName: 'Bar'
},
computed: {
fullName: {
get: function () { //getter
return this.firstName + ' ' + this.lastName;
},
set: function (newValue) { //setter
var names = newValue.split(' ');
this.firstName = names[0];
this.lastName = names[names.length - 1];
}
}
}
});
//現在在調用 vm.fullName = 'John Doe' 時,setter 會被調用,vm.firstName 和 vm.lastName 也會有相應更新
八、class與style綁定(數據綁定在data上)
1、綁定class
1)對象語法
<div id="box" v-bind:class="{ 'class-a': isA, 'class-b': isB }"></div>
<div id="box2" v-bind:class="classObject"></div>
2)數組語法
<div id="box3" v-bind:class="[classA,classB]"></div>
<div id="box4" v-bind:class="[classA,isB?classB:'']"></div>
<div id="box5" v-bind:class="[classA,{classB:isB,classC:isC}]"></div> <!--當有多個條件 class 時,在 1.0.19+ 中,可以在數組語法中使用對象語法-->
2、 綁定內聯樣式style
1)對象語法
<div id="box6" v-bind:style="{color:activeColor,fontSize:fontSize+'px'}"></div>
<div id="box7" v-bind:style="styleObject"></div>
2)數組語法
<div id="box8" v-bind:style="[styleObjectA,styleObjectB]">text</div> <!-- v-bind:style 的數組語法可以將多個樣式對象應用到一個元素上-->
九、條件渲染 v-if、v-show、v-else(條件指令不能在實例元素上使用)
1、在字符串模板中,如 Handlebars,我們得像這樣寫一個條件塊:
{{#if ok}}
<h1>Yes</h1>
{{/if}}
* 注意,以下所有的條件指令,都不能在實例根元素上使用
1)v-if,v-else
HTML:
<div id="box1">
<h1 v-if="greeting">Yes</h1>
</div>
<div id="box2">
<h1 v-else="greeting2">No</h1>
</div>
JS:
var vm=new Vue({
el:"#box1",
data:{
greeting:false
}
});
var vm2=new Vue({
el:"#box2",
data:{
greeting2:false
}
});
2)多個元素v-if,需要將v-if添加到包裝元素template上,最終的渲染結果不會包含它
HTML:
<div id="box3">
<template v-if="ok">
<h1>Title</h1>
<p>Paragraph 1</p>
<p>Paragraph 2</p>
</template>
</div>
JS:
var vm3=new Vue({
el:'#box3',
data:{
ok:false
}
});
3)v-show 指令: 也是根據條件展示元素的選項,但它只是切換display屬性。注意,v-show 不支持 <template> 語法
HTML:
<div id="box4">
<h1 v-show="ok">Hello!</h1>
</div>
JS:
var vm4=new Vue({
el:"#box4",
data:{
ok:false
}
});
4)v-else 指令:必須立即跟在v-if/v-show的后面,否則它不能被識別
HTML:
<div id="box5">
<div v-if="greeting">Sorry</div>
<div v-else>Not sorry</div>
</div>
JS:
var vm5=new Vue({
el:"#box5",
data:{
greeting:Math.random()>0.5
}
});
5)v-if、v-show與組件組合使用
HTML:
<div id="box6">
<custom-component v-show="condition">1</custom-component>
<p v-else>這可能也是一個組件1</p>
</div>
<div id="box7">
<custom-component v-show="condition">2</custom-component>
<p v-show="!condition">這可能也是一個組件2</p>
</div>
JS:
var vm6=new Vue({
el:"#box6",
data:{
condition:true
}
});
var vm7=new Vue({
el:"#box7",
data:{
condition:false
}
});
6)v-if、v-show對比
在切換 v-if 塊時,Vue.js 有一個局部編譯/卸載過程,因為 v-if 之中的模板也可能包括數據綁定或子組件。v-if 是真實的條件渲染,因為它會確保條件塊在切換當中合適地銷毀與重建條件塊內的事件監聽器和子組件。
v-if 也是惰性的:如果在初始渲染時條件為假,則什么也不做——在條件第一次變為真時才開始局部編譯(編譯會被緩存起來)。
相比之下,v-show 簡單得多——元素始終被編譯並保留,只是簡單地基於 CSS 切換。
一般來說,v-if 有更高的切換消耗,而 v-show 有更高的初始渲染消耗。
因此,如果需要頻繁切換 v-show 較好,如果在運行時條件不大可能改變 v-if 較好。
十、列表渲染 v-for
1、v-for: $index、template v-for(items是data中的一個數組)
HTML:
<li v-for="(index,item) in items">{{ index }}-{{ item.message }}</li>
<li v-for="item of items">{{ $index }}-{{ item.message }}</li> <!--從 1.0.17 開始可以使用 of 分隔符,更接近 JavaScript 遍歷器語法-->
HTML:
<ul id="example1">
<template v-for="item in items">
{{ parentMessage }} - {{ $index+1 }}
<li>{{ item.msg }}</li>
<li class="divider">--------------</li>
</template>
</ul>
JS:
var vm1=new Vue({
el:'#example1',
data:{
parentMessage:'標題',
items:[
{ msg:'Foo' },
{ msg:'Bar' }
]
}
});
2、數組變動檢測: 變異方法、非變異方法、track-by、$set、$remove
1)數組方法
a、變異方法:會修改原始數組
? push() ? pop() ? shift() ? unshift()
? splice() ? sort() ? reverse()
b、非變異方法(替換數):不修改原始數組,而返回新數組,可直接用新數組替換舊數組
? filter() ? concat() ? slice()
這並不會導致 Vue棄用已有DOM,重新渲染整個列表,Vue實現了一些啟發算法,最大化復用 DOM 元素,會用新數組替換原始數組
HTML:
<ul id="example2">
<li v-for="item in items">
{{ item.message }}
</li>
</ul>
JS:
var vm2=new Vue({
el:'#example2',
data:{
items:[
{ message:'Foo1' },
{ message:'Bar1' }
]
}
});
vm2.items.push({ message:'test1' });
vm2.items = vm2.items.filter(function (item) {
return item.message.match(/Foo/);
});
2)track-by:追蹤元素,避免無用的重新渲染DOM元素
HTML:
<ul id="example3">
<li v-for="item in items" track-by="_uid">
{{item._uid}}
</li>
</ul>
JS:
var vm3=new Vue({
el:'#example3',
data:{
items:[
{ _uid:'88f869d' },
{ _uid:'7496c10' }
]
}
});
/*
在替換數組 items 時,如遇到包含 _uid: '88f869d' 的新對象,Vue可復用這個已有對象的作用域與 DOM 元素,
如沒有唯一的鍵供追蹤,可以使用 track-by="$index",它強制讓 v-for 進入原位更新模式:
-> 片斷不會被移動,只是刷新對應索引的新值,這種模式也可處理數據數組中重復的值
-> 數據替換高效,但也會付出一定的代價
-> DOM 節點不再映射數組元素順序的改變,不能同步臨時狀態(eg: <input> 元素的值)以及組件的私有狀態
-> 如果 v-for 塊包含 <input> 元素或子組件,要小心使用 track-by="$index"
*/
3)問題: .$set(); .items=[];
因為 JavaScript 的限制,Vue.js 不能檢測到下面數組變化:
a.直接用索引設置元素,如 example3.items[0] = {}
b.修改數據的長度,如 example3.items.length = 0
為了解決問題1,Vue.js 擴展了觀察數組,為它添加了一個 $set() 方法:
HTML:
<ul id="example4">
<li v-for="item in items">
{{ $index+1 }}—{{ item.childMsg }}
</li>
</ul>
JS:
var vm4 = new Vue({
el: '#example4',
data: {
items: [
{ childMsg: 'Foo3' },
{ childMsg: 'Bar3' }
]
}
});
vm4.items.$set(0, { childMsg: 'Changed!'}); //為了解決問題a,Vue.js 擴展了觀察數組,為它添加了一個 $set() 方法
vm4.items=[]; //至於問題b,只需用一個空數組替換 items
4)$remove:用於從目標數組中查找並刪除元素
HTML:
<ul id="example5">
<li v-for="item in items">
{{ $index }}—{{ item.msg }}
</li>
</ul>
JS:
var vm5 = new Vue({
el: '#example5',
data: {
items: [
{ msg: 'Foo4' },
{ msg: 'Bar4' }
]
}
});
/*
在內部它調用 splice(),因此,不必這樣:
var index = this.items.indexOf(item);
if (index !== -1) {
this.items.splice(index, 1);
}
只用這樣:
this.items.$remove(item);
*/
vm5.items.filter(function (item) {
if(item.msg=='Foo4'){
vm5.items.$remove(item);
}
});
3、對象json v-for: $key、value
<li v-for="value in object">{{ $key }} : {{ value }}</li>
<li v-for="(key,val) in object">{{ key }} {{ val }}</li> <!--也可以給對象的鍵提供一個別名-->
對象json的遍歷,在內部是用的Object.keys遍歷,但不同的JS引擎下不是一致的
4、值域: v-for="n in 10"
<div id="example6"><span v-for="n in 10">{{ n }} </span></div>
5、顯示過濾排序的結果:
想顯示過濾/排序過的數組,同時不實際修改或重置原始數據,有2個辦法:
a、使用內置的過濾器 filterBy 和 orderBy,過濾器更方便
b、創建一個計算屬性,返回過濾/排序過的數組,計算屬性有更好的控制力,更靈活,因為它是全功能JS
1)filterBy : 限制—指令的值須是數組,eg:v-for
a、只顯示包含字符串 "hello" 的元素 : <div v-for="item in items | filterBy 'hello'"></div>
b、只在用戶對象的 name 屬性中搜索 "Jack": <div v-for="user in users | filterBy 'Jack' in 'name'"></div>
c、使用動態參數作為搜索目標或搜索字段,配合 v-model 我們可以輕松實現輸入提示效果:
HTML:
<div id="example6">
<input v-model="searchText" />
<ul>
<li v-for="user in users | filterBy searchText in 'name'">
{{ user.name }}
</li>
</ul>
</div>
JS:
var vm6=new Vue({
el:'#example6',
data:{
searchText:'',
users:[
{ name:'Bruce' },
{ name:'Chuck' },
{ name:'Jackid' }
]
}
});
d、多搜索字段:
HTML:
<div id="example7">
<input v-model="searchText">
<ul>
<li v-for="user in users | filterBy searchText in 'name' 'phone'">
{{ user.name }}-{{ user.phone }}
</li>
</ul>
</div>
JS:
var vm7=new Vue({
el: '#example7',
data: {
searchText: '',
users: [
{ name: 'Bruce', phone:'18701039633' },
{ name: 'Chuck', phone:'18700000000' },
{ name: 'Jackie', phone:'15811119619' }
]
}
});
2)orderBy:限制—指令的值須是數組,eg v-for, 1為升序,-1為降序
a、升序: <li v-for="user in users | orderBy 'phone'">{{ user.name }}-{{ user.phone }}</li>
b、降序: <li v-for="user in users | orderBy 'phone' -1">{{ user.name }}-{{ user.phone }}</li>
c、原始類型數組: <li v-for="n in 10 | orderBy -1">{{ n }}</li>
d、動態排序:
HTML:
<div id="example8">
<button @click="order = order * -1">Reverse Sort Order</button>
<ul>
<li v-for="user in users | orderBy 'name' order">
{{ user.name }}
</li>
</ul>
</div>
JS:
var vm8=new Vue({
el: '#example8',
data: {
order: 1,
users: [
{ name: 'Bruce' },
{ name: 'Chuck' },
{ name: 'Jackie' }
]
}
});
e、使用兩個鍵名排序:
HTML:
<div id="example9">
<ul>
<li v-for="user in users | orderBy 'name' 'phone' order">
{{ user.name }}-{{ user.phone }}
</li>
</ul>
</div>
JS:
var vm9=new Vue({
el: '#example9',
data: {
users: [
{ name: 'Bruce', phone:'18701039633' },
{ name: 'Chuck', phone:'18700000000' },
{ name: 'Jackie', phone:'15811119619' }
]
}
});