一、工具
- 具備html、css、js的基礎知識
- chrome瀏覽器
- vscode文本編輯器
- vuejs的官方文檔
二、我理解的vuejs
vue(讀/vju:/,與view同音)是一套用於構建用戶界面的js框架,它是輕量級的,易上手(作爲一個前端小白本人用事實證明確實易上手)
官方提供了webpack等腳手架工具,提供了一整套前端集成框架,所有依賴都已經包辦,只需要下載好然後根據要求在指定目錄下開發自己的項目內容即可(但本博文沒有使用此方法)
另一種引入vue的方法是,直接在.html靜態文件中通過
<script>
標籤的方式引入(本文采取的方式),可以根據需要選擇版本,這僅適用小小型應用:<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
我理解的vue是一個寫好的js類,我們需要先new一個vue的實例並綁定標籤,才能使用它
vue能夠動態地將html中的元素與vue中定義的data雙向綁定起來,動態更新,能夠方便地將數據操作與頁面渲染展示的工作分割開來,能更專注於展示,屏蔽底部細節。下面的介紹也會體現這一點,這裏僅概括一下我的理解
三、編寫一個簡單的todolist
3.1 引入vuejs
html部分的靜態文件非常簡單,如下所示:
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>TodoList</title> <link href="index.css" rel="stylesheet" type="text/css" /> <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script> </head> <body> <div id="app"> <todo-body></todo-body> </div> <script src="../src/main.js"></script> </body> </html>
注意到
<body>
部分有一個<todo-body>
的標籤,這是一個vue組件(component),正確定義和註冊就可以直接在html文件中以標籤的形式使用引入vuejs之後,在chrome瀏覽器中可以觀察到文件目錄結構如下所示:
3.2 註冊一個vue的實例,並綁定id
// main.js
new Vue({
el: '#app',
})
- 這裏的
el
是element
的意思 #app
表示id="app"
的元素是一個vue實例- 缺少這一句註冊,是無法正確渲染的
- 曾嘗試過將
el
設爲'body'
,會報錯說不要將vue掛載在<html>
或<body>
元素上,讓我使用一般的元素:
[Vue warn]: Do not mount Vue to <html> or <body> - mount to normal elements instead.
3.3 註冊一個vue組件
(1)什麼是vue組件
任何應用界面都可以抽象爲一個組件樹(圖源自vuejs官方文檔):
在vue中,組件的本質是一個擁有預定義選項的vue實例,因此組件也擁有vue的四大選項:
data
數據、methods
方法/函數、watch
監聽事件、props
組件自定義屬性
(2)註冊一個名叫todo-body的vue組件
//main.js
Vue.component('todo-body', {
data: function() {
return {
title: 'This is a ToDoList'
}
},
template: '<h2>{{ title }}</h2>',
methods: {},
watch: {}
})
- 意思是註冊一個名叫
todo-body
的vue組件,其擁有一個數據變量title
(一個擁有初始值的字符串) - 這樣註冊以後,在靜態html中使用
<todo-body>
標籤就會套入組件中定義好的template
部分(如3.1所述),而template
中的雙花括號會顯示組件中的title
變量的值 - 需要注意的是,註冊組件用到的
data
必須是以函數返回值的形式,避免複用組件時因數據共享導致的意想不到的錯誤
3.4 完善todo-body的vue組件
//main.js
Vue.component('todo-body', {
data: function() {
return {
title: 'This is a ToDoList',
newLabel: '',
items: []
}
},
template: '<div>\
<h2>{{ title }}</h2> \
<input v-model="newLabel" v-on:keyup.enter="addNewLabel"> \
<ul> \
<li v-for="item in items" \
v-bind:class="{finished: item.isFinished}" \
v-on:click="finishState(item)" \
style="cursor:pointer"> \
{{ item.label }} \
</li> \
</ul> \
</div>',
methods: {
addNewLabel: function() {
this.items.push({
label: this.newLabel,
isFinished: false
});
this.newLabel = '';
},
finishState: function(item) {
item.isFinished = !item.isFinished;
}
},
watch: {}
})
(1)首先,一個組件的template
只能包含一個根標籤,本例是<div>
(2)template
的根標籤中包含三個子標籤:<h2>
、<input>
、<ul>
,分別表示標題、輸入待辦事項的輸入框、待辦事項列表
(3)data
部分新增兩個變量:newLabel
用於接收輸入的新的待辦事項,初始值爲空字符串;items
用於存儲當前已經輸入的所有待辦事項,初始值是一個空數組,數組的每一個元素都是一個json格式的數據,包括label
和isFinished
兩個字段
(4)下面重點解釋一下template
中的vue指令(可以參考官方文檔)
v-model="newLabel"
:表示<input>
輸入框中輸入的內容在回車後直接賦值給newLabel
v-on:keyup.enter="addNewLabel"
:表示當觸發回車鍵時,將會調用組件的methods
中定義好的addNewLabel
函數v-for="item in items"
:表示循環取出items
數組中的每一個元素item
,以列表的方式渲染item.label
的內容,如果數組爲空則不渲染<li>
標籤v-bind:class="{finished: item.isFinished}"
:根據雙引號中的表達式的布爾值決定是否使用class=finished
屬性(配合css使用)v-on:click="finishState(item)
:表示當觸發click事件時,將會調用組件的finishState(item)
函數
3.5 使用localStorage存儲待辦事項
window
對象表示瀏覽器的一個實例,它既是通過js訪問瀏覽器窗口的一個接口,又是ECMAScript規定的Global對象localStorage
是瀏覽器提供的一個本地存儲,其文件存放在瀏覽器目錄下的某個文件夾中,只要不去手動刪除它,每次刷新瀏覽器頁面這個文件都還是存在的,那麼我們就可以通過它存儲我們剛輸入的待辦事項localStorage
有兩個方法:setItem(文件名, 存儲內容)
用於設置保存內容到本地存儲,getItem(文件名)
用於提取本地存儲的內容//main.js const STORAGE_KEY = 'todo-list'; function initalItems() { return JSON.parse(window.localStorage.getItem(STORAGE_KEY) || '[]') } function saveItems(items) { window.localStorage.setItem(STORAGE_KEY, JSON.stringify(items)) } Vue.component('todo-body', { data: function() { return { title: 'This is a ToDoList', newLabel: '', items: initalItems() } }, template: '...', methods: {...}, watch: { items: { handler: function(items) { saveItems(items); }, deep: true } } })
這裏的代碼增加了兩個函數用於設置和提取本地存儲內容,並修改了vue組件中的兩個地方:
- 數據變量中的
items
的初始值不再是空數組,而是從本地瀏覽器中提取到的內容,如果提取不到則設爲空 watch
監聽items
變量的變化,只要items
發生變化,就會調用handler函數,將變化後的items
存儲到localStorage
,並且是深複製(類似於python的深複製機制)localStorage的內容可以在chrome瀏覽器中查看,如下圖所示:
這樣一來即使關掉瀏覽器本地存儲的內容也還會存在,再次打開使用瀏覽器打開該html時,依然能正確加載先前存儲好的待辦事項。如果想要清空,只需要選中localStorage下對應的html文件目錄,右鍵,
clear
即可
四、未解決問題記錄
main.js調用store.js中定義的函數:
//main.js
new_element = document.createElement("script");
new_element.setAttribute("type", "text/javascript");
new_element.setAttribute("src", "../src/store.js"); //引入store.js
document.body.appendChild(new_element);
然後出現了store.js中的函數能在main.js的vue組件中的watch
中調用,但不能在data
中調用的情況,報錯爲initialItems
未定義。
疑似與vue的生命週期有關,查閱一些資料可以使用created
或mounted
,似乎無法解決上述調用問題,因此直接將store.js的函數寫在main.js中了,仍未能解決js相互調用函數的vue渲染問題。