一 Vue2.x生命周期
每個vue實例再被創(chuàng)建時都要經(jīng)過一系列的初始化過程:
創(chuàng)建實例
裝載模板
渲染模板等等
vue為生命周期中的每個狀態(tài)都設置了鉤子函數(shù)(監(jiān)聽函數(shù))雏胃。每個vue實例處于不同的生命周期時街州,對應的函數(shù)就會觸發(fā)調用
https://www.cnblogs.com/L-xmin/p/13031773.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<div id="app">
<span id="num">{{num}}</span>
<button @click="num++">點贊</button><br>
{{name}},有{{num}}個點贊面徽!
</div>
</head>
<body>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
let vm=new Vue({
el:"#app",
data:{
name:"張三",
num:1
},
methods:{
show(){
return this.name
}
},
// 第一個生命周期函數(shù)霎匈,組件的data,methods球匕,DOM結構都還沒有初始化
beforeCreate() {
console.log("=========beforeCreate=============");
console.log("數(shù)據(jù)模型未加載: "+this.name,this.num); //undefined
console.log("方法未加載: "+this.show());
console.log("html模板未渲染: "+document.getElementById("num").innerText);
},
// 第二個生命周期函數(shù)乾忱,組件的data趟卸,methods已經(jīng)可以訪問到,但html模板尚未渲染,該函數(shù)中我們通常發(fā)送ajax請求
created(){
console.log("=========created=============");
console.log("數(shù)據(jù)模型已加載: "+this.name,this.num); //undefined
console.log("方法已加載: "+this.show());
console.log("html模板已加載:" + document.getElementById("num"));
console.log("html模板未渲染: "+document.getElementById("num").innerText);
},
// 第三個生命周期函數(shù),模板結構已經(jīng)在內(nèi)存中編譯完成,但還沒有渲染到頁面上,仍然無法獲得模板中的內(nèi)容寝凌,頁面看到的還是一個插值表達式
beforeMount() {
console.log("=========beforeMount=============");
console.log("html模板未渲染: "+document.getElementById("num").innerText);
},
// 組件創(chuàng)建階段的最后一個生命周期函數(shù)劫映,頁面真正被渲染了,用戶能看到真實頁面數(shù)據(jù)
mounted() {
console.log("=========mounted=============");
console.log("html模板已渲染: "+document.getElementById("num").innerText);
},
//更新部分的生命周期
beforeUpdate() {
console.log("=========beforeUpdate=============");
console.log("數(shù)據(jù)模型已更新:"+this.num);
console.log("html模板未更新:"+document.getElementById("num").innerText);
},
updated() {
console.log("=========updated=============");
console.log("數(shù)據(jù)模型已更新:"+this.num);
console.log("html模板已更新:"+document.getElementById("num").innerText);
},
})
</script>
</body>
</html>
創(chuàng)建部分的生命周期
beforeCreate
此時千诬,組件的data和methods以及頁面DOM結構都還沒有初始化
created
此時傲茄,組件的data和methods可用。但頁面還沒被渲染出來,在該函數(shù)中,我們經(jīng)常會發(fā)起ajax請求
beforeMount
此時枪孩,模板結構已經(jīng)在內(nèi)存中編譯完成嘹屯,但還沒有真正渲染到頁面上低零。頁面上看不到真實的數(shù)據(jù)潭陪,能看到的只是一個模板而已,仍然無法獲得模板中的內(nèi)容,仍然是一個插值表達式
mounted
組件創(chuàng)建階段的最后一個生命周期拜隧。此時,頁面已經(jīng)真正渲染好了,用戶可以看到真實頁面數(shù)據(jù)。
以上執(zhí)行完,組件就離開了創(chuàng)建階段,進入運行階段。如果用到了一些第三方UI插件,必須在mounted中來初始化插件已艰。
運行中的生命周期函數(shù)捆蜀,會根據(jù)data數(shù)據(jù)的變化有選擇性的觸發(fā)0次或n次
更新部分的生命周期
以后當每點一次贊,num就會變化,就會觸發(fā)下面的兩個鉤子函數(shù)
beforeUpdate
此時數(shù)據(jù)是最新的,但頁面上呈現(xiàn)的數(shù)據(jù)還是舊的
updated
頁面已經(jīng)完成了更新,此時data數(shù)據(jù)是最新的,同時頁面上呈現(xiàn)的數(shù)據(jù)也是最新的
beforeDestroy
執(zhí)行該函數(shù)的時候盈匾,組件即將被銷毀但還沒有真正銷毀,此時組件(data橱赠、methods等數(shù)據(jù)或方法)還可以正常用苏遥。
destroyed
組件完成銷毀教硫,組件廢了
二 使用Vue腳手架進行模塊化開發(fā)
我們實際在使用vue開發(fā)項目的時候锋玲,大多使用其模塊化的開發(fā)環(huán)境盾碗。我們?nèi)プ鲆粋€后臺管理系統(tǒng),也是通過其模塊化的開發(fā)環(huán)境搭建了一個單頁應用,我們會發(fā)現(xiàn)項目中實際上只有一個html頁面(index.html),其他所有的功能都是通過編寫vue相關的組件(.vue結尾的文件),來完成最后的功能
2.1 搭建模塊化環(huán)境測試
- 全局安裝webpack,webpack是一個項目打包工具。-g是指全局安裝
npm install webpack -g
- 全局安裝vue腳手架
npm install -g @vue/cli-init
- 初始化vue項目。vue腳手架使用webpack模塊初始化一個appname項目
vue init webpack appname
桌面創(chuàng)建項目文件夾名稱,如vue-demo髓梅,然后進入該文件夾鸭你,在文件路徑地址上輸入cmd愉老,回車就可以在當前目錄中打開cmd窗口咒林,在當前目錄執(zhí)行上面的命令
初始化的時候有幾項配置
項目名稱欢瞪,項目描述骑祟,作者抒巢,vue構建版本(使用standalone)崇堵,安裝vue-router赏廓,不適用eslint既忆,不使用單元測試苛吱,不安裝e2e tests彰亥,選擇npm為包管理工具
如果出現(xiàn)vue不是內(nèi)部或者外部命令等錯誤瘟檩,使用cnpm或者配置npm路徑環(huán)境變量
npm config list
然后打開上面的地址奏赘,查看是否有vue.cmd
如果一直處于downloading template然后最后超時報錯如下:
是因為github被墻了,無法訪問,解決方法:https://www.cnblogs.com/liufqiang/p/13697531.html,按照要求更改后可以正常初始化
- 啟動vue項目
上一步構建完后抡谐,再cd進入下一層目錄(vue-demo目錄下還有一層vue-demo免胃,需要進入第二層實際項目路徑)扼雏,執(zhí)行如下的命令來運行腳手架工程
npm run dev
項目的package.json中有scripts蝴蜓,代表我們能運行的命令
2.2 vue腳手架工程目錄介紹
在 vscode中打開vue-demo項目伯病,可以看到如下目錄
目錄/文件 | 作用 | 圖片 |
---|---|---|
build | 與打包工具webpack有關的代碼 | |
config | 主要是一些配置信息,如項目訪問端口號 | |
node_modules | 使用npm install 給項目安裝的所有依賴 | |
src | 這里是我們要開發(fā)的目錄我碟,基本上要做的事情都在這個目錄里 | |
static | 靜態(tài)資源文件,如圖片,字體 | |
index.html | 首頁內(nèi)容,只有一個id為app的div | |
package.json | npm安裝的依賴包的信息丸卷,我們每安裝一個依賴沐兰,在package.json中都會有devDependencies依賴聲明插佛,包括它在哪里下載谢床,它的版本號是多少渡讼,都有 |
src里面包含了幾個目錄及文件:
- assets: 放置一些圖片蹬昌,如logo等
- components: 目錄里面放了一個組件文件明刷,可以不用
- App.vue: 項目入口文件挤聘,我們也可以直接將組件寫這里添怔,而不使用 components 目錄
- main.js: 項目的核心文件
總結:一句話艾杏,開發(fā)期間關注src里面的代碼以及src里面編寫相應的功能
2.3 vue腳手架項目運行流程
- index.html
聲明簡單的id為 app 的div給 vue 掛載 - src下的main.js主程序
主程序中引入了 vue、App 和 router 模塊, 創(chuàng)建了一個 Vue實例,并把 App.vue 模板的內(nèi)容掛載到 index.html 的 id 為 app 的 div 標簽下颠印, 并綁定了一個路由配置
- App.vue
上面 main.js 把 App.vue 模板的內(nèi)容沽翔,放置在了 index.html 的 div 標簽下面窗轩。查看 App.vue 的內(nèi)容我們看到堤舒,這個頁面的內(nèi)容由一個 logo 和一個待放置內(nèi)容的 router-view国撵,router-view 的內(nèi)容將由 router 配置決定 - router下的index.js
查看 route 目錄下的 index.js,我們發(fā)現(xiàn)這里配置了一個路由, 在訪問路徑 / 的時候, 會把 HelloWorld 模板的內(nèi)容放置到上面的 router-view中
如果我們自定義了一個Hello路由,那么我們訪問/hello的時候,會把Hello 模板的內(nèi)容放置到上面的router-view中刻蚯,即:如果不需要首頁a標簽跳轉讨便,只是輸入地址訪問的話疆瑰,直接改路由即可
關于APP.vue文件:可以發(fā)現(xiàn)內(nèi)容分為3個部分,
- template(模板,頁面要顯示成什么)劲适,
- script(vue實例的methods,data等),
- style(當前template的樣式)诫钓。這是一個標準的vue單文件組件
https://cn.vuejs.org/v2/guide/single-file-components.html
模塊化開發(fā)的時候场梆,我們會寫大量的.vue的單模塊組件,格式就是上面的3個部分
上面的router-view是路由視圖的意思搓逾,意思是當前頁面上面顯示的是圖片污淋,下面顯示什么,要根據(jù)我們訪問路徑動態(tài)決定。默認是/*/
(url哈希的訪問方式) 心铃,所以這個是一個動態(tài)的視圖唆铐,* 后的/是默認要顯示的視圖
訪問/的定義在route目錄的index.js中,訪問/,會使用我們名稱為HelloWorld的組件癞松,而Helloworld組件從哪來枫甲,我們從下圖可以看到也是從外面導入的
導入Helloworld的from后面有個@符號食店,@符號代表當前src整個目錄的根目錄用踩,然后從src下面的components下找HelloWorld.vue
如果我們想自己編寫一個Hello.vue組件,來訪問,我們同樣在components目錄下編寫Hello.vue呀页,編寫3要素,template谍咆,script旦签,style
<template>
<div>
<h1>你好啊,hello,{{name}}</h1>
</div>
</template>
<script>
// 導出vue實例蕾羊,推薦data寫函數(shù)的方式,return 一個對象,對象有個name值
export default {
data(){
return {
name:"周杰倫"
}
}
}
</script>
<style></style>
組件寫好以后日丹,要想使用,而且是路徑/hello使用谈秫,那么接下來我們需要編寫路由,在main.js中拇囊,我們可以看到導入的路由都在router目錄下,因此我們在router目錄下的index.js中添加一個路由path指向訪問地址啤覆,name是訪問path的地址,要展示哪個組件苍苞,使用之前都得先導入
import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'
import Hello from '@/components/Hello'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: 'HelloWorld',
component: HelloWorld
},
{
path:'/hello',
name:'Hello',
component:Hello
}
]
})
然后保存涛癌,我們訪問/hello路徑
然后我們再訪問/岸裙,會發(fā)現(xiàn)又變回了helloworld組件翅楼,而我們可以發(fā)現(xiàn)上面的圖片不變,原因就是因為訪問不同的組件只會改變路由視圖的部分求厕,不會改變路由視圖上面的圖片
我們?nèi)绻朦c擊一個超鏈接就去我們的hello組件沼沈,那么需要在App.vue中修改如下
app.vue只有路由視圖可以變呻袭,上面的圖片是不會變的
三 使用Vue整合element-ui
element-ui是一個使用比較廣泛的vue組件庫纷纫,幫我們抽取了常用的如單選框,輸入框妓盲,按鈕之類的各種組件,可以簡化我們的開發(fā)
3.1 npm安裝與引入
- 安裝elementUI:i是install的簡寫
npm i element-ui
- 安裝完后策州,在我們vue-demo項目的package.json中的依賴列表會列出剛剛安裝的element-ui,可以看到是2.15.6版本
然后,我們在main.js主程序中將element-ui組件以及它的css樣式導入
因為我們引入了,所以我們可以直接導入绿满,類似于java中pom文件添加完依賴,就可以直接import進去
最后我們需要讓vue使用我們的element-ui組件,添加一行代碼Vue.use
未來我們需要用到其他組件庫摊阀,也是在main.js中采用上述方法導入使用
3.2 使用element-ui組件
3.2.1 簡單引入
我們在我們之前編寫的Hello.vue組件中使用Elementui灵临,添加一個單選框,單選框組件代碼復制下面鏈接的文檔 https://element.eleme.cn/#/zh-CN/component/installation
el-radio其實本質上就是elementUI抽取的組件,之前不是學過組件化么,等于以前我們要自己做很多設定,現(xiàn)在elementUI幫我們做好了
要使用 Radio 組件巡扇,只需要設置v-model綁定變量顽分,選中意味著變量的值為相應 Radio label屬性的值仇箱,label可以是String县恕、Number或Boolean。
如上文檔所示剂桥,我們修改Hello.vue組件內(nèi)容,添加單選框属提,label就是單選框的value值权逗,通過data中設置radio值來默認讓某個選中
// 0. 如果使用模塊化機制編程,導入 Vue 和 VueRouter冤议,要調用 Vue.use(VueRouter)
// 1. 定義(路由)組件斟薇。
// 可以從其他文件 import 進來
const Foo = { template: '<div>foo</div>' }
const Bar = { template: '<div>bar</div>' }
// 2. 定義路由
// 每個路由應該映射一個組件。 其中"component" 可以是
// 通過 Vue.extend() 創(chuàng)建的組件構造器恕酸,
// 或者堪滨,只是一個組件配置對象。
// 我們晚點再討論嵌套路由蕊温。
const routes = [
{ path: '/foo', component: Foo },
{ path: '/bar', component: Bar }
]
// 3. 創(chuàng)建 router 實例袱箱,然后傳 `routes` 配置
// 你還可以傳別的配置參數(shù), 不過先這么簡單著吧。
const router = new VueRouter({
routes // (縮寫)相當于 routes: routes
})
// 4. 創(chuàng)建和掛載根實例义矛。
// 記得要通過 router 配置參數(shù)注入路由发笔,
// 從而讓整個應用都有路由功能
const app = new Vue({
router
}).$mount('#app')
// 現(xiàn)在,應用已經(jīng)啟動了凉翻!
3.2 簡單后臺管理界面
https://element.eleme.cn/#/zh-CN/component/container
在elementui官方文檔的基本組件中選擇container布局容器了讨,elementui幫我們寫好了常見的幾個頁面布局,我們使用如下的布局,分左右上三部分
復制template部分代碼到App.vue里面前计,因為頁面一進來就是index.html頁面胞谭,是一個id為app的div,在main.js中配置了在這個div里面加載App.vue組件男杈,相當于一進來就展示的是App.vue的template部分韭赘,因此我們將App.vue的template部分完全替換
然后將scripts部分的代碼和style部分的代碼復制并覆蓋之前的App.vue的script和style中的代碼
data就是v-bind:data的縮寫,也就是它綁定了一個自定義屬性data势就,這個data的值關聯(lián)export default {data}中的data泉瞻,這個data函數(shù),返回了一個對象苞冯,對象中有個屬性tableData數(shù)組
然后每一列el-table-column使用prop指定取出數(shù)組中每一個對象的哪個元素的值作為顯示袖牙,label就是表頭顯示的字
當el-table元素中注入data對象數(shù)組后,在el-table-column中用prop屬性來對應對象中的鍵名即可填入數(shù)據(jù)舅锄,用label屬性來定義表格的列名鞭达。可以使用width屬性來定義列寬
修改完后皇忿,再次訪問畴蹭,發(fā)現(xiàn)效果如下:
我們下面去實現(xiàn)點擊左側的選項1,右邊顯示默認給的用戶列表鳍烁,點擊選項2叨襟,右邊顯示hello組件的內(nèi)容
通過修改el-main標簽,el-main就是右邊的內(nèi)容區(qū)幔荒,是需要根據(jù)路徑的不同顯示不同的內(nèi)容糊闽,因此我們需要將它抽取出來。首先注釋掉表格部分內(nèi)容爹梁,然后改為如下
然后將表格部分內(nèi)容抽取為一個組件右犹,叫做MyTable組件,MyTable.vue文件
后來我們要經(jīng)常編寫vue組件,自己每次都寫template姚垃,script念链,style這3部分太麻煩了,可以快捷的讓vscode給我們生成這樣一個模板
很簡單:創(chuàng)建vue對應的代碼片段积糯,可以幫我們快速的生成vue模板
vue.json
文件–首選項–用戶代碼片段–新建代碼片段–取名vue.json
// https://www.cnblogs.com/songjilong/p/12635448.html
{
"Print to console": {
"prefix": "vue",
"body": [
"<!-- $1 -->",
"<template>",
"<div class='$2'>$5</div>",
"</template>",
"",
"<script>",
"http://這里可以導入其他文件(比如:組件掂墓,工具js,第三方插件js絮宁,json文件梆暮,圖片文件等等)",
"http://例如:import 《組件名稱》 from '《組件路徑》';",
"",
"export default {",
"http://import引入的組件需要注入到對象中才能使用",
"components: {},",
"data() {",
"http://這里存放數(shù)據(jù)",
"return {",
"",
"};",
"},",
"http://監(jiān)聽屬性 類似于data概念",
"computed: {},",
"http://監(jiān)控data中的數(shù)據(jù)變化",
"watch: {},",
"http://方法集合",
"methods: {",
"",
"},",
"http://生命周期 - 創(chuàng)建完成(可以訪問當前this實例)",
"created() {",
"",
"},",
"http://生命周期 - 掛載完成(可以訪問DOM元素)",
"mounted() {",
"",
"},",
"beforeCreate() {}, //生命周期 - 創(chuàng)建之前",
"beforeMount() {}, //生命周期 - 掛載之前",
"beforeUpdate() {}, //生命周期 - 更新之前",
"updated() {}, //生命周期 - 更新之后",
"beforeDestroy() {}, //生命周期 - 銷毀之前",
"destroyed() {}, //生命周期 - 銷毀完成",
"activated() {}, //如果頁面有keep-alive緩存功能,這個函數(shù)會觸發(fā)",
"}",
"</script>",
"<style scoped>",
(這一行復制的時候需要刪掉) "http://@import url($3); 引入公共css類",
"$4",
"</style>"
],
"description": "生成vue模板"
},
"http-get請求": {
"prefix": "httpget",
"body": [
"this.\\$http({",
"url: this.\\$http.adornUrl(''),",
"method: 'get',",
"params: this.\\$http.adornParams({})",
"}).then(({ data }) => {",
"})"
],
"description": "httpGET請求"
},
"http-post請求": {
"prefix": "httppost",
"body": [
"this.\\$http({",
"url: this.\\$http.adornUrl(''),",
"method: 'post',",
"data: this.\\$http.adornData(data, false)",
"}).then(({ data }) => { });"
],
"description": "httpPOST請求"
}
}
然后以后我們寫一個vue绍昂,就會快捷的幫我們提示生成全部的3部分內(nèi)容
<template>
<div>
<el-table :data="tableData">
<el-table-column prop="date" label="日期" width="140">
</el-table-column>
<el-table-column prop="name" label="姓名" width="120">
</el-table-column>
<el-table-column prop="address" label="地址">
</el-table-column>
</el-table>
</div>
</template>
<script>
export default {
data() {
const item = {
date: '2016-05-02',
name: '王小虎',
address: '上海市普陀區(qū)金沙江路 1518 弄'
};
return {
tableData: Array(20).fill(item)
}
}
};
</script>
然后修改路由啦粹,通過點擊左側連接偿荷,右邊內(nèi)容頁顯示具體內(nèi)容。
左邊點擊選項1唠椭,發(fā)送table請求跳纳,點擊選項2,發(fā)送hello請求
修改router目錄下的index.js文件贪嫂,增加路由:
import MyTable from '@/components/MyTable'
{
path: '/table',
name: 'MyTable',
component: MyTable
}
然后修改導航一種分組一的選項1和選項2的index并且開發(fā)menu的屬性router為true
然后再次點擊左側導航1的分組一的選項1和選項2可以看到正確的跳轉了