vue 學(xué)習(xí)
1. 組件基礎(chǔ)
1.1 什么是組件
組件是可以服用的 vue 實(shí)例坎背,說(shuō)白了是一組可以重復(fù)使用的模板。組件里面可以套用組件。
//定義組件
//使用Vue.component來(lái)定義組件
Vue.component("my-component-li",{
template: "<li>這是一個(gè)名為my-component-li的組件</li>"
})
//組件定義好了钮孵,引用組件
<div>
<ul>
<my-component-li v-for="item in items" v-bind:item="item"></my-component-li> //1
</ul>
</div>
//但是上面的方法只是把li 顯示出來(lái)戈泼,一般li 是需要做列表渲染的婿禽,也就是要把數(shù)據(jù)傳進(jìn)去的,所以需要做一些改動(dòng)
//1.要把data數(shù)據(jù)里的數(shù)組渲染到 li 里大猛,先給 li 組件綁定 v-for 循環(huán)扭倾。
//2.然后把 item替換到li里
<script>
//定義組件
Vue.component("my-component-li",{
props:["item"],//這里是把 template 里的 item 關(guān)聯(lián)上了,為了把item 跟<my-component-li v-for="item in items"></my-component-li> 這里的 item 關(guān)聯(lián)挽绩,需要用到 v-bind:item 方法
template:"<li>{{item}}</li>"http://2
})
var app = new Vue({
//掛載元素
el:"#app",
data:{
items:['衛(wèi)青','霍去病','張騫']
}
})
</script>
2. 前端膛壹,服務(wù)器和數(shù)據(jù)庫(kù)
[圖片上傳失敗...(image-3a922-1656668459121)]
解釋:前端可以是 vue 等框架,服務(wù)器可以是由 node 搭建的也可以是 node 的框架 express唉堪,數(shù)據(jù)庫(kù)使用 MySQL
3 vue 從零開(kāi)始一個(gè)項(xiàng)目
3.1 安裝 vue
安裝 vue 的方法有四種
-
在頁(yè)面上以 CDN 引入
<script src="https://unpkg.com/vue@next"></script>
-
下載 javascript 文件并自行托管
即下載 vue 的 .js 文件然后放到自己的工程文件中模聋,然后在項(xiàng)目中去引用。
-
使用 npm 安裝它
npm 為你和你的團(tuán)隊(duì)打開(kāi)了連接整個(gè) JavaScript 天才世界的一扇大門(mén)唠亚。它是世界上最大的軟件注冊(cè)表链方,每星期大約有 30 億次的下載量,包含超過(guò) 600000 個(gè) 包(package) (即代碼模塊)灶搜。來(lái)自各大洲的開(kāi)源軟件開(kāi)發(fā)者使用 npm 互相分享和借鑒祟蚀。包的結(jié)構(gòu)使您能夠輕松跟蹤依賴項(xiàng)和版本工窍。 下面是關(guān)于 npm 的快速介紹: npm 由三個(gè)獨(dú)立的部分組成: 網(wǎng)站 注冊(cè)表(registry) 命令行工具 (CLI) 網(wǎng)站 是開(kāi)發(fā)者查找包(package)、設(shè)置參數(shù)以及管理 npm 使用體驗(yàn)的主要途徑前酿。 注冊(cè)表 是一個(gè)巨大的數(shù)據(jù)庫(kù)患雏,保存了每個(gè)包(package)的信息。 CLI 通過(guò)命令行或終端運(yùn)行薪者。開(kāi)發(fā)者通過(guò) CLI 與 npm 打交道纵苛。
-
使用 vue 腳手架 CLI 來(lái)構(gòu)建它。推薦使用 vue 腳手架言津。
Vue 提供了一個(gè)官方的 CLI攻人,為單頁(yè)面應(yīng)用 (SPA) 快速搭建繁雜的腳手架。它為現(xiàn)代前端工作流提供了功能齊備的構(gòu)建設(shè)置悬槽。只需要幾分鐘的時(shí)間就可以運(yùn)行起來(lái)并帶有熱重載怀吻、保存時(shí) lint 校驗(yàn),以及生產(chǎn)環(huán)境可用的構(gòu)建版本初婆。更多詳情可查閱 Vue CLI 的文檔
3.1.1 使用 vue-cli 創(chuàng)建項(xiàng)目
安裝 node.js 使用 vue-cli 必須先安裝 node
-
安裝 vue cli
npm install -g @vue/cli
-
創(chuàng)建項(xiàng)目名
vue create 項(xiàng)目名
根據(jù)提示進(jìn)行選擇
ps. 因?yàn)?npm 的包的下載速度很慢蓬坡,可以使用淘寶的鏡像資源 cnpm 來(lái)加快速度:
npm install -g cnpm --registry=https://registry.npm.taobao.org
使用 npm 去安裝 cnpm
當(dāng)項(xiàng)目使用 vue create 項(xiàng)目名并且選擇配置完成以后會(huì)自動(dòng)生成一些文件
cd 項(xiàng)目名 // 進(jìn)入項(xiàng)目中
npm run serve 啟動(dòng)項(xiàng)目
App running at:
- Local: http://localhost:8080/
- Network: http://192.168.31.146:8080/
即項(xiàng)目啟動(dòng)成功
[圖片上傳失敗...(image-974b78-1656668459121)]
[圖片上傳失敗...(image-27abf5-1656668459121)]
方法和計(jì)算屬性
方法定義在
methods(){
方法體
}
computed:{
計(jì)算屬性
}
兩個(gè)使用中非常相似,不同點(diǎn)是計(jì)算屬性是靜態(tài)的磅叛。相當(dāng)于把計(jì)算結(jié)果緩存起來(lái)成為靜態(tài)的屬性屑咳,避免系統(tǒng)開(kāi)銷
4. mysql
mysql 環(huán)境變量配置了以后可以直接用 cmd 去啟動(dòng) mysql
mysql -uroot -p
//連接的命令
如果不配置環(huán)境變量,則每次需要進(jìn)入到 mysql 的安裝文件的bin目錄的去啟動(dòng)弊琴,本機(jī)的安裝目錄是 C:\Program Files\MySQL\MySQL Server 8.0\bin
即兆龙,如果沒(méi)有配置環(huán)境變量,則需要在 cmd 中輸入 cd C:\Program Files\MySQL\MySQL Server 8.0\bin 進(jìn)入到這個(gè)目錄中再鏈接數(shù)據(jù)庫(kù)敲董。
本數(shù)據(jù)庫(kù)的賬戶密碼都是 root
5. node.js
5.1 創(chuàng)建一個(gè)經(jīng)典的服務(wù)器
創(chuàng)建空文件夾 nodejsdemo
初始化 npm init
在文件目錄中看到主入口文件是 index.js, 所以創(chuàng)建 index.js
[圖片上傳失敗...(image-1d4eff-1656668459121)]
在 index.js 中寫(xiě)入 console.log(1234), 終端輸入node index.js 運(yùn)行輸出 1234說(shuō)明 node 運(yùn)行了 index.js
-
這樣一個(gè)簡(jiǎn)單的服務(wù)器就做好了
// setServers const http = require("http"); // require 引入模塊的方法紫皇,http 是一個(gè)默認(rèn)的模塊,所以可以直接寫(xiě)不用再?gòu)牡谌揭?const hostname = "127.0.0.1"; //定義本地地址(服務(wù)器地址) const port = 3000; //定義端口號(hào) //http有createServer 方法(接受參數(shù)腋寨,req 為請(qǐng)求參數(shù)聪铺,res 為響應(yīng)參數(shù)) var server = http.createServer((req,res)=>{ res.statusCode = 200; res.setHeader("Content-type","text/plain") res.write("hello node") res.end() }); //server 啟動(dòng)以后使用listion 方法去看是否啟動(dòng)成功 server.listen(port, hostname, ()=>{ console.log("服務(wù)器已啟動(dòng)"); })
- nodemon 自動(dòng)重新啟動(dòng)項(xiàng)目
- 先全局安裝 npm i nodemon -g
- 然后在 package.json 文件里添加 “serve”:nodemon index.js
5.2 node中的 http 模塊
-
http 服務(wù)端
在服務(wù)端使用
請(qǐng)求對(duì)象(IncomingMessage類的實(shí)例)和相應(yīng)對(duì)象(ServerResponse類的實(shí)例)
-
http客戶端
- 客戶端使用(request, get)
- 請(qǐng)求對(duì)象(ClientRequest類的實(shí)例)和相應(yīng)對(duì)象(IncomingMessage類的實(shí)例)
5.3 node 的其他模塊(看文檔)
- Buffer 模塊
- url 模塊
- fs 模塊
- crypto模塊
- path模塊
- 模板引擎
- nodemon 自動(dòng)重新啟動(dòng)項(xiàng)目
6. express.js
基于 node.js 的極簡(jiǎn),快速萄窜,開(kāi)放的 web 開(kāi)發(fā)框架铃剔。exprss 和 node 的關(guān)系就如同 jQuery 和 js 的關(guān)系。
6.1 express 安裝
npm init 初始化文件
-
安裝 express 并將其保存在依賴列表中
npm install express //因?yàn)閑xpress 是第三方的庫(kù)查刻,所以要安裝才能使用
-
安裝完成進(jìn)入 hello wold 頁(yè)面
const express = require("express"); //引入express模塊 var app=express(); //express 函數(shù)運(yùn)行以后賦值給 app键兜。 app 即是應(yīng)用對(duì)象 //使用get方法 app.get("/",function(req,res){ res.send("hello express") }) //使用 liston方法監(jiān)聽(tīng) app.listen(3000,function(){ console.log("運(yùn)行環(huán)境") })
代碼賦值到 index.js(如果在 package.jason文件中改了入口文件,那么就需要運(yùn)行改動(dòng)后的文件赖阻。index.js 是默認(rèn)的入口文件), node 運(yùn)行 index.js
瀏覽器中運(yùn)行 localhost:3000
6.2 請(qǐng)求本地的 json 數(shù)據(jù)
module.expors={
"name":"zhangsan",
"age":20
}
//module.exports 意思是當(dāng)我們創(chuàng)建了一個(gè) data的js 文件以后蝶押,我們要把這個(gè)文件暴露出去,這樣別的程序可以訪問(wèn)的到
6.3 靜態(tài)資源
為了提供如圖片火欧,js棋电,css文件之類的靜態(tài)資源茎截,使用 express 中的中間件 express.static.
例如,圖片放在 static 文件加下面赶盔,我們?nèi)绻褂眠@些靜態(tài)資源則使用
app.use(express.static("static"))企锌,那么 static 文件夾里的文件就對(duì)外開(kāi)放了。
app.use(express.static("",))
6.4 路由
路由的目的于未,上面的所有g(shù)et/put/path等接口都寫(xiě)在了主文件 mian.js里撕攒,這樣太亂了,為了把這些接口函數(shù)放到一個(gè)專門(mén)的地方烘浦,所以引入了路由的概念抖坪。
- 創(chuàng)建一個(gè)文件夾 route
- 在文件夾里創(chuàng)建文件 index.js 文件
7. 鏈接 mysql
-
現(xiàn)在終端安裝mysql
npm install mysql
在路由文件去引入 mysql
var mysql = require(mysql)
8. dos 命令
- cd xx 進(jìn)入到哪個(gè)文件
- cd ../ or cd.. 進(jìn)入上一個(gè)文件夾
- cls 清除
實(shí)戰(zhàn)項(xiàng)目
安裝 node 搭建后臺(tái) (略)
-
搭建后臺(tái)項(xiàng)目
1. cmd 輸入 npm init 初始化項(xiàng)目。 (npm init -y 快速初始化項(xiàng)目) 2. 初始化成功后將在項(xiàng)目里出現(xiàn) package.json 文件 3. 創(chuàng)建與入口文件同名的文件js 4. 新增項(xiàng)目啟動(dòng)命令 5. nodemon: 自動(dòng)重啟項(xiàng)目當(dāng)code內(nèi)容改變以后 npm i nodemon -g 然后在 package.json 文件里添加 “serve”:nodemon index.js
-
package.json 字段解釋
"dependencies": 項(xiàng)目依賴 "devDependencies":開(kāi)發(fā)依賴(只在開(kāi)發(fā)的時(shí)候會(huì)用闷叉,項(xiàng)目打包上線的時(shí)候擦俐,這個(gè)部分不會(huì)被打包) "name": "expressdemo", 項(xiàng)目名稱 "version": "1.0.0", 項(xiàng)目版本 "description": "", 項(xiàng)目描述 "main": "main.js" 項(xiàng)目的入口文件
如果 npm 比較滿,安裝一下淘寶鏡像 cnpm
-
安裝并使用 koa + koa-router
koa 基于 node.js 的下一代 web 開(kāi)發(fā)框架握侧。
koa 是新的框架由 express 原班人馬打造蚯瞧,致力于成為 web 應(yīng)用和 api 開(kāi)發(fā)的更小的,更富有表現(xiàn)力的基石品擎。
koa 建立在 es6+ 之上埋合,提升現(xiàn)代的 js 語(yǔ)法。
使用 generators 和 async / await
優(yōu)雅萄传,簡(jiǎn)潔甚颂,靈活,體積小
相關(guān)名利 npm - koa -s, npm - koa-router -s
//入口文件的基本設(shè)置
//1. 引入 koa
const Koa = require("koa");
//2. 實(shí)例化 koa
const App = new Koa();
//3. 搭建服務(wù)
App.use(async ctx=>{
ctx.body = "荊承鵬學(xué)習(xí)前端";
})
//4. 監(jiān)聽(tīng)端口
App.listen(5000, ()=>{
console.log("服務(wù)器啟動(dòng)成功:5000")
})
// nodemon index.js 啟動(dòng)服務(wù) http://localhost:5000 可以訪問(wèn)
// 這個(gè)時(shí)候有個(gè)問(wèn)題盲再,上面的無(wú)法指定特定的 api 端口西设,比如 http://localhost:5000/index瓣铣, http://localhost:5000/index1 是不同的路徑答朋,這個(gè)時(shí)候就需要 koa-router
// 安裝 koa-router : npm i koa-router -s
-
引入 koa-router 以后需要做的
//1. 引入 koa const Koa = require("koa"); const Router = require("koa-router"); //2. 實(shí)例化 koa const App = new Koa(); const router = new Router(); //3. 搭建服務(wù) // App.use(async ctx=>{ // ctx.body = "荊承鵬學(xué)習(xí)前端"; // }) // 使用 koa-router 來(lái)啟動(dòng)服務(wù),并且可以指定不同的路徑 router.get("/index", async ctx=>{ ctx.status = 200; ctx.body = "荊承鵬學(xué)習(xí)前端koa-router"; }) router.get("/index1", async ctx=>{ ctx.status = 200; ctx.body = "月薪過(guò)萬(wàn)不是夢(mèng)" }) //配置路由 // 調(diào)用router.routes()來(lái)組裝匹配好的路由棠笑,返回一個(gè)合并好的中間件 // 調(diào)用router.allowedMethods()獲得一個(gè)中間件梦碗,當(dāng)發(fā)送了不符合的請(qǐng)求時(shí),會(huì)返回 `405 Method Not Allowed` 或 `501 Not Implemented` App.use(router.routes()); App.use(router.allowedMethods()); //4. 監(jiān)聽(tīng)端口 App.listen(5000, ()=>{ console.log("服務(wù)器啟動(dòng)成功:5000") })
搭建數(shù)據(jù)庫(kù)環(huán)境 (安裝 mysql 略)
安裝 Navicat premium (mysql 的圖形管理系統(tǒng))
-
編寫(xiě)后臺(tái)接口
使用 node 連接 sql 數(shù)據(jù)庫(kù) 安裝依賴 數(shù)據(jù)庫(kù) npm i mysql -s 跨域 npm i koa2-cors -s 獲取body 請(qǐng)求參數(shù) npm i koa-bodyparser -s 封裝 bd.js: 對(duì)鏈接數(shù)據(jù)庫(kù)的函數(shù)進(jìn)行模塊封裝 編寫(xiě)接口:接口 koa-router+mysql編寫(xiě)接口 測(cè)試接口:使用 vscode 中postman 插件進(jìn)行接口測(cè)試
bd.js 內(nèi)容 // 引入 bd.js 作為數(shù)據(jù)庫(kù)的鏈接文件 // 引入 mysql const mysql = require("mysql"); //聲明變量用來(lái)存儲(chǔ)數(shù)據(jù)庫(kù)綁定連接以后的對(duì)象屬性 const poolSql = mysql.createPool({ host: "localhost", user:"root", password:"root", port: "3306", database:"test" }) function query(sql, value){ return new Promise((resolve,reject)=>{ poolSql.query(sql,value, (err,result)=>{ if(err){ reject(err) }else{ resolve(result) } }) }) } module.exports = query;
入口頁(yè)面 index.js 內(nèi)容
//1. 引入 koa const Koa = require("koa"); const Router = require("koa-router"); const Pool = require("mysql/lib/Pool"); //引入bd.js 里的模塊 const poopSql = require("./bd.js"); const cors = require("koa2-cors"); //跨域 const bodyparser = require("koa-bodyparser");//body 參數(shù) //2. 實(shí)例化 koa const App = new Koa(); const router = new Router(); //3. 搭建服務(wù) // App.use(async ctx=>{ // ctx.body = "荊承鵬學(xué)習(xí)前端"; // }) // 使用 koa-router 來(lái)啟動(dòng)服務(wù)蓖救,并且可以指定不同的路徑 router.get("/index", async ctx=>{ ctx.status = 200; ctx.body = "荊承鵬學(xué)習(xí)前端koa-router"; }) router.get("/query", async ctx=>{ ctx.status = 200; try { let _sql = "SELECT * FROM t_user"; let _data = await poopSql(_sql); ctx.body = { errorMessage : "", result:true, data: _data } } catch (error) { ctx.body = { errorMessage : "查詢失敗", result:false, data: null } } }) //配置路由 // 調(diào)用router.routes()來(lái)組裝匹配好的路由洪规,返回一個(gè)合并好的中間件 // 調(diào)用router.allowedMethods()獲得一個(gè)中間件,當(dāng)發(fā)送了不符合的請(qǐng)求時(shí)循捺,會(huì)返回 `405 Method Not Allowed` 或 `501 Not Implemented` App.use(router.routes()); App.use(router.allowedMethods()); App.use(cors()); App.use(bodyparser()); //4. 監(jiān)聽(tīng)端口 App.listen(5000, ()=>{ console.log("服務(wù)器啟動(dòng)成功:5000") })
-
查詢斩例,添加,修改从橘,刪除數(shù)據(jù)庫(kù)字段的寫(xiě)法
// bd.js //1. 引入 koa const Koa = require("koa"); const bodyparser = require("koa-bodyparser");//body 參數(shù) const Router = require("koa-router"); const Pool = require("mysql/lib/Pool"); //引入bd.js 里的模塊 const poolSql = require("./bd.js"); const cors = require("koa2-cors"); //跨域 //2. 實(shí)例化 koa const App = new Koa(); const router = new Router(); //3. 搭建服務(wù) // App.use(async ctx=>{ // ctx.body = "荊承鵬學(xué)習(xí)前端"; // }) // 使用 koa-router 來(lái)啟動(dòng)服務(wù)念赶,并且可以指定不同的路徑 router.get("/index", async ctx => { ctx.status = 200; ctx.body = "荊承鵬學(xué)習(xí)前端koa-router"; }) //查詢數(shù)據(jù)庫(kù) router.get("/query", async ctx => { ctx.status = 200; try { let _sql = "SELECT * FROM t_user"; let _data = await poolSql(_sql); ctx.body = { errorMessage: "", result: true, data: _data } } catch (error) { ctx.body = { errorMessage: "查詢失敗", result: false, data: null } } }) //向數(shù)據(jù)庫(kù)表中添加信息 router.post("/add", async ctx => { ctx.status = 200; let _info = ctx.request.body; //上下文request 里的 body 的內(nèi)容賦給 _info //表中username 是必填項(xiàng)础钠,所以先判斷一下 if(!_info.name){ ctx.body = { errorMessage:"name 是必填項(xiàng)目", result:false, data:null } return } try { let _sql = "INSERT INTO demo (id,name,number,price) VALUES (?,?,?,?)"; let _value = [_info.id,_info.name, _info.number, _info.price]; await poolSql(_sql,_value); ctx.body = { errorMessage: "", result: true, data: null } } catch (error) { ctx.body = { errorMessage: "添加失敗", result: false, data: null } } }) //向數(shù)據(jù)庫(kù)表中修改信息 router.put("/put", async ctx=>{ ctx.status = 200; let _info = ctx.request.body; if(!_info.id){ ctx.body = { errorMessage:"id 是必填項(xiàng)目", result:false, data:null } return }else if(!_info.name){ ctx.body = { errorMessage:"name 是必填項(xiàng)目", result:false, data:null } return } try{ let _sql = "UPDATE demo SET name=?,number=?,price=? WHERE id=?"; let _value = [_info.name, _info.number, _info.price,_info.id]; await poolSql(_sql, _value); ctx.body = { errorMessage: "", result: true, data: null } }catch(err){ ctx.body = { errorMessage: "修改失敗", result: false, data: null } } }) //刪除數(shù)據(jù)庫(kù)中的數(shù)據(jù),通過(guò)路徑傳參的方式 router.delete("/delete/:id", async ctx=>{ ctx.status = 200; console.log(ctx); let _info = ctx.params; try{ let _sql = "DELETE FROM demo WHERE id=?"; let _value = [_info.id]; await poolSql(_sql,_value); ctx.body ={ errorMessage: "", result: true, data: null } }catch(err){ ctx.body = { errorMessage:"刪除錯(cuò)誤", result:false, data:null } } }) //配置路由 // 調(diào)用router.routes()來(lái)組裝匹配好的路由叉谜,返回一個(gè)合并好的中間件 // 調(diào)用router.allowedMethods()獲得一個(gè)中間件旗吁,當(dāng)發(fā)送了不符合的請(qǐng)求時(shí),會(huì)返回 `405 Method Not Allowed` 或 `501 Not Implemented` App.use(cors()).use(bodyparser()).use(router.routes()).use(router.allowedMethods()); //4. 監(jiān)聽(tīng)端口 App.listen(5000, () => { console.log("服務(wù)器啟動(dòng)成功:5000") })
-
搭建前端框架
使用 vue3 + vite 搭建項(xiàng)目
此步驟以前的都是服務(wù)器端的設(shè)置停局,項(xiàng)目里新建文件夾把服務(wù)器端的項(xiàng)目文件命名為 server 然后在這個(gè)項(xiàng)目里開(kāi)始搭建前端很钓。
$ npm create vite@latest // 快速搭建一個(gè)項(xiàng)目
Vue3 基礎(chǔ) api
- defineComponent 這是對(duì) setup 函數(shù)進(jìn)行封裝,返回 options 的對(duì)象董栽,主要就是為了服務(wù) ts 而存在的码倦。 - ref 接受一個(gè)內(nèi)部值返回一個(gè)響應(yīng)式可變的 ref 對(duì)象。 ref 對(duì)象具有指向內(nèi)部值的單個(gè) property.value - reactive 與 ref 類似锭碳,不同的是它用來(lái)定義更為復(fù)雜的數(shù)據(jù)類型 - toRefs 將響應(yīng)式對(duì)象轉(zhuǎn)為普通對(duì)象叹洲,其中結(jié)果對(duì)象的每個(gè) property 都指向原始對(duì)象對(duì)應(yīng)的 property 的 ref - toRaw 只是對(duì)原生數(shù)據(jù)進(jìn)行修改,不改變更新 ui 視圖 - setup 函數(shù) 這個(gè)函數(shù)主要是為了使用組合式 api工禾,使用setup函數(shù)時(shí)候运提,有兩個(gè)參數(shù) props: 可以從中獲取組件的 props 參數(shù),他是響應(yīng)式的闻葵,也就是傳入新的 prop 時(shí)候民泵,它被更新; context: context是一個(gè)普通的 JavaScript對(duì)象槽畔,暴露了其他可能在 setup 中有用的值栈妆。這些值就是之前 vue2中 this 上暴露的 property 屬性,比如 attrs, slots, emit 注意:在setup() 中, this 不是該活躍實(shí)例的引用厢钧。
引用 ant design vue
npm install ant-design-vue --save
當(dāng)前端界面完成鳞尔,開(kāi)始前端和聯(lián)調(diào)
使用 axios 封裝 api
axios 是一個(gè)基于 promise 的 http 庫(kù),可以在瀏覽器和node.js 中使用早直。
它符合現(xiàn)在的 mvvm 浪潮寥假。
vue筆記
1. vue 零碎的知識(shí)點(diǎn)
-Vue中有兩種數(shù)據(jù)綁定,v-band 和 v-module
1. 單向數(shù)據(jù)綁定 v-band:xxx 簡(jiǎn)寫(xiě):xxx; 數(shù)據(jù)只能從 data 流向頁(yè)面霞扬。
2. 雙向數(shù)據(jù)綁定 v-model:xxx 簡(jiǎn)寫(xiě)為 v-model = ""
- el 和 data 的兩種寫(xiě)法
- el的兩種寫(xiě)法
(1) new Vue 時(shí)候配置el 的屬性
(2)先創(chuàng)建實(shí)例子糕韧,然后通過(guò)$monunt("掛載") - data的兩種寫(xiě)法:對(duì)象式,函數(shù)式
(1)對(duì)象式 data:{
//寫(xiě)入data 的值喻圃,可以直接用在模板中
}
(2)函數(shù)式寫(xiě)法 data(){
return {
//寫(xiě)入data 的值萤彩,可以直接用在模板中
}
}
在實(shí)際的項(xiàng)目中,主要謝函數(shù)式
上面是這個(gè)的變形寫(xiě)法 data:function(){
return {
//寫(xiě)入data 的值斧拍,可以直接用在模板中
}
} - 一個(gè)重要的原則:由 Vue 管理的函數(shù)一定不要寫(xiě)箭頭函數(shù)雀扶,一旦寫(xiě)了箭頭函數(shù) this 的指向就不再是 Vue 了。
- el的兩種寫(xiě)法
2. mvvm 模型
MVVM 模型肆汹,細(xì)說(shuō)其實(shí)是 M-V-VM 模型
M (model:指的是 data 中的數(shù)據(jù))
V (view) 視圖:模板代碼愚墓,即顯示在頁(yè)面中的內(nèi)容
VM (ViewModel) 視圖模型窍侧,即 Vue 實(shí)例所做的事情
發(fā)現(xiàn):1: data 中所有數(shù)據(jù)都出現(xiàn)在了 vm 身上;vm身上所有屬性转绷,包括從原型鏈上繼承來(lái)的都可以直接使用在模板中直接使用伟件。
3. vue2 數(shù)據(jù)雙向綁定的原理
Object.defineProperty() 實(shí)現(xiàn)數(shù)據(jù)代理
- vue中的數(shù)據(jù)代理
通過(guò)vm對(duì)象來(lái)代理data對(duì)象中的屬性的操作(讀/寫(xiě)) - vue中的數(shù)據(jù)代理的好處
更加方便的操作data中的數(shù)據(jù) - 基本原理
- 通過(guò)Object.defineProperty()把data中的對(duì)象所有屬性添加到vm上。
- 為每個(gè)添加到vm的屬性议经,都指定一個(gè)getter/setter.
- 在getter/setter內(nèi)部去操作(讀/寫(xiě))data中對(duì)應(yīng)的的屬性
4. 事件處理
- 使用v-on:xxx或者@xxx綁定事件斧账,其中xxx是事件名稱;
- 事件回調(diào)需要配置在methods對(duì)象中煞肾,最終會(huì)在vm上咧织;
- methods中配置的函數(shù),不要用箭頭函數(shù)籍救,否則this就不是vm了习绢;
- methods中配置的函數(shù),都是被vue所管理的函數(shù)蝙昙,this的指向是vm或者組件實(shí)例對(duì)象闪萄;
- @lick="demo"和@lick="demo($event)"效果一致,但是后者可以傳參奇颠。
5. 事件修飾符
描述:就是修飾事件的
- prevent:阻止默認(rèn)事件(常用)
- stop:阻止事件冒泡(常用)
- once:事件只觸發(fā)一次(常用)
- capture:使用事件的捕獲模式
- self:只有event.target是當(dāng)前操作的元素時(shí)才觸發(fā)事件
- passive:事件的默認(rèn)行為立即執(zhí)行败去,不用等事件回調(diào)執(zhí)行完畢。
案例:@click.once="showMe",這個(gè)事件只執(zhí)行一次烈拒;@click.prevent="showMe"阻止事件的默認(rèn)行為圆裕,比如在 a 標(biāo)簽上添加此修飾符,在點(diǎn)擊a標(biāo)簽以后荆几,執(zhí)行showMe函數(shù)吓妆,a標(biāo)簽的跳轉(zhuǎn)行為不執(zhí)行。 - 修飾符可以連續(xù)寫(xiě)
6. 鍵盤(pán)事件
-
vue中常用的按鍵別名:
- 回車 => enter
- 刪除 => delete (捕獲刪除和退格鍵)
- 退出 => esc
- 空格 => space
- 換行 => tab
- 上 => up
- 下 => down
- 左 => left
- 右 => right
vue未提供別名的按鍵吨铸,可以使用按鍵原始的key值去綁定行拢,但是要注意轉(zhuǎn)換為kebab-case(短橫線命名)
-
系統(tǒng)修飾鍵(用法特殊):ctrl, alt, shift, meta
- 配合keyup使用:按下修飾鍵的同時(shí),再按其他鍵釋放后觸發(fā);
- 配合keydown使用:正常觸發(fā)事件焊傅。
也可以使用keycode去指定具體的案件(不推薦)
Vue.config.keycodes.自定義按鍵名 = 鍵碼剂陡,可以去定制按鍵別名狈涮。
案例:@keyup.enter="showMe" (鍵盤(pán)的按鍵輸入enter鍵狐胎,在按鍵升起的時(shí)候觸發(fā))「桠桑或者@keydown.enter="showMe" (鍵盤(pán)的按鍵輸入enter鍵握巢,在按鍵按下的時(shí)候觸發(fā))。
7. 內(nèi)置指令
v-bind:單向綁定解析表達(dá)式松却,可以簡(jiǎn)寫(xiě)為:xxx
v-model:雙向數(shù)據(jù)綁定
v-for:遍歷數(shù)據(jù)暴浦、對(duì)象溅话、字符串
v-on:綁定事件監(jiān)聽(tīng),簡(jiǎn)寫(xiě)為@xxx
v-if:條件渲染(動(dòng)態(tài)控制節(jié)點(diǎn)是否存在)
v-show:條件渲染(動(dòng)態(tài)控制節(jié)點(diǎn)是否展示)
v-else:條件渲染(動(dòng)態(tài)控制節(jié)點(diǎn)是否存在)
v-text:向所在節(jié)點(diǎn)中添加渲染文本內(nèi)容歌焦;與插值語(yǔ)法區(qū)別:v-text會(huì)替換掉節(jié)點(diǎn)中的內(nèi)容飞几,{{xxx}}則不會(huì)。
-
v-html
- 作用:向指定節(jié)點(diǎn)中渲染包含html結(jié)構(gòu)的內(nèi)容独撇;
- 與插值語(yǔ)法的區(qū)別:v-html會(huì)替換掉節(jié)點(diǎn)中所有的內(nèi)容屑墨,{{xxx}}不會(huì)
- 嚴(yán)重注意:v-html有安全性問(wèn)題。在網(wǎng)站上動(dòng)態(tài)渲染任意html是非常危險(xiǎn)的纷铣,容易導(dǎo)致xss攻擊
- 一定要在可信的內(nèi)容上使用v-html,永遠(yuǎn)不要用在用戶輸入上卵史。
-
v-once
- v-once所在節(jié)點(diǎn)在初次動(dòng)態(tài)渲染后,就視為靜態(tài)內(nèi)容了搜立。
- 以后數(shù)據(jù)的改變不會(huì)引起v-once所在結(jié)構(gòu)的更新以躯,可以用于優(yōu)化性能。
-
v-pre
- 跳過(guò)其所在節(jié)點(diǎn)的編譯過(guò)程
- 可用它跳過(guò)沒(méi)有使用指令語(yǔ)法啄踊,沒(méi)有使用插值語(yǔ)法的節(jié)點(diǎn)忧设,會(huì)加快編譯
v-cloak: v-cloak(沒(méi)有值)
- 本質(zhì)是一個(gè)特殊屬性,vue實(shí)例創(chuàng)建完畢并接管容器以后會(huì)刪除v-cloak的屬性
- 使用css配合v-cloak可以解決網(wǎng)速慢時(shí)頁(yè)面展示出插值語(yǔ)法的問(wèn)題颠通。
8. 自定義指令
- 定義語(yǔ)法
- 局部指令:
new Vue({
directives:{指令名稱:配置對(duì)象}
})
或者
new Vue({
directives:{指令名:回調(diào)函數(shù)}
})
- 全局指令
Vue.directive(指令名见转,配置對(duì)象)或者Vue.directive(指令名,回調(diào)函數(shù))
-
配置對(duì)象中的常用的三個(gè)回調(diào)
- .bind:指令與元素成功綁定是調(diào)用
- .inserted:指令所在元素被插入頁(yè)面時(shí)調(diào)用
- .updated:指令所在模板結(jié)構(gòu)被重新解析時(shí)調(diào)用
-
備注:
- 指令定義時(shí)不加v-蒜哀,但是使用時(shí)需要加v-
- 指令名如果是多個(gè)單詞斩箫,要使用連字符鏈接,不要用駝峰命名
9. 計(jì)算屬性
- 定義:要用的屬性不存在撵儿,需要通過(guò)已有屬性計(jì)算而來(lái)乘客。
- 原理:底層借助了Object.defineProperty()方法提供的getter和setter
- get函數(shù)什么時(shí)候執(zhí)行?
- 初次讀取的時(shí)候會(huì)運(yùn)行一次淀歇;
- 當(dāng)依賴的數(shù)據(jù)發(fā)生變化時(shí)會(huì)被再次調(diào)用易核。
- 優(yōu)勢(shì):與methods相比,內(nèi)部有緩存機(jī)制(復(fù)用)浪默,效率更高牡直,測(cè)試方便
- 備注:計(jì)算屬性會(huì)最終出現(xiàn)在 vm 上,直接讀取使用即可纳决;如果計(jì)算屬性要被修改碰逸,那必須寫(xiě)set函數(shù)去相應(yīng)修改,且set中要引起計(jì)算時(shí)依賴的數(shù)據(jù)發(fā)生改變阔加。
10. 監(jiān)視屬性 watch
- 當(dāng)被監(jiān)視的屬性發(fā)生變化時(shí)饵史,回調(diào)函數(shù)自動(dòng)調(diào)用,進(jìn)行相關(guān)操作。
- 監(jiān)視屬性必須存在胳喷,才能進(jìn)行監(jiān)視
- 監(jiān)視的兩種寫(xiě)法:
- new Vue 時(shí)傳入 watch 配置
- 通過(guò)vm.$watch("",{})監(jiān)視
11.條件渲染
- v-in
- 寫(xiě)法:v-if湃番、v-else-if,v-else
- 適用于切換頻率較低的場(chǎng)景
- 特點(diǎn):不展現(xiàn) dom節(jié)點(diǎn)。dom直接被移除
- 注意:v-if可以和v-else-if,v-else 一起使用吭露,但是要求結(jié)構(gòu)不能被打斷吠撮。
- v-show
- 寫(xiě)法:v-show
- 適用于切換場(chǎng)景較高的場(chǎng)景
- 不展示dom,但是dom被隱藏
- 備注:使用v-if時(shí)讲竿,元素可能無(wú)法獲取到纬向,而是用v-show的時(shí)候時(shí)可以獲取到的
12 v-for 指令
- 用于展示列表信息
- 語(yǔ)法:v-for="(item, index) in xxx" :key="yyy"
- 可以遍歷:數(shù)組,對(duì)象戴卜,字符串(用的少)逾条,指定次數(shù)(用的少)
12. 面試題 react,vue中key的作用(key的內(nèi)部原理)
- 虛擬 dom 中 key 的作用:key是虛擬dom對(duì)象的標(biāo)識(shí)投剥,當(dāng)數(shù)據(jù)發(fā)生變化時(shí)师脂,vue會(huì)根據(jù)新數(shù)據(jù)生成新的虛擬dom,隨后vue進(jìn)行新虛擬dom與舊虛擬dom的差異比較江锨,比較規(guī)則如下:
- 舊虛擬dom用到了與新dom相同的key:
(1)若虛擬dom中內(nèi)容沒(méi)有變化吃警,直接復(fù)用之前的真是dom;
(2)虛擬dom內(nèi)容變化了啄育,則生成新的真實(shí)dom酌心,隨后替換掉頁(yè)面中舊的真實(shí)dom - 舊虛擬dom沒(méi)有找到與新虛擬dom相同的key:創(chuàng)建新的真實(shí)dom,然后渲染到頁(yè)面上挑豌;
- 舊虛擬dom用到了與新dom相同的key:
- 用 index 作為key可能會(huì)引發(fā)的問(wèn)題
- 若對(duì)數(shù)據(jù)進(jìn)行逆序添加安券,逆序刪除等破壞順序的操作,會(huì)產(chǎn)生沒(méi)有必要的真實(shí)dom更新 ---> 頁(yè)面沒(méi)有問(wèn)題氓英,但是效率低侯勉。
- 如果結(jié)構(gòu)中還包含輸入類的dom,會(huì)產(chǎn)生錯(cuò)誤的dom更新 --> 界面會(huì)有問(wèn)題
- 開(kāi)發(fā)中如何選擇key
- 最好使用每條數(shù)據(jù)唯一的標(biāo)識(shí)作為key铝阐,比如id址貌,手機(jī)號(hào),身份證號(hào)等徘键。
- 如果不存在對(duì)數(shù)據(jù)的逆序添加练对,逆序刪除等破壞順序的操作,僅用于渲染列表的展示吹害,使用index作為key是沒(méi)有問(wèn)題的螟凭。