通過三方力量,對vue有了初步的了解,通過數據直接影響視圖。通過vue實現todolist任務來鞏固相關知識點。Todolist需要實現的主要功能有:任務的添加,回車添加(v-model、v-on)、刪除(v-on)、選定重編輯(@dblclick)及取消重編輯(按esc)、對已完成任務、未完成任務及所有任務的列表切換顯示(computed、v-show、v-if、v-bind、v-for、active)、存取數據(localStorage、watch)。
添加任務:
在<input>輸入框中輸入內容,按回車,則下面的任務列表中會出現剛剛添加的內容。該功能利用函數在methods中實現,調用push()方法(與數組中push()方法不太一樣)。在methods中定義一個addTodo()方法實現,並在<input>標簽中通過v-on指令綁定該函數。即當我們向<input>輸入內容后按回車鍵觸發該函數,前面的勾選框默認false不選中,此時會向列表項中插入一條任務,即一個對象,然后把輸入框清空。title值通過v-model實現雙向數據綁定。
刪除任務:
直接點擊任務列表后面的叉即可刪除任務。根據任務內容找到list對象中的下標,然后通過splice()方法(與數組中對應方法不太一樣)將其刪除。
雙擊修改任務:
雙擊任務內容,可以改變任務內容,即title的值,將當前編輯的值賦值給title,然后在<label>標簽中通過@dblclick綁定該修改函數edtorTodo(),同時在類名todo的<li>標簽上,動態綁定一個class為editing,並為其指定修改之后的值edtorTodos,通過這個class來改變任務列表及相對應修改title的輸入框的隱藏與顯示,通過v-model檢測title的改變並進行綁定。
輸入框內取消修改:
在輸入框內輸入修改內容后,若不想修改了,則可按esc返回到之前的內容狀態。這里在methods里定義了一個取消修改的函數cancelTodo(),定義一個beforeTitle保存之前的內容,然后將beforeTitle值賦給當前title。同時,通過@keyup.esc綁定cancelTodo()函數。
所有任務、未完成任務、完成任務的切換及計算:
通過計算屬性computed根據isChecked值動態計算出對應list中任務個數。通過filter過濾、watch及hash值實現對應項的切換功能。
(1-我們可以給window對象通過addEventListener綁定一個 hashchange事件,回調函數就是獲得這個hash值,然后把這個hash值賦給Vue實例中的visibility屬性,這個visibility默認是全部顯示的。2-通過一個計算屬性filteredList來根據visibility的值動態返回不同的狀態的list,然后html中v-for指令就不是直接渲染list了,而是通過這個filteredList篩選出來的list,如果在輸錯hash值的情況下,我們可以判斷hash不存在的情況下,全都返回hash值為all的結果,這樣就達到了我們想要的效果了。
)
實現刷新頁面時列表項內容依然存在,即列表項內容的存儲:
這里用localStorage,利用其save()與fetch()實現數據的存取,即通過localStorage.setItem()實現存儲,localStorage.getItem()實現讀取。將獲取的本粗存儲的值賦給list,即可實現列表項內容不丟失。通過watch的深監控來監控list內數據的值並作出相應處理。
實現該任務用到的知識點有:
- 將vue.js框架通過<script>標簽引入
- v-for指令:根據一組數組的選項列表進行渲染
語法:
value,key in items
value,key of items
- 變異方法:
vue提供一組方法,對數組進行操作時候,會觸發視圖更新
push() pop() shift() unshift() splice() sort() reverse()
- 事件處理器
v-on指令:用來監聽dom事件觸發代碼
語法:v-on:eventName=”eventHandle”
指令簡寫: @
事件處理函數:寫在methods中統一管理
事件對象:在事件處理函數中獲取;內聯事件處理函數執行,傳入事件對象。$event
- 事件修飾符:
事件處理函數只有純粹的邏輯判斷,不處理dom事件的細節,如阻止冒泡、取消默認行為、判斷按鍵
修飾符的位置:v-on:eventName.修飾符
修飾符:.stop .prevent .capture .self .once
按鍵修飾符:
.enter .tab .delete .esc .space .up .down .left .right .ctrl .alt .shift .meta .鍵值
執行事件處理函數時可以進行傳參
<input placeholder="勇敢自信youcan; 提示:+回車即可添加任務" class="task-input" type="text" v-model="todo" v-on:keyup.enter="addTodo(123,$event)" /> new Vue({ el:".main", data:{ list:list, todo:"" }, methods:{ //統一管理事件處理函數 addTodo:function(data,ev){ /*//添加任務//向list中添加一項任務//事件處理函數中的this指向的是當前這個根實例*/ this.list.push({ /*title:ev.target.value*/ title:this.todo //替換上面的語句,減少dom操作 }); this.todo=" "; //數據更新視圖 } } });
- 條件渲染:
v-show指令:根據表達式的值,決定顯示或隱藏元素。
語法:v-show=”表達式”
元素會被渲染在頁面中只根據表達式的值進行css切換
- 動態綁定class:
class也為元素的屬性,可以使用v-bind:class
語法:
:class=”{className:表達式}” // 表達式值為true,添加className,否則不添加
:class=”[className,className]”
v-bind指令:為元素動態綁定class,不同的條件下綁定不同的class,從而實現不同的樣式顯示。
- 自定義指令:
除了vue內置的指令,可以自己設置指令
選項對象的directives屬性{
directives:{}
}
鈎子函數:
update被綁定元素所在的模板更新時調用
鈎子函數中參數:
el:指令所綁定的元素,可以用來直接操作dom
binding:一個對象
value:指定的綁定值
- 計算屬性
模板是為了描述視圖的結構,模板中放入太多邏輯,導致模板太重,難以維護。
在計算一個屬性時,vue.js更新它的依賴列表並緩存結果,只有當其中一個依賴發生了變化,緩存的結果才有效。通過計算屬性可以實現對數據的過濾篩選。
語法:
在選項對象中
{
…
computed:{}
}
- v-model指令:實現對數據的雙向綁定
- 存取localStorage中的數據
- 通過監控hash值變化來決定顯示哪一部分
- watch的深監控與淺監控
var list=[ { title:"勇敢勇敢再勇敢", isChecked:false //false表示未選中,任務未完成 }, { title:"堅強自信youcan", isChecked:true //true,選中,任務完成 } ] watch:{ //監控功能 /* list:function(){ //監控list這個屬性,當值發生變化時就會執行后面的函數 store.save("miaov-new-class",this.list); }//淺監控*/ list:{ handler:function(){ store.save("miaov-new-class",this.list); }, deep:true //深監控 } }
html核心代碼:
<body> <div class="page-top"> <div class="page-content"> <h2>任務計划列表</h2> </div> </div> <div class="main"> <h3 class="big-title">添加任務</h3> <input placeholder="勇敢自信youcan; 提示:+回車即可添加任務" class="task-input" type="text" v-model="todo" v-on:keyup.enter="addTodo" /> <ul class="task-count" v-show="list.length"> <li>{{ noCheckeLength }}個任務未完成</li><!--渲染數據--> <li class="action"> <a :class="{active:visibility==='all'}" href="#all">所有任務</a> <a href="#unfinished" :class="{active:visibility==='unfinished'}">未完成的任務</a> <a href="#finished" :class="{active:visibility==='finished'}">完成的任務</a> </li> </ul> <h3 class="big-title">任務列表</h3> <div class="tasks"> <span class="no-task-tip" v-show="!list.length">還沒有添加任何任務</span> <ul class="todo-list"> <li class="todo " :class="{completed:item.isChecked,editing:item===edtorTodos}" v-for="item in filteredList"> <div class="view"> <input class="toggle" type="checkbox" v-model="item.isChecked" /> <label @dblclick="edtorTodo(item)">{{item.title}}</label> <button class="destroy" @click="deleteTodo(item)"></button> </div> <input v-focus="edtorTodos===item" class="edit" type="text" v-model="item.title" @blur="edtorTodoed(item)" @keyup.enter="edtorTodoed(item)" @keyup.esc="cancelTodo(item)" /> </li> </ul> </div> </div>
js核心代碼:
var store={ //封裝一個對象//存取localStorage中的數據 save(key,value){ //es6函數寫法 localStorage.setItem(key,JSON.stringify(value)); //將數據轉換為json形式的字符串 }, fetch(key){ return JSON.parse(localStorage.getItem(key))||[]; //獲得的數據是json字符串,需要用json.parse解析一下,若沒取到就返回空 } } //取出所有的值 //到localStorage中取數據 var list=store.fetch("miaov-new-class"); //過濾的時候分三種情況:all、finished、unfinished var filter={ all:function(list){ return list; }, finished:function(list){ return list.filter(function(item){ return item.isChecked; }) }, unfinished:function(){ return list.filter(function(item){ return !item.isChecked; }) } } var vm=new Vue({ el:".main", data:{ list:list, todo:"", edtorTodos:'' ,//記錄正在編輯的數據 beforeTitle:'' ,//記錄一下正在編輯的數據的title visibility:"all" //通過這個屬性值的變化對數據進行篩選 }, watch:{ //監控功能 list:{ handler:function(){ store.save("miaov-new-class",this.list); }, deep:true //深監控 } }, computed:{ noCheckeLength:function(){ return this.list.filter(function(item){ return !item.isChecked }).length }, filteredList:function(){ //找到了過濾函數就返回過濾后的數據,如果沒有則返回所有數據 return filter[this.visibility] ? filter[this.visibility](list) : list; } }, methods:{ //統一管理事件處理函數 addTodo:function(){ /*//添加任務 //向list中添加一項任務 //事件處理函數中的this指向的是當前這個根實例*/ this.list.push({ /*title:ev.target.value*/ title:this.todo , //替換上面的語句,減少dom操作 isChecked:false }); this.todo=''; //數據更新視圖 }, deleteTodo:function(todo){ //刪除任務 var index=this.list.indexOf(todo); this.list.splice(index,1); }, edtorTodo:function(todo){ //編輯任務 console.log(todo); this.edtorTodos=todo;//用數據記錄一下現在正在編輯的信息, // 編輯任務的時候,記錄一項編輯這條任務的title,方便取消編輯的是好重新給之前的title this.beforeTitle=todo.title; }, edtorTodoed:function(todo){ //編輯任務成功 this.edtorTodos=""; }, cancelTodo:function(todo){ //取消編輯任務 /*console.log(123);*/ todo.title=this.beforeTitle; this.beforeTitle=''; //讓div顯示出來,input框隱藏,可以選擇將正在編輯的信息置為空 this.edtorTodos=''; } }, directives:{ "focus":{ update(el,binding){ /* console.log(el); console.log(binding);*/ if(binding.value){ el.focus();//當選中某個input時自動獲得焦點 } } } } }); function watchHashChange(){ var hash=window.location.hash.slice(1); /*console.log(hash);*/ vm.visibility=hash; } watchHashChange(); window.addEventListener("hashchange",watchHashChange);
結果:
初次錄屏,有點失敗啊,捂臉。。。。。。
遇到的問題:
1-網頁開始定義的文字及列表后面的叉刪除符顯示異常
解決方法:
html的head中定義:
<meta
http-equiv="Content-Type"
content="text/html; charset=utf-8"
/>
;
同時
在css開頭定義:@charset "utf-8";
2- {{message}}直接顯示,而沒有渲染成綁定的數據
數據沒有傳進去,初步判斷為es6與es5模式的混用,如let聲明、var聲明及函數的簡寫
3-在所有任務、未完成任務、完成任務三個顯示框上,點擊哪個下面對應的列表項就顯示哪個,但紅色的框框始終顯示在所有任務上
原來問題出在css :active選擇器上啊。:active選擇器用於選擇活動鏈接,當在一個鏈接上點擊時,其將成為活動鏈接即被激活的。此外,:link選擇器用於設置對未被訪問頁面的鏈接的樣式;:visited選擇器用於設置指向已訪問頁面的鏈接的樣式;:hover選擇器用於設置鼠標指針浮動在鏈接上時的樣式。
<li class="action">
<a :class="{active:visibility==='all'}" href="#all">所有任務</a>
<a href="#unfinished" :class="{active:visibility==='unfinished'}">未完成的任務</a>
<a href="#finished" :class="{active:visibility==='finished'}">完成的任務</a>
</li>
.active {
border: 1px solid rgba(175, 47, 47, 0.2);
}
4-在所有任務頁面,當刪除列表項內容時,下面的列表項內容會立即消失,但是在未完成任務與已完成任務頁面,當點擊刪除列表項內容時,列表項內容不會立即消失,當刷新頁面或點擊別處再點回來時其下被刪除的列表項內容才會被刪除,這里的問題出現在哪里呢?
有待解決。。。。。。
源碼可參考:https://github.com/sunshineqt/vue