做app+的模板下載網(wǎng)站短視頻精準(zhǔn)獲客
vue基礎(chǔ)回顧+進(jìn)階
課程內(nèi)容
- VUE 基礎(chǔ)回顧
- 路由 Vue-Router
- 狀態(tài)管理 vuex
- TypeScript
1. VUE 基礎(chǔ)回顧
1.1 基于腳手架創(chuàng)建前端工程
1.1.1 環(huán)境要求
要想基于腳手架創(chuàng)建前端工程,需要具備如下環(huán)境要求:
- ? node.js 前端項目的運(yùn)行環(huán)境
- 學(xué)習(xí)web階段已安裝
- ? npm JavaScript的包管理工具
- 安裝完node.js之后自帶了npm這個命令
- ? Vue CLI 基于Vue進(jìn)行快速開發(fā)的完整系統(tǒng),實(shí)現(xiàn)交互式的項目腳手架
- 需要通過npm命令來安裝
安裝完node.js后,可以通過命令行來查看版本號,如下:
安裝 Vue CLI,命令如下:
1.1.2 操作過程
使用 Vue CLI 創(chuàng)建前端工程的方式:
- 方式一:vue create 項目名稱
-
管理員的方式打開Dos窗口,之后進(jìn)入到一個非中文目錄(這個目錄當(dāng)做我們的VScode工作空間),輸入命令
vue create vue-demo-1
-
上下鍵選擇vue的版本,這里以vue2為例
-
可以看到vue項目創(chuàng)建成功
-
- ? 方式二:vue ui(推薦)
重點(diǎn)介紹使用 vue ui 命令創(chuàng)建前端工程的過程:
第一步:同樣首先以管理員的方式打開命令行窗口,之后切換到一個非中文的目錄(這個目錄當(dāng)做我們的VScode工作空間),在命令行輸入命令 vue ui
,在瀏覽器ui界面中選擇前端工程存放的位置
第二步:點(diǎn)擊“在此創(chuàng)建新項目”按鈕,跳轉(zhuǎn)到創(chuàng)建新項目設(shè)置頁面。填寫項目名稱、選擇包管理器為npm,點(diǎn)擊“下一步”按鈕
第三步:選擇 Default(Vue 2),點(diǎn)擊"創(chuàng)建項目"按鈕,完成項目的創(chuàng)建
1.1.3 工程結(jié)構(gòu)
工程目錄結(jié)構(gòu):
1.1.4 啟動前端服務(wù)
使用VS Code打開創(chuàng)建的前端工程,啟動前端工程:
訪問前端工程:
注:要停止前端服務(wù),可以在命令行終端使用 ctrl + C
前端項目啟動后,服務(wù)端口默認(rèn)為8080,很容易和后端tomcat端口號沖突。如何修改前端服務(wù)的端口號?
可以在vue.config.js中配置前端服務(wù)端口號:
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({transpileDependencies: true,devServer: {port: 7070 //指定前端服務(wù)端口號}
})
1.2 vue基本使用方式
本章節(jié)從如下幾個方面進(jìn)行vue回顧:
- vue 組件
- 文本插值
- 屬性綁定
- 事件綁定
- 雙向綁定
- 條件渲染
- axios
1.2.1 vue 組件
Vue 的組件文件以 .vue
結(jié)尾,每個組件由三部分組成:
- 結(jié)構(gòu)
<template>
- 樣式
<style>
- 邏輯
<script>
1.2.2 測試準(zhǔn)備工作
說明:
- 當(dāng)前頁面比較亂它自帶了很多的數(shù)據(jù),為了方便測試效果把數(shù)據(jù)給它清理一下。
- 可以看到頁面上還顯示一個圖片,這是因為當(dāng)前展示的這個頁面并不是直接來自于HelloWorld.Vue組件而是這個App.vue,App.vue組件才是真正的項目入口頁面,App.vue頁面中又引入了HelloWorld.Vue組件,這個圖片是設(shè)置在App.vue組件中,此時不想要圖片需要到App.vue組件中進(jìn)行刪除。
- 效果
1.2.3 文本插值
作用:用來綁定 data 方法返回的對象屬性
用法:{{插值表達(dá)式}}
示例:
測試:
代碼:
<template><div class="hello">{{name}}{{age > 60 ? '老年' : '青年'}}</div>
</template><script>
export default {name: 'HelloWorld',props: {msg: String},data() {return {name: '張三',age: 22}},}
</script><!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h3 {margin: 40px 0 0;
}
ul {list-style-type: none;padding: 0;
}
li {display: inline-block;margin: 0 10px;
}
a {color: #42b983;
}
</style>
效果:
1.2.4 屬性綁定
作用:為標(biāo)簽的屬性綁定 data 方法中返回的屬性
用法:v-bind
:xxx,簡寫為 :xxx
示例:
測試:
代碼
效果
1.2.5 事件綁定
作用:為元素綁定對應(yīng)的事件
用法:v-on:
xxx,簡寫為 @
xxx
示例:
測試:
代碼
效果
1.2.6 雙向綁定
作用:表單輸入項和 data 方法中的屬性進(jìn)行綁定,任意一方改變都會同步給另一方
用法:v-model
示例:
測試:
代碼
效果:修改輸入框的值name會發(fā)生變化,點(diǎn)擊事件方法修改name的值輸入框的值會跟著改變
1.2.7 條件渲染
作用:根據(jù)表達(dá)式的值來動態(tài)渲染頁面元素
用法:v-if、v-else、v-else-if
示例:
測試:
代碼
效果
1.2.8 axios
Axios 是一個基于 promise 的 網(wǎng)絡(luò)請求庫
,作用于瀏覽器和 node.js 中。使用Axios可以在前端項目中發(fā)送各種方式的HTTP請求。
安裝axios的命令:npm install axios
(以管理員的方式打開VScode)
導(dǎo)入:import axios from 'axios'
axios 的 API 列表:[ ]代表可選參數(shù),可以有可以沒有。
參數(shù)說明:
- url:請求路徑
- data:請求體數(shù)據(jù),最常見的是JSON格式數(shù)據(jù)
- config:配置對象,可以設(shè)置查詢參數(shù)、請求頭信息
注:在使用axios時,經(jīng)常會遇到跨域問題。為了解決跨域問題,可以在 vue.config.js 文件中配置代理:
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({transpileDependencies: true,devServer: {port: 7070,proxy: {'/api': {target: 'http://localhost:8080',pathRewrite: {'^/api': ''}}}}
})
axios的post請求示例:
axios.post('/api/admin/employee/login',{username:'admin',password: '123456'}).then(res => {console.log(res.data)}).catch(error => {console.log(error.response)})
axios的get請求示例:
axios.get('/api/admin/shop/status',{headers: {token: ‘xxx.yyy.zzz’}})
axios提供的統(tǒng)一使用方式示例一(可以發(fā)送各種方式的請求):
axios提供的統(tǒng)一使用方式示例二(可以發(fā)送各種方式的請求):
axios({url: '/api/admin/employee/login',method:'post',data: {username:'admin',password: '123456'}}).then((res) => {console.log(res.data.data.token)axios({url: '/api/admin/shop/status',method: 'get',params: {id: 100},headers: {token: res.data.data.token}})}).catch((error) => {console.log(error)})
1.2.9 axios 測試:沒有配置跨域----post請求
HelloWorld.vue代碼:
<input type="button" value="發(fā)送POST請求" @click="handleSendPOST"/>handleSendPOST() {//通過axios發(fā)送post請求 提供了url data 沒有提供config//地址是蒼穹外賣后臺登錄的接口地址,后臺項目要先啟動axios.post('http://localhost:8080/admin/employee/login',{username: 'admin',password: '123456'}).then(res => { //調(diào)用成功的回調(diào)函數(shù)console.log(res.data)}).catch(error => { //調(diào)用失敗的回調(diào)函數(shù)console.log(error.response)})},
啟動后臺項目,啟動前端項目vue-demo-2,點(diǎn)擊按鈕發(fā)送請求發(fā)現(xiàn)前后臺沒有任何反應(yīng),f12查看控制臺發(fā)現(xiàn)報錯(發(fā)生了跨域)
原因:發(fā)生了跨域問題,前端的訪問端口是7070,后端的是8080,當(dāng)前是在7070服務(wù)中往8080這個端口發(fā)送,所以產(chǎn)生了跨域。
解決:需要配置代理
1.2.10 axios 測試:配置跨域----post請求
為了解決跨域問題,可以在 vue.config.js 文件中配置代理:
代理的作用:前端發(fā)送的請求先請求到代理上,然后由代理進(jìn)行轉(zhuǎn)發(fā)到我們的后臺服務(wù),這樣就可以解決跨域問題了。
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({transpileDependencies: true,devServer: {port: 7070,proxy: {'/api': {//攔截前端發(fā)送的請求都含有api前綴的地址target: 'http://localhost:8080',//攔截后轉(zhuǎn)發(fā)到的目標(biāo)服務(wù)器地址pathRewrite: {//請求轉(zhuǎn)發(fā)到后端后,后端接口路徑多了個/api,匹配不上找不到controller,所以需要去掉'^/api': '' //路徑重寫:把/api替換為空串 ^api表示以/api作為開頭}}}}
})
修改HelloWorld.vue中發(fā)送的后臺請求地址:http://localhost:8080—》/api
因為修改的是配置文件所以需要重啟前端項目才能生效
再次發(fā)送請求:
1.2.11 axios 測試:get請求
HelloWorld.vue代碼:
<input type="button" value="發(fā)送GET請求" @click="handleSendGET"/>handleSendGET() {//通過axios發(fā)送get方式請求 指定了url(店鋪的營業(yè)狀態(tài)) 指定configaxios.get('/api/admin/shop/status',{//這個請求需要攜帶jwt的令牌地址才能正確訪問,復(fù)制上面發(fā)送post請求調(diào)用登錄接口生成的令牌地址headers: { //指定config,在請求頭里追加參數(shù)tokentoken: 'eyJhbGciOiJIUzI1NiJ9.eyJlbXBJZCI6MSwiZXhwIjoxNzEwNjkyMTgxfQ.WAb2SoElTlJcobDCXUAqKPlm0At68LAexTz1MTwZdz4'}}).then(res => {console.log(res.data)})},
對應(yīng)的店鋪營業(yè)狀態(tài)接口:
首先發(fā)送post請求,復(fù)制返回的token.
刷新頁面發(fā)送get請求:成功
1.2.12 axios 測試:通用方式發(fā)送請求
axios 統(tǒng)一使用方式:axios(config)
HelloWorld.vue代碼:
<input type="button" value="統(tǒng)一請求方式" @click="handleSend"/>handleSend() {//使用axios提供的統(tǒng)一調(diào)用方式發(fā)送請求axios({url: '/api/admin/employee/login',method: 'post', //默認(rèn)是getdata: { //data表示通過請求體傳參 username: 'admin',password: '123456'}}).then(res => {//成功回調(diào)console.log(res.data.data.token) //res.data:返回的result對象,里面包含data,data中又包含tokenaxios({ //在成功的回調(diào)函數(shù)里又發(fā)送一個get請求 獲取店鋪的營業(yè)狀態(tài)url: '/api/admin/shop/status',method: 'get',headers: {token: res.data.data.token //因為這個get方法實(shí)際上是在post請求的回調(diào)函數(shù)里面,所以這個地方可以動態(tài)的獲取token}})})}
測試:2次請求都成功發(fā)送
2. 路由 Vue-Router
2.1 Vue-Router 介紹
vue 屬于單頁面應(yīng)用,所謂路由,就是根據(jù)瀏覽器路徑不同,用不同的視圖組件替換這個頁面內(nèi)容。
單頁面應(yīng)用:在整個vue應(yīng)用中,實(shí)際上只有一個頁面,我們看到的瀏覽器多個頁面其實(shí)是一種假象,它是通過頁面切換 切換不同的視圖組件
現(xiàn)實(shí)舉例:一塊黑板,不同的老師上課把之前老師寫的內(nèi)容刪除掉,之后寫上自己課的內(nèi)容。
這個替換的過程就是通過路由來完成的。
如上圖所示:不同的訪問路徑,對應(yīng)不同的頁面展示。
基于Vue CLI 創(chuàng)建帶有路由功能的前端項目:
在vue應(yīng)用中使用路由功能,需要安裝Vue-Router:
注:創(chuàng)建完帶有路由功能的前端項目后,在工程中會生成一個路由文件,如下所示:
關(guān)于路由的配置,主要就是在這個路由文件中完成的。
為了能夠使用路由功能,在前端項目的入口文件main.js中,創(chuàng)建Vue實(shí)例時需要指定路由對象:
創(chuàng)建完路由項目后自動生成
啟動項目查看效果:點(diǎn)擊不同的地址會自動切換頁面
說明:
- 什么是路由?
- 根據(jù)瀏覽器訪問路徑不同,展示不同的視圖組件
- vue應(yīng)用中如何實(shí)現(xiàn)路由?
- 通過 vue-router 實(shí)現(xiàn)路由功能,需要安裝js庫(npm install vue-router)
- 剛才之所以沒有顯示的去安裝是因為,在頁面上使用了腳手架構(gòu)建項目并且勾選了路由功能,這樣的話在創(chuàng)建這個前端工程時,實(shí)際上就會通過這個命令安裝所需要的庫。
- 如果是一個老項目使用路由功能,此時需要執(zhí)行此命令手動安裝。
2.2 路由配置
首先了解一下路由組成:
VueRouter
:路由器,根據(jù)路由請求在路由視圖中動態(tài)渲染對應(yīng)的視圖組件- 路由器作用:根據(jù)路由請求來渲染這個不同的視圖
- 具體渲染哪一個視圖組件呢???在路由器中其實(shí)會維護(hù)一個路由表,它里面保存了映射關(guān)系,某一個路由路徑對應(yīng)的那一個視圖組件。
<router-link>
:路由鏈接組件,瀏覽器會解析成<a>
- 作用:生成超鏈接標(biāo)簽的
<router-view>
:路由視圖組件,用來展示與路由路徑匹配的視圖組件- 展示某一個視圖組件指定的位置,本質(zhì)是頁面中的一個占位符,通過路由去渲染不同的視圖組件,視圖組件要渲染的就是這個頁面
<router-view>
占位符所在的位置。
- 展示某一個視圖組件指定的位置,本質(zhì)是頁面中的一個占位符,通過路由去渲染不同的視圖組件,視圖組件要渲染的就是這個頁面
這三部分之間是如何協(xié)作的:
- 點(diǎn)擊路由鏈接組件(超鏈接)發(fā)起路由請求,這個請求會交給路由器處理。
- 路由器會根據(jù)路由路徑的不同然后去渲染對應(yīng)的視圖組件
- 具體渲染到這個路由視圖組件
<router-view>
這個占位符位置。
具體配置方式:
基于腳手架創(chuàng)建前端項目的時候勾選了路由功能,此時工程中路由的代碼已經(jīng)自動生成好了。
首先在package.json里面加入vue-router
:此時就可以在前端項目中使用路由功能了
然后在main.js入口文件中引入router,這個router來自于index.js文件
找到router下面有一個index.js,然后在這個文件里引入VueRouter,這個VueRouter來自于node_modules(保存創(chuàng)建好項目之后所依賴的包)中的vue-router里
- 在路由文件index.js中配置路由路徑和視圖的對應(yīng)關(guān)系:路由表
import Vue from 'vue'
import VueRouter from 'vue-router'
import HomeView from '../views/HomeView.vue'Vue.use(VueRouter)//維護(hù)路由表,某個路由路徑對應(yīng)哪個視圖組件
const routes = [{path: '/', //對應(yīng)一個路由路徑name: 'home', //名字component: HomeView //路徑所對應(yīng)的視圖組件 方式一:靜態(tài)導(dǎo)入,最終項目上線需要打包,打包會把這些組件}, // 打到同一個js文件里面,兩種打包方式不同// 性能稍差:不管你視圖展示不展示都打入到同一個js文件里面,導(dǎo)致這個js文件非常大,// 哪怕你這個視圖從來沒有強(qiáng)求過沒顯示過,但是這部分資源已經(jīng)加載了,{path: '/about',name: 'about',// route level code-splitting// this generates a separate chunk (about.[hash].js) for this route// which is lazy-loaded when the route is visited.//方式二:動態(tài)導(dǎo)入(推薦) 懶加載策略:打包的時候會單獨(dú)的把這些組件打到j(luò)s文件里面// 性能更好:按需引入因為它是單獨(dú)的把這些視圖組件單獨(dú)的打到j(luò)s文件里面,// 只有請求這個視圖它才會加載這個js文件,如果不請求就不會加載了。component: () => import(/* webpackChunkName: "about" */ '../views/AboutView.vue')}
]const router = new VueRouter({routes
})export default router
- 在視圖組件App.vue入口頁面文件中配置 router-link標(biāo)簽,用于生成超鏈接
<router-link to="/">Home</router-link> | <!-- 路由鏈接組件生成超鏈接 --><router-link to="/about">About</router-link>
- 在視圖組件匯總配置router-view標(biāo)簽:占位符,視圖渲染到的位置
- 效果:可以來回切換
要實(shí)現(xiàn)路由跳轉(zhuǎn),可以通過標(biāo)簽式和編程式兩種:
- 標(biāo)簽式:
<router-link to="/about">About</router-link>
- 通過router-link標(biāo)簽生成超鏈接實(shí)現(xiàn)跳轉(zhuǎn)
- 編程式:
this.$router.push('/about')
- 通過js代碼實(shí)現(xiàn)跳轉(zhuǎn)
- 通過js代碼實(shí)現(xiàn)跳轉(zhuǎn)
測試編程式:
代碼:
<input type="button" value="編程式路由跳轉(zhuǎn)" @click="jump"/> <!-- 方法不需要參數(shù)的話()可以省略掉 --><script>
export default {methods: {jump() {//使用編程路由的方式跳轉(zhuǎn) 具體的路由路徑(路由表中配置的路徑)this.$router.push('/about',()=> {})}}
}
</script>
效果:點(diǎn)擊按鈕也能跳轉(zhuǎn)到about頁面
問題思考:如果用戶訪問的路由地址不存在,該如何處理?
可以通過配置一個404視圖組件,當(dāng)訪問的路由地址不存在時,則重定向到此視圖組件,具體配置如下:
index.js文件:路由表
/* 只寫這一個配置的效果:我們訪問到404路徑的時候就可以訪問到這個組件,而我們的需求是 當(dāng)用戶訪問一個不存在的路徑時才會跳轉(zhuǎn)到404視圖去展示,所以還需要接著配置重定向*/{path: '/404', //name可以不用配置component: () => import('../views/404View.vue')},/* 配置重定向流程:當(dāng)用戶訪問到一個不存在的路徑就會重定向到/404,/404路徑對應(yīng)的就是404頁面組件 */{path: '*', //上面這些訪問的路徑都沒匹配上才會走這最后一個路徑redirect: '/404' //重定向到/404訪問路徑,}
App.vue:超鏈接
<router-link to="/test">Test</router-link> | <!-- 沒有對應(yīng)的路由路徑/test -->
路由請求路徑不存在,跳轉(zhuǎn)的頁面組件:
<template><div class="about"><h1>您請求的資源不存在</h1></div>
</template>
效果:
2.3 嵌套路由
嵌套路由:組件內(nèi)要切換內(nèi)容,就需要用到嵌套路由(子路由),效果如下:
在App.vue視圖組件中有<router-view>
標(biāo)簽,其他視圖組件可以展示在此
ContainerView.vue組件可以展示在App.vue視圖組件的<router-view>
位置
ContainerView.vue組件進(jìn)行了區(qū)域劃分(分為上、左、右),在右邊編寫了<router-view>
標(biāo)簽,點(diǎn)擊左側(cè)菜單時,可以將對應(yīng)的子視圖組件展示在此
總結(jié):
- 原先是不同的vue組件嵌套到App.vue入口視圖組件頁面中
- 現(xiàn)在是不同的子組件先嵌套到ContainerView.vue組件中,ContainerView.vue組件在嵌套到App.vue入口視圖組件中。
實(shí)現(xiàn)步驟:
第一步:安裝并導(dǎo)入 elementui,實(shí)現(xiàn)頁面布局(Container 布局容器)—ContainerView.vue
安裝: elementui
npm i element-ui -S
導(dǎo)入: elementui,在 main.js 中寫入以下內(nèi)容:
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';Vue.use(ElementUI);//全局使用ElementUi
實(shí)現(xiàn)頁面布局(Container 布局容器)—ContainerView.vue
<template><el-container><el-header>Header</el-header><el-container><el-aside width="200px"></el-aside><el-main></el-main></el-container></el-container>
</template><script>
export default {}
</script><style>
.el-header, .el-footer {background-color: #B3C0D1;color: #333;text-align: center;line-height: 60px;}.el-aside {background-color: #D3DCE6;color: #333;text-align: center;line-height: 200px;}.el-main {background-color: #E9EEF3;color: #333;text-align: center;line-height: 160px;}body > .el-container {margin-bottom: 40px;}.el-container:nth-child(5) .el-aside,.el-container:nth-child(6) .el-aside {line-height: 260px;}.el-container:nth-child(7) .el-aside {line-height: 320px;}
</style>
第二步:提供子視圖組件,用于效果展示 —P1View.vue、P2View.vue、P3View.vue
<template><div>這是P1 View</div>
</template><script>
export default {}
</script><style>
.el-header, .el-footer {background-color: #B3C0D1;color: #333;text-align: center;line-height: 60px;}.el-aside {background-color: #D3DCE6;color: #333;text-align: center;line-height: 200px;}.el-main {background-color: #E9EEF3;color: #333;text-align: center;line-height: 160px;}body > .el-container {margin-bottom: 40px;}.el-container:nth-child(5) .el-aside,.el-container:nth-child(6) .el-aside {line-height: 260px;}.el-container:nth-child(7) .el-aside {line-height: 320px;}
</style>
第三步:在 src/router/index.js 中配置路由映射規(guī)則(嵌套路由配置)
{path: '/c',component: () => import('../views/container/ContainerView.vue'),//嵌套路由(子路由),對應(yīng)的組件會展示在當(dāng)前組件內(nèi)部children: [//通過children屬性指定子路由相關(guān)信息(path、component){path: '/c/p1',component: () => import('../views/container/P1View.vue')},{path: '/c/p2',component: () => import('../views/container/P2View.vue')},{path: '/c/p3',component: () => import('../views/container/P3View.vue')}]}
第四步:在ContainerView.vue 布局容器視圖中添加,實(shí)現(xiàn)子視圖組件展示
<el-main><router-view/>
</el-main>
第五步:在ContainerView.vue 布局容器視圖中添加,實(shí)現(xiàn)路由請求
<el-aside width="200px"><router-link to="/c/p1">P1</router-link><br><router-link to="/c/p2">P2</router-link><br><router-link to="/c/p3">P3</router-link><br>
</el-aside>
效果:http://localhost:8080/#/c
點(diǎn)擊超鏈接(http://localhost:8080/#/c/p1)右側(cè)會進(jìn)行替換組件。
注意:子路由變化,切換的是【ContainerView 組件】中 <router-view></router-view>
部分的內(nèi)容
問題思考:
1.對于前面的案例,如果用戶訪問的路由是 /c,會有什么效果呢?
2.如何實(shí)現(xiàn)在訪問 /c 時,默認(rèn)就展示某個子視圖組件呢?
配置重定向,當(dāng)訪問/c時,直接重定向到/c/p1即可,如下配置:
redirect :'/c/p1',
效果:
3. 狀態(tài)管理 vuex(待定:P177)
3.1 vuex 介紹
- vuex 是一個專為 Vue.js 應(yīng)用程序開發(fā)的狀態(tài)管理庫
- vuex 可以在多個組件之間共享數(shù)據(jù),并且共享的數(shù)據(jù)是響應(yīng)式的,即數(shù)據(jù)的變更能及時渲染到模板
- vuex 采用集中式存儲管理所有組件的狀態(tài)
每一個 Vuex 應(yīng)用的核心就是 store(倉庫)。“store”基本上就是一個容器,它包含著你的應(yīng)用中大部分的狀態(tài) (state)。Vuex 和單純的全局對象有以下兩點(diǎn)不同:
- Vuex 的狀態(tài)存儲是響應(yīng)式的。當(dāng) Vue 組件從 store 中讀取狀態(tài)的時候,若 store 中的狀態(tài)發(fā)生變化,那么相應(yīng)的組件也會相應(yīng)地得到高效更新。
- 你不能直接改變 store 中的狀態(tài)。改變 store 中的狀態(tài)的唯一途徑就是顯式地提交 (commit) mutation。這樣使得我們可以方便地跟蹤每一個狀態(tài)的變化,從而讓我們能夠?qū)崿F(xiàn)一些工具幫助我們更好地了解我們的應(yīng)用。
安裝vuex:npm install vuex@next --save
vuex中的幾個核心概念:
- state:狀態(tài)對象,集中定義各個組件共享的數(shù)據(jù)
- mutations:類似于一個事件,用于修改共享數(shù)據(jù),要求必須是同步函數(shù)
- actions:類似于mutation,可以包含異步操作,通過調(diào)用mutation來改變共享數(shù)據(jù)
3.2 使用方式
本章節(jié)通過一個案例來學(xué)習(xí)vuex的使用方式,具體操作步驟如下:
第一步:創(chuàng)建帶有vuex功能的前端項目
注:在創(chuàng)建的前端工程中,可以發(fā)現(xiàn)自動創(chuàng)建了vuex相關(guān)的文件(src/store/index.js),并且在main.js中創(chuàng)建Vue實(shí)例時,需要將store對象傳入,代碼如下:
import Vue from 'vue'
import App from './App.vue'
import store from './store'Vue.config.productionTip = falsenew Vue({store,//使用vuex功能render: h => h(App)
}).$mount('#app')
第二步:在src/store/index.js文件中集中定義和管理共享數(shù)據(jù)
import Vue from 'vue'
import Vuex from 'vuex'
import axios from 'axios'Vue.use(Vuex)//集中管理多個組件共享的數(shù)據(jù)
export default new Vuex.Store({//集中定義共享數(shù)據(jù)state: {name: '未登錄游客'},getters: {},//通過當(dāng)前屬性中定義的函數(shù)修改共享數(shù)據(jù),必須都是同步操作mutations: {},//通過actions調(diào)用mutation,在actions中可以進(jìn)行異步操作actions: {},modules: {}
})
第三步:在視圖組件中展示共享數(shù)據(jù)
<template><div class="hello"><h1>歡迎你,{{$store.state.name}}</h1></div>
</template>
注:$store.state為固定寫法,用于訪問共享數(shù)據(jù)
第四步:在mutations中定義函數(shù),用于修改共享數(shù)據(jù)
//通過當(dāng)前屬性中定義的函數(shù)修改共享數(shù)據(jù),必須都是同步操作mutations: {setName(state,newName) {state.name = newName}},
第五步:在視圖組件中調(diào)用 mutations 中定義的函數(shù)
注:mutations中定義的函數(shù)不能直接調(diào)用,必須通過狀態(tài)對象的 commit 方法來調(diào)用
第六步:如果在修改共享數(shù)據(jù)的過程中有異步操作,則需要將異步操作的代碼編寫在actions的函數(shù)中
//通過actions調(diào)用mutation,在actions中可以進(jìn)行異步操作actions: {setNameByAxios(context){axios({ //異步請求url: '/api/admin/employee/login',method: 'post',data: {username: 'admin',password: '123456'}}).then(res => {if(res.data.code == 1){//異步請求后,需要修改共享數(shù)據(jù)//在actions中調(diào)用mutation中定義的setName函數(shù)context.commit('setName',res.data.data.name)}})}},
注:在actions中定義的函數(shù)可以聲明context參數(shù),通過此參數(shù)可以調(diào)用mutations中定義的函數(shù)
第七步:在視圖組件中調(diào)用actions中定義的函數(shù)
注:在actions中定義的函數(shù)不能直接調(diào)用,必須通過 this.$store.dispatch(‘函數(shù)名稱’) 這種方式調(diào)用
4. TypeScript
4.1 TypeScript 介紹
- TypeScript(簡稱:TS) 是微軟推出的開源語言
- TypeScript 是 JavaScript 的超集(JS 有的 TS 都有)
- TypeScript = Type + JavaScript(在 JS 基礎(chǔ)上增加了類型支持)
- TypeScript 文件擴(kuò)展名為 ts
- TypeScript 可編譯成標(biāo)準(zhǔn)的 JavaScript,并且在編譯時進(jìn)行類型檢查
在前端項目中使用TS,需要進(jìn)行安裝,命令為:npm install -g typescript
查看TS版本:
TS初體驗:
- 創(chuàng)建 hello.ts 文件,內(nèi)容如下:
//定義一個函數(shù) hello,并且指定參數(shù)類型為string
function hello(msg:string) {console.log(msg)
}//調(diào)用上面的函數(shù),傳遞非string類型的參數(shù)
hello(123)
- 使用 tsc 命令編譯 hello.ts 文件
可以看到編譯報錯,提示參數(shù)類型不匹配。這說明在編譯時TS會進(jìn)行類型檢查。需要注意的是在編譯為JS文件后,類型會被擦除。
思考:TS 為什么要增加類型支持 ?
- TS 屬于靜態(tài)類型編程語言,JS 屬于動態(tài)類型編程語言
- 靜態(tài)類型在編譯期做類型檢查,動態(tài)類型在執(zhí)行期做類型檢查
- 對于 JS 來說,需要等到代碼執(zhí)行的時候才能發(fā)現(xiàn)錯誤(晚)
- 對于 TS 來說,在代碼編譯的時候就可以發(fā)現(xiàn)錯誤(早)
- 配合 VSCode 開發(fā)工具,TS 可以提前到在編寫代碼的同時就發(fā)現(xiàn)代碼中的錯誤,減少找 Bug、改 Bug 的時間
在前端項目中使用TS,需要創(chuàng)建基于TS的前端工程:
4.2 TypeScript 常用類型
TS中的常用類型如下:
類型 | 例 | 備注 |
---|---|---|
字符串類型 | string | |
數(shù)字類型 | number | |
布爾類型 | boolean | |
數(shù)組類型 | number[],string[], boolean[] 依此類推 | |
任意類型 | any | 相當(dāng)于又回到了沒有類型的時代 |
復(fù)雜類型 | type 與 interface | |
函數(shù)類型 | () => void | 對函數(shù)的參數(shù)和返回值進(jìn)行說明 |
字面量類型 | “a”|“b”|“c” | 限制變量或參數(shù)的取值 |
class 類 | class Animal |
4.2.1 類型標(biāo)注的位置
基于TS進(jìn)行前端開發(fā)時,類型標(biāo)注的位置有如下3個:
- 標(biāo)注變量
- 標(biāo)注參數(shù)
- 標(biāo)注返回值
4.2.2 字符串、數(shù)字、布爾類型
字符串、數(shù)字、布爾類型是前端開發(fā)中常用的類型
4.2.3 字面量類型
字面量類型用于限定數(shù)據(jù)的取值范圍,類似于java中的枚舉
4.2.4 interface 類型
interface 類型是TS中的復(fù)雜類型,它讓 TypeScript 具備了 JavaScript 所缺少的、描述較為復(fù)雜數(shù)據(jù)結(jié)構(gòu)的能力。
可以通過在屬性名后面加上?,表示當(dāng)前屬性為可選,如下:
4.2.5 class 類型
使用 class 關(guān)鍵字來定義類,類中可以包含屬性、構(gòu)造方法、普通方法等
在定義類時,可以使用 implments 關(guān)鍵字實(shí)現(xiàn)接口,如下:
在定義類時,可以使用 extends 關(guān)鍵字 繼承其他類,如下: