文章的原材料來自於vue的官方示例:https://cn.vuejs.org/v2/examples/todomvc.html,我們在學習過程中,試着對其中的一些知識點進行記錄:
一、瀏覽器數據存儲,為了方便,此處將數據存儲到客戶端的緩存中,使用localStorage,他的主要api有
localStorage.getItem(key)和localStorage.setItem(key,value)
二、對於localStorage中的數據采取json數組形式保存,因此在保存value和獲取時候需要先做json和string的轉化,ECMA5提供了兩個轉化方法:
將指定格式數據轉為json:JSON.parse(string);將json轉為string:JSON.stringify(json)
var TODO_KEY="vue-todo"; var todoStorage={ fetch:function(){ var todos=JSON.parse(localStorage.getItem(TODO_KEY)||'[]') todos.forEach(function(todo,index){ todo.id=index; }); todoStorage.uid=todos.length; return todos; }, save:function(todos){ localStorage.setItem(TODO_KEY,JSON.stringify(todos)); } }
三、使用hashchange監聽瀏覽器地址欄變化
在單頁應用同頁跳轉的情況下,添加監聽window.addEventListener('hashchange',onHashChange)來獲取地址欄的變化,然后可以使用window.location.hash來監聽到地址欄的后綴變化,如果xxx.html#/all,此處值為"#/all",獲取地址欄的值變化,此處主要根據地址欄的visibility過濾不同的內容
function onHashChange(){ var visibility=window.location.hash.replace(/#\/?/,''); if(filters[visibility]){ app.visibility=visibility; }else{ window.location.hash=''; app.visibility='all'; } } window.addEventListener('hashchange', onHashChange) onHashChange()
三、json或者數組的過濾
如果要根據todos中的completed的狀態過濾掉對應的子項,需要使用filter,如過濾掉非completed的項,是如下寫法
function(todos){ return todos.filter(function(todo){ return !todo.completed; });
四、json或者數組中的某一項,修改
如果要將todos的子項中的內容進行修改,需要使用forEach操作,如將所有completed修改為true,如下寫法:
this.todos.forEach(function(todo){ todo.completed=true; });
五、自定義vue標簽
<input class="edit" type="text" v-model="todo.title" v-todo-focus="todo == editedTodo" @blur="doneEdit(todo)" @keyup.enter="doneEdit(todo)" @keyup.esc="cancelEdit(todo)">
在此input標簽中,我們希望如果是正在編輯的todo時候,自動被選中,此處自定義了一個v-todo-focus標簽,此標簽的格式如下
directives: { 'todo-focus': function (el, value) { if (value) { el.focus() } } }
指令定義,官方提供了五個鈎子函數來供我們使用,分別代表了一個組件的各個生命周期
bind: 只調用一次,指令第一次綁定到元素時調用,用這個鈎子函數可以定義一個在綁定時執行一次的初始化動作。
inserted: 被綁定元素插入父節點時調用(父節點存在即可調用,不必存在於 document 中)。
update: 被綁定元素所在的模板更新時調用,而不論綁定值是否變化。通過比較更新前后的綁定值,可以忽略不必要的模板更新(詳細的鈎子函數參數見下)。
componentUpdated: 被綁定元素所在模板完成一次更新周期時調用。
unbind: 只調用一次, 指令與元素解綁時調用。
在這里其他幾個都好理解,關於模板更新(update)這里,本人的理解是:該指令所在的模板有變化而需要重新渲染的時候,比如當一個輸入框的model發生了變化就會觸發指令。當然此處說的比較模糊,具體的還有待研究。
六、v-cloak標簽
vuejs做的界面加載過程中會閃現vue的變量,如{{msg}},在標簽加上v-cloak,在css定義可以解決此問題
[v-cloak] { display: none; }
<section class="main" v-show="todos.length" v-cloak>
這段 CSS 的含義是,包含 v-cloak (cloak n. 披風,斗篷;vt. 遮蓋,掩蓋) 屬性的 html 標簽在頁面初始化時會被隱藏。
在 vuejs instance ready 之后,v-cloak 屬性會被自動去除,也就是對應的標簽會變為可見。問題來了,怎么才算是 ready 呢?這就需要了解 vuejs instance 的生命周期了
七、使用watch完成localStorage的寫入操作
watch: { todos: { handler: function (todos) { todoStorage.save(todos) }, deep: true } },
在todo-list的應用中,整個操作過程中的增刪改查操作很多,系統使用todos來保存每次操作后的結果,然后使用watch監控todos的變化,完成緩存的更新,注:deep表示深復制,即元素發生變化,也會導致他的變化
八、計算屬性和觀察屬性
在todo-list有一個全選按鈕,如果選中的時候,所有任務被標記為完成,如果任務全部完成,此標記也會被標記選中
1、以下是我的實現,對allDon進行watch,如果發生了改變,則修改所有任務狀態,
allDone:function(){ this.allDone!=this.allDone; var selDone=this.allDone; this.todos.forEach(function(todo){ todo.completed=selDone; }); }
同時在computed計算remaining的時候,根據remaining修改allDone
remaining:function(){ var remaining=filters.active(this.todos).length; this.allDone=remaining===0?true:false; return remaining; }
2、以下是官方實現,使用computed的get和set操作allDone,減少了元素定義,也更為清晰
allDone: { get: function () { return this.remaining === 0 }, set: function (value) { this.todos.forEach(function (todo) { todo.completed = value }); }
九、數組的操作-使用push和slice進行添加數組元素和刪除數組元素,略
十、使用filters進行格式化,此處其實可以使用computed進行實現
filters: { pluralize: function (n) { return n === 1 ? 'item' : 'items' } },
十一、在做var app=new Vue()的時候,我們可以不用指定元素,等其他初始化完成后,最后一步再使用mount進行綁定
// mount app.$mount('.todoapp')
十二、對於todo的編輯和展示切換
對於某一條todo,我們要求雙擊進行切換到編輯模式,回車切換到展示模式,我們的處理是:對於此todo,兩種模式在頁面上共存,通過method方法,改變對應的class,達到切換的目的。
<li v-for="todo in filteredTodos" class="todo" :key="todo.id" :class="{ completed: todo.completed, editing: todo == editedTodo }"> <div class="view"> <input class="toggle" type="checkbox" v-model="todo.completed"> <label @dblclick="editTodo(todo)">{{ todo.title }}</label> <button class="destroy" @click="removeTodo(todo)"></button> </div> <input class="edit" type="text" v-model="todo.title" v-todo-focus="todo == editedTodo" @blur="doneEdit(todo)" @keyup.enter="doneEdit(todo)" @keyup.esc="cancelEdit(todo)"> </li>
代碼可以看到,顯示todo的地方有一個div用於顯示,一個input用於編輯,根據editedTodo來確定是否給li綁定editing的class,如果綁定后,class如下,顯示edit,隱藏view
.todo-list li.editing .edit { display: block; width: 506px; padding: 12px 16px; margin: 0 0 0 43px; } .todo-list li.editing .view { display: none; }
