大家好,我是前端嵐楓铐刘,今天主要跟大家分享我整理的筆記2021前端面試題系列:vue傳值方式陪每、vuex、router镰吵、vue服務(wù)器端渲染檩禾、多頁(yè)面、權(quán)限疤祭、開(kāi)發(fā)環(huán)境跨域方案等等盼产,此方面內(nèi)容在我們的工作中常用到, 也是面試官經(jīng)常提問(wèn)的問(wèn)題勺馆,希望下面文章對(duì)大家有所幫助戏售。
vue 傳值方式
vue傳值‘
- 父 子 傳值 使用props接受
- 子 父 傳值 父親寫(xiě)事件函數(shù) 子 $emit觸發(fā) 傳值
- 兄弟傳值 $bus 中轉(zhuǎn)站
- 如果組件之間 關(guān)系很遠(yuǎn) 是很多組件都要用的值 vuex
- provide, inject注入方式
vuex 就是一個(gè)全局狀態(tài)數(shù)據(jù)管理 簡(jiǎn)單來(lái)說(shuō) 他的數(shù)據(jù)類(lèi)似全局變量 哪個(gè)組件都可以使用
在項(xiàng)目中使用vuex
- 下載 vuex 包 并導(dǎo)入 use一下
import Vuex from 'vuex'
Vue.use(Vuex)
- 需要new 一下 寫(xiě)上全局?jǐn)?shù)據(jù)
// store
new Vuex.Store({
state: {
count:1 //這個(gè)count 就是全局的數(shù)據(jù)
},
mutations: {
},
actions: {
}
})
- 需要掛載到new vue上
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
<template>
<div class="home">
<!-- home啊
<hr>
{{$store.state.m1.m1Name}}
<button @click="add">點(diǎn)擊</button> -->
<!-- <hr> -->
<!-- <my-swiper :list="list"></my-swiper> -->
<button @click="getAll">發(fā)送請(qǐng)求</button>
home組件啊
<hr>
<h1>count的值:{{$store.state.count}}</h1>
<button @click="addCount">讓全局count+1</button>
<hr>
<h2>m1下的全局?jǐn)?shù)據(jù) {{$store.state.m1.m1Name}} </h2>
<button @click="add">點(diǎn)擊修改某個(gè)模塊的數(shù)據(jù)</button>
<!-- 3 哪個(gè)組件要用 就直接 使用注冊(cè)的組件標(biāo)簽名 -->
<hr>
<!-- 用組件 傳了list數(shù)據(jù)進(jìn)去 -->
<my-swiper :list="list"></my-swiper>
</div>
</template>
<script>
// 要在組件使用全局?jǐn)?shù)據(jù)
// 1 在html范圍 直接 $store.state.名字
// 2 在js范圍 this.$store.state.名字
// @ is an alias to /src
// import HelloWorld from '@/components/HelloWorld.vue'
import { mapMutations , mapActions ,mapState } from 'vuex'
export default {
name: 'Home',
components: {
// HelloWorld
},
data(){
return {
list:[
{id:1,src:'http://122.51.238.153/images/1.jpg'},
{id:2,src:'http://122.51.238.153/images/2.jpg'},
{id:3,src:'http://122.51.238.153/images/3.jpg'},
{id:4,src:'http://122.51.238.153/images/4.jpg'}
]
}
},
created(){
console.log('created')
console.log('store',this.$store)
},
mounted(){
console.log("home 的 mounted")
},
methods:{
// 這句話的意思是 直接 解構(gòu)出 全局 m1模塊下的 loginMutation
// 把loginMutation 放到this上 并且?guī)湍銓?xiě)好了 commit
// 相當(dāng)于幫你簡(jiǎn)化了代碼
...mapMutations('m1', ['loginMutation']),
//不是modules的直接寫(xiě) ...mapMutations( ['loginMutation'])
add(){
// console.log('add',this)
// console.log('add',this.$route.meta)
// this.$store.commit("m1/loginMutation")
// 或者下面的 先mapMutations 相當(dāng)于幫你寫(xiě)了commit
this.loginMutation()
// this.$store.commit("m1/loginMutation")
// 和剛剛的思路 就是加上一個(gè)模塊前綴 m1/
// this.$store.dispatch("m1/loginAction")
},
async getAll(){
// http://localhost:8080/
// 請(qǐng)求 http://122.51.238.153/getok.php
// let res=await this.$http.get("http://122.51.238.153/getok.php")
// console.log('res',res)
let res=await this.$http.get("/api/getok.php")
console.log('res',res)
},
addCount(){
// 讓全局?jǐn)?shù)據(jù)count+1
// 1 正常情況
// dispatch 觸發(fā)action
// -》commit觸發(fā)mutation
// -》在mutation修改全局?jǐn)?shù)據(jù)
//2 其他情況 可以直接跳過(guò)action 但是必須mutation修改
// console.log('$store',this.$store)
// this.$store.dispatch( 'countAction' )
this.$store.commit("countMutation")
}
}
}
</script>
這個(gè)步驟是寫(xiě)死的 你可以記一下 下載使用腳手架直接就可以選vuex
他的使用邏輯是什么?
在 store里面的 state 寫(xiě)的數(shù)據(jù) 是全局?jǐn)?shù)據(jù) 所有組件都可以使用
使用邏輯
操作全局vuex的 state數(shù)據(jù)
正常情況 必須 dispatch (action)--->action去commit觸發(fā) mutation--》mutation里面才能修改state全局?jǐn)?shù)據(jù)
action--->mutation--->修改state
其他情況 你也可以跳過(guò) action 去 直接 commit mutation--》修改state全局?jǐn)?shù)據(jù)
vuex怎么合理規(guī)范管理數(shù)據(jù),及mutations和actions區(qū)別
解析: 此題考查 vuex中數(shù)據(jù)的管理和數(shù)據(jù)結(jié)構(gòu)的設(shè)計(jì),還有mutations 和actions的區(qū)別
**解答**
: 首先要明確一個(gè)特別重要的原則, 就是 不是所有的數(shù)據(jù)都要放在vuex中, 因?yàn)関uex有一句名言:假如你并不知道為什么要使用vuex,那就不要使用它 !那么什么樣式的數(shù)據(jù)需要放在vuex中呢 ? 首先這個(gè)數(shù)據(jù)肯定要被多個(gè)組件頻繁用到, 如果只是被一個(gè)組件 用到, 那完全沒(méi)有任何必要為了使用vuex和使用vuex
舉例: 一個(gè)網(wǎng)站用戶(hù)的昵稱(chēng),賬號(hào),資料,像這種系統(tǒng)級(jí)別的信息 隨時(shí)可能在業(yè)務(wù)中展示,使用, 如果在組件中存儲(chǔ), 那么要獲取N次, 所以**系統(tǒng)級(jí)別的數(shù)據(jù)**
是需要放置在vuex中的, 那么系統(tǒng)級(jí)別數(shù)據(jù) 也不能所以的放置,為了讓數(shù)據(jù)看著更有層級(jí)結(jié)構(gòu)感,可以按照像下面這樣設(shè)計(jì),
{
// 系統(tǒng)消息
system: {
user: {},
setting: {}
}
}
上面這種結(jié)構(gòu),一看 便知道我們應(yīng)該哪里獲取系統(tǒng)數(shù)據(jù)即 設(shè)置數(shù)據(jù)
如果有些業(yè)務(wù)數(shù)據(jù),也需要共享,最好按照模塊的具體業(yè)務(wù)含義分類(lèi) , 比如下面
{
// 系統(tǒng)消息
system: {
user: {},
setting: {}
},
product: {
productList: [], // 商品信息列表
productOrders: [] // 商品訂單啊列表
}
}
如上圖代碼所示,我們很清晰的能夠分清楚 每個(gè)模塊的數(shù)據(jù),這樣不會(huì)導(dǎo)致數(shù)據(jù)管理的混亂
mutations和 actions 的區(qū)別
不同于redux只有一個(gè)action, vuex單獨(dú)拎出了一個(gè)mutations, 它認(rèn)為 更新數(shù)據(jù)必須是同步的, 也就是只要調(diào)用了 提交數(shù)據(jù)方法, 在mutation里面才可以修改數(shù)據(jù)
那么如果我們想做 異步請(qǐng)求,怎么做? 這里 vuex提供了專(zhuān)門(mén)做異步請(qǐng)求的模塊,action, 當(dāng)然action中也可以做同步操作, 只不過(guò) 分工更加明確, 所有的數(shù)據(jù)操作 不論是同步還是異步 都可以在action中完成,
mutation只負(fù)責(zé)接收狀態(tài), 同步完成
**數(shù)據(jù)快照**
所以可以認(rèn)為
state => 負(fù)責(zé)存儲(chǔ)狀態(tài)
mutations => 負(fù)責(zé)同步更新?tīng)顟B(tài)
actions => 負(fù)責(zé)獲取 處理數(shù)據(jù)(如果有異步操作必須在action處理 再到mutation), 提交到mutation進(jìn)行狀態(tài)更新
vuex模塊化module管理,使用的時(shí)候有注意事項(xiàng)
pro111
分析: 此題考查 當(dāng)vuex維護(hù)的數(shù)據(jù)越來(lái)越復(fù)雜的時(shí)候, 模塊化的解決方案
**解析**
:使用單一的狀態(tài)樹(shù)草穆,應(yīng)用的所有狀態(tài)都會(huì)**集中在一個(gè)比較大的對(duì)象**
上面灌灾,隨著項(xiàng)目需求的不斷增加,狀態(tài)樹(shù)也會(huì)變得越來(lái)越臃腫悲柱,增加了狀態(tài)樹(shù)維護(hù)的復(fù)雜度,而且代碼變得沉長(zhǎng)锋喜;因此我們需要**modules(模塊化)**
來(lái)為我們的狀態(tài)樹(shù)**分隔**
成不同的模塊,每個(gè)模塊擁有自己的state诗祸,getters跑芳,mutations轴总,actions直颅;而且允許每個(gè)module里面嵌套子module;如下:
store
├── index.js # 我們組裝模塊并導(dǎo)出 store 的地方
├── actions.js # 根級(jí)別的 action
├── mutations.js # 根級(jí)別的 mutation
├── state.js # 根級(jí)別的 state
└── modules
├── module1.js # 模塊1的state樹(shù)
└── module2.js # 模塊2的state樹(shù)
上面的設(shè)計(jì)中, 每個(gè)vuex子模塊都可以定義 state/mutations/actions
需要注意的是 我們?cè)瓉?lái)使用
**vuex輔助函數(shù)**
mapMutations/mapActions 引入的是 全局的的mutations 和actions , 并且我們vuex子模塊 也就是module1,module2 ... 這些模塊的aciton /mutation 也注冊(cè)了全局,也就是如果 module1 中定義了 loginMutation, module2中也定義了 loginMutation, 此時(shí), mutation就沖突了
如果重名,就報(bào)錯(cuò)了.....
如果不想沖突, 各個(gè)模塊管理自己的action 和 mutation ,需要 給我們的子模塊一個(gè) 屬性
**namespaced: true**
那么 組件中怎么使用子模塊的action 和 mutations
// 你可以將模塊的空間名稱(chēng)字符串作為第一個(gè)參數(shù)傳遞給上述函數(shù)怀樟,這樣所有綁定都會(huì)自動(dòng)將該模塊作為上下文
methods:{
...mapMutations('m1', ['loginMutation']),
add(){
console.log('add',this)
// this.$store.commit("m1/loginMutation")
// 或者下面的 先mapMutations 相當(dāng)于幫你寫(xiě)了commit
// this.loginMutation()
}
}
// 這句話的意思是 直接 解構(gòu)出 全局 m1模塊下的 loginMutation
// 把loginMutation 放到this上 并且?guī)湍銓?xiě)好了 commit
// 相當(dāng)于幫你簡(jiǎn)化了代碼
...mapMutations('m1', ['loginMutation']),
//不是modules的直接寫(xiě) ...mapMutations( ['loginMutaton])
store.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
// 1 下載vuex 導(dǎo)入 use一下
// 2 new Vuex.Store
// 3 掛載到new vue上
export default new Vuex.Store({
state: {
// 在這里寫(xiě)的就是所有組件都能有 全局?jǐn)?shù)據(jù)了
// 名字:值
// 如果我1000個(gè)全局?jǐn)?shù)據(jù) 有可能重名
count:100
},
mutations: {
countMutation(state){
// state 就是那個(gè)全局state
console.log('mutation觸發(fā)了',state)
state.count++
}
},
actions: {
// action對(duì)應(yīng)的函數(shù)
countAction(obj){
console.log('action觸發(fā)了',obj)
// obj對(duì)象 里面有commit
obj.commit("countMutation")
}
},
// modules 在store全局?jǐn)?shù)據(jù) 是可以來(lái)分模塊管理的
// 他可以用來(lái)區(qū)分每個(gè)不同模塊的數(shù)據(jù)
// 15:10 上課
modules: {
// 模塊:{ 一套state action mutation }
m1: {
namespaced: true,//開(kāi)啟命名空間大白話 他是m1下的 不會(huì)影響其他人
// 模塊內(nèi)容(module assets)
state: { // 模塊內(nèi)的狀態(tài)已經(jīng)是嵌套的了功偿,使用 `namespaced` 屬性不會(huì)對(duì)其產(chǎn)生影響
m1Name:"我是m1模塊的m1Name"
},
actions: {
loginAction () {
console.log('m1的action')
} // -> dispatch('m1/loginAction')
},
mutations: {
loginMutation () {
console.log('loginMutation-執(zhí)行啦')
} // -> commit('m1/loginMutation')
}
},
home:{
namespaced: true,
state:{
count:1
}
},
about:{
namespaced: true,
state:{
count:100
},
actions:{
}
},
}
})
此題具體考查 Vuex雖然是一個(gè)公共狀態(tài), 但是公共狀態(tài)還可以切分成若干個(gè)子狀態(tài)模塊, 也就是moduels,
解決當(dāng)我們的狀態(tài)樹(shù)過(guò)于龐大和復(fù)雜時(shí)的一種解決方案. 但是筆者認(rèn)為, 一旦用了vuex, 幾乎 就認(rèn)定該項(xiàng)目是較為復(fù)雜的
封裝Vue組件的步驟
組件是什么?組件是一段功能代碼 ---大白話 就是一段html +js +css 你可以重復(fù)使用
封裝輪播圖 -
1 新建vue組件
2 Vue.component注冊(cè)組件
3 在其他組件使用 標(biāo)簽名
參數(shù): 可以傳入數(shù)據(jù) 使用props接受 比如 數(shù)組 定時(shí)器時(shí)間等
分析: 本題考查 對(duì)于Vue組件化開(kāi)發(fā)的熟練程度
解析: 首先明確 組件是本質(zhì)是什么?
組件就是一個(gè)單位的HTML結(jié)構(gòu) + 數(shù)據(jù)邏輯 + 樣式的 操作單元
Vue的組件 繼承自Vue對(duì)象, Vue對(duì)象中的所有的屬性和方法,組件可自動(dòng)繼承.
- 組件的要素 template => 作為頁(yè)面的模板結(jié)構(gòu)
- script => 作為數(shù)據(jù)及邏輯的部分
- style => 作為該組件部分的樣式部分
要封裝一個(gè)組件,首先要明確該組件要做的具體業(yè)務(wù)和需求, 什么樣的體驗(yàn)特征, 完成什么樣的交互, 處理什么樣的數(shù)據(jù)
明確上述要求之后, 著手模板的結(jié)構(gòu)設(shè)計(jì)及搭建,也就是 常說(shuō)的html結(jié)構(gòu)部分, 先完成 靜態(tài)的html結(jié)構(gòu)
結(jié)構(gòu)完成, 著手?jǐn)?shù)據(jù)結(jié)構(gòu)的設(shè)計(jì)及開(kāi)發(fā), 數(shù)據(jù)結(jié)構(gòu)一般存儲(chǔ)于組件的data屬性 或者 vuex 狀態(tài)共享的數(shù)據(jù)結(jié)構(gòu)
數(shù)據(jù)設(shè)計(jì)完成/ 結(jié)構(gòu)完成 接下來(lái) 完成數(shù)據(jù)和模塊的結(jié)合 , 利用vuejs中指令和 插值表達(dá)式的特性 將靜態(tài)結(jié)構(gòu)
**動(dòng)態(tài)化**
展現(xiàn)的部分完成, 接下來(lái)完成
**交互部分**
,即利用 組件的生命周期的鉤子函數(shù) 和 事件驅(qū)動(dòng) 來(lái)完成 邏輯及數(shù)據(jù)的處理與操作
最后組件完成,進(jìn)行測(cè)試及使用
常用的組件屬性 => data/ methods/filters/ components/watch/created/mounted/beforeDestroy/computed/props
常用組件指令: v-if/v-on/v-bind/v-model/v-text/v-once
Vue中的data是以函數(shù)的形式還是對(duì)象的形式表示
分析: 此題考查 data的存在形式
**解析**
: 我們?cè)诔醪綄W(xué)習(xí)Vue實(shí)例化的時(shí)候?qū)懙拇a時(shí)這個(gè)樣子
上面代碼中的data 是一個(gè)對(duì)象, 但是我們?cè)陂_(kāi)發(fā)組件的時(shí)候要求data必須是一個(gè)帶返回值的函數(shù)
new Vue({
el: '#app',
data: {
name: 'hello world'
}
})
export default {
data () {
return {
name: '張三'
}
}
}
為什么組件要求必須是帶返回值的函數(shù)? 因?yàn)?我們的組件在實(shí)例化的時(shí)候, 會(huì)直接將data數(shù)據(jù)作用在視圖上,
對(duì)組件實(shí)例化, 會(huì)導(dǎo)致我們組件的data數(shù)據(jù)進(jìn)行共享, 好比 現(xiàn)在有兩輛新車(chē), 你一踩油門(mén), 不光你的車(chē)往前車(chē),另輛車(chē)也和你一樣往前沖! 這顯然不符合我們的程序設(shè)計(jì)要求, 我們希望組件內(nèi)部的數(shù)據(jù)是相互獨(dú)立的,且互不響應(yīng),所以 采用
**return {}**
每個(gè)組件實(shí)例都返回新對(duì)象實(shí)例的形式,保證每個(gè)組件實(shí)例的唯一性
使用Proxy代理跨域
pro111
什么是跨域往堡?
域名 協(xié)議 ip地址 端口 任何一個(gè)不一樣 就跨域
解決跨域械荷?
1 jsonp ---使用script的src發(fā)送 只能get 請(qǐng)求
2 cors 后臺(tái)設(shè)置允許跨域 需要后臺(tái)設(shè)置 允許跨域
所有后臺(tái)語(yǔ)言 都可以設(shè)置
3 服務(wù)器代理
重點(diǎn) 現(xiàn)在 前端 vue 框架 是可以自己設(shè)置 服務(wù)器代理的 proxy
配置:vue在 vue.config.js 可以配置重寫(xiě)webpack
分析: 本題考查如何解決跨域問(wèn)題
解析: 解決跨域問(wèn)題的方式有幾種,
- 一種是服務(wù)端設(shè)置 , 但這種方式依賴(lài)服務(wù)端的設(shè)置,在前后分離的場(chǎng)景下 ,不太方便
- 還有一種jsonp形式, 可以利用script標(biāo)簽 的特性解決同源策略帶來(lái)的跨域問(wèn)題,但這是這種方案對(duì)于請(qǐng)求的類(lèi)型有限制,只能get
- 還有一種就可以在開(kāi)發(fā)環(huán)境(本地調(diào)試)期間,進(jìn)行代理, 說(shuō)白了 就是通過(guò) 在本地通過(guò)nodejs 啟動(dòng)一個(gè)微型服務(wù),
- 然后我們先請(qǐng)求我們的微型服務(wù), 微型服務(wù)是服務(wù)端, 服務(wù)端代我們?nèi)フ?qǐng)求我們想要的跨域地址, 因?yàn)榉?wù)端是不受同源策略的限制的, 具體到開(kāi)發(fā)中,打包工具webpack集成了代理的功能,可以采用配置webpack的方式進(jìn)行解決, 但是這種僅限于 本地開(kāi)發(fā)期間, 等項(xiàng)目上線時(shí),還是需要另?yè)翊?nginx
Access-Control-Allow-Origin:*
Access-Control-Allow-Methods:"POST, GET, OPTIONS, DELETE"
以下為webpack配置代理的配置
// vue.config.js
module.exports = {
// 修改的配置
devServer: {
proxy: {
'/api': {
target: 'http://122.51.238.153',
changeOrigin: true,
pathRewrite: {
'^/api': ''
}
}
}
}
}
target:接口域名;
changeOrigin: 如果設(shè)置為true
,那么本地會(huì)虛擬一個(gè)服務(wù)端接收你的請(qǐng)求并代你發(fā)送該請(qǐng)求虑灰;
pathRewrite:如果接口中是沒(méi)有api的吨瞎,那就直接置空(如上)如果接口中有api,就需要寫(xiě)成{‘^/api’:‘’}
上線了如果還有跨域 可以讓后臺(tái)設(shè)置 允許跨域
服務(wù)器代理流程圖
Vue中的watch如何深度監(jiān)聽(tīng)某個(gè)對(duì)象
分析: 此題考查Vue的選項(xiàng)watch的應(yīng)用方式
解析: watch最基本的用法是
上面代碼中: 有個(gè)原則監(jiān)聽(tīng)誰(shuí),寫(xiě)誰(shuí)的名字,然后是對(duì)應(yīng)的執(zhí)行函數(shù), 第一個(gè)參數(shù)為最新的改變值,第二個(gè)值為上一次改變的值, 注意: 除了監(jiān)聽(tīng) data,也可以監(jiān)聽(tīng)計(jì)算屬性 或者一個(gè) 函數(shù)的計(jì)算結(jié)果
那怎么深度監(jiān)聽(tīng)對(duì)象 ,兩種方式
- 字符串嵌套方式
- 啟用深度監(jiān)聽(tīng)方式
export default {
data () {
return {
name: '張三'
}
},
watch: {
name (newValue, oldValue) {
}
}
}
export default {
data () {
return {
a: {
b: {
c :'張三'
}
}
}
},
watch: {
"a.b.c": function (newValue, oldValue) {
}
}
}
export default {
data () {
return {
a: {
b: {
c :'張三'
}
}
}
},
watch: {
a: {
deep: true // deep 為true 意味著開(kāi)啟了深度監(jiān)聽(tīng) a對(duì)象里面任何數(shù)據(jù)變化都會(huì)觸發(fā)handler函數(shù),
handler(){
// handler是一個(gè)固定寫(xiě)法
}
}
}
}
Vue keep-alive使用
分析: 此題考查Vue中組件緩存的使用
解析: keep-alive是 Vue提供的一個(gè)全局組件, Vue的組件是有銷(xiāo)毀機(jī)制的,比如條件渲染, 路由跳轉(zhuǎn)時(shí) 組件都會(huì)經(jīng)歷銷(xiāo)毀, 再次回到頁(yè)面時(shí),又會(huì)回到 重生, 這一過(guò)程保證了生命周期鉤子函數(shù)各個(gè)過(guò)程都會(huì)在這一生命周期中執(zhí)行.
但是,我們辛辛苦苦獲取的數(shù)據(jù) 滑動(dòng)的頁(yè)面 會(huì)因?yàn)榻M件的銷(xiāo)毀 重生 而 歸零,這影響了交互的體驗(yàn), 所以 keep-alvie出現(xiàn)了, 可以幫助我們緩存想要緩存的組件實(shí)例, 只用用keep-alive 包裹你想要緩存的組件實(shí)例, 這個(gè)時(shí)候, 組件創(chuàng)建之后,就不會(huì)再進(jìn)行 銷(xiāo)毀, 組件數(shù)據(jù)和狀態(tài)得以保存
但是,沒(méi)有了銷(xiāo)毀,也就失去了重生的環(huán)節(jié), 我們失去了 原有的鉤子函數(shù), 所以keep-alive包裹的組件 都獲取了另外兩個(gè)事件 --如果緩存組件需要重新獲取數(shù)據(jù)
喚醒 activated重新喚醒休眠組件實(shí)例時(shí) 執(zhí)行: 緩存的組件還提供了activated生命周期 可以在這里面重新發(fā)送請(qǐng)求
休眠 deactivated組件實(shí)例進(jìn)入休眠狀態(tài)時(shí)執(zhí)行
但是我們不能緩存所有的組件實(shí)例, 如果是針對(duì) 組件容器 router-view 這個(gè)組件進(jìn)行的緩存, 一般的策略是在路由的元信息 meta對(duì)象中設(shè)置是否緩存的標(biāo)記, 然后根據(jù)標(biāo)記決定是否進(jìn)行緩存
<div id="app">
<keep-alive>
<!-- 里面是當(dāng)需要緩存時(shí) -->
<router-view v-if="$route.meta.isAlive" />
</keep-alive>
<!-- 外面是不需要緩存時(shí) -->
<router-view v-if="!$route.meta.isAlive" />
</div>
還有需要注意的問(wèn)題是: 被緩存的組件中如果還有子組件, 那么子組件也會(huì)一并擁有 激活和喚醒事件,并且這些事件會(huì)在同時(shí)執(zhí)行
app.vue
<template>
<div id="app">
<div id="nav">
<router-link to="/">Home</router-link> |
<router-link to="/about">About</router-link>
</div>
<!-- <keep-alive> -->
<!-- 里面是當(dāng)需要緩存時(shí) -->
<!-- <router-view v-if="$route.meta.isAlive" /> -->
<!-- </keep-alive> -->
<!-- 外面是不需要緩存時(shí) -->
<!-- <router-view v-if="!$route.meta.isAlive" /> -->
<!-- 這樣寫(xiě)的 組件顯示 就不會(huì)緩存
在路由里面配置的meta 可以直接使用
$route獲取
現(xiàn)在我配置 了 home 不需要緩存
home 每次都重新創(chuàng)建--生命周期會(huì)走一遍
about需要緩存 --你再回到about組件 他不會(huì)重新創(chuàng)建一遍
-->
<router-view v-if="!$route.meta.isAlive"></router-view>
<!-- 如果組件需要緩存 用keep-alive 包裹起來(lái) -->
<keep-alive>
<router-view v-if="$route.meta.isAlive"></router-view>
</keep-alive>
</div>
</template>
<script>
export default {
created(){
// console.log('$route',this.$route)
}
}
</script>
<style lang="less">
*{
margin: 0;
padding: 0;
}
li{
list-style: none;
}
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
}
#nav {
padding: 30px;
a {
font-weight: bold;
color: #2c3e50;
&.router-link-exact-active {
color: #42b983;
}
}
}
</style>
router.js
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'
Vue.use(VueRouter)
const routes = [
{
path: '/',
name: 'Home',
component: Home,
// meta 標(biāo)識(shí)符 也是路由配置里面可以寫(xiě)的
// 他可以用來(lái) 判斷一些操作
meta:{
// 名字:值
isAlive:false // 我想 isAlive false代表不緩存
// 需要緩存的就在這寫(xiě)成 isAlive:true
}
},
{
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.
component: () => import(/* webpackChunkName: "about" */ '../views/About.vue'),
meta:{
isAlive:true // about組件 需要緩存
}
}
]
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
})
export default router
需要緩存的組件穆咐? 最常見(jiàn)的事 列表(因?yàn)楹荛L(zhǎng) 到詳情頁(yè)返回 又回到列表)
keep-alive圖說(shuō)明
vue的雙向數(shù)據(jù)綁定原理是什么
分析 :此題考查 Vue的MVVM原理
解答: Vue的雙向綁定原理其實(shí)就是MVVM的實(shí)現(xiàn)原理, Vuejs官網(wǎng)已經(jīng)說(shuō)明, 實(shí)際就是通過(guò) Object.defineProperty方法 完成了對(duì)于Vue實(shí)例中數(shù)據(jù)的 劫持, 通過(guò)對(duì)于 data中數(shù)據(jù) set的監(jiān)聽(tīng),
然后通過(guò)觀察者模式, 通知 對(duì)應(yīng)的綁定節(jié)點(diǎn) 進(jìn)行節(jié)點(diǎn)數(shù)據(jù)更新, 完成數(shù)據(jù)驅(qū)動(dòng)視圖的更新
同理, 通過(guò)對(duì)于節(jié)點(diǎn)的表單值改變事件的監(jiān)聽(tīng), 執(zhí)行對(duì)于數(shù)據(jù)的修改
簡(jiǎn)單概述 : 通過(guò)Object.defineProperty 完成對(duì)于數(shù)據(jù)的劫持, 通過(guò)觀察者模式, 完成對(duì)于節(jié)點(diǎn)的數(shù)據(jù)更新
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<button id="btn">點(diǎn)擊修改獲取值</button>
<h1 id="con">
name的值是:{{name}}
</h1>
<script>
// Object.defineProperty() 原生js就自帶的方法
// vue 也是js 他就是一個(gè)封裝了 js的 庫(kù)而已
// Object.defineProperty() 方法會(huì)直接在一個(gè)對(duì)象上定義一個(gè)新屬性颤诀,或者修改一個(gè)對(duì)象的現(xiàn)有屬性字旭, 并返回這個(gè)對(duì)象。
// vue的原理
// Object.defineProperty(對(duì)象,屬性名,{ get set 等配置 })
// data.name='李四' 設(shè)置值 就會(huì)觸發(fā) set
// vue 原理
// vue 通過(guò) 原生js的 Object.defineProperty 監(jiān)聽(tīng)到了 我們寫(xiě)的data數(shù)據(jù)
// 這個(gè)data里面的數(shù)據(jù) 有修改 就會(huì)觸發(fā) Object.defineProperty 里面的 set
// 在set里面 我們可以 獲取到最新的修改的值 去頁(yè)面上 正則匹配到對(duì)應(yīng)地方 替換修改
// 你看過(guò)vue 源碼 如果沒(méi)看過(guò)就說(shuō) 沒(méi)怎么看過(guò) 只是了解了一下 稍微寫(xiě)了一下
function Vue(){
this.data={
name:'zs'
}
// 那 vue的data 那么多數(shù)據(jù)怎么辦崖叫?
// vue里面 就循環(huán)執(zhí)行下面這段話 不就全部data 監(jiān)聽(tīng)到了嗎遗淳?
// for()
Object.defineProperty(this.data,'name',{
get:function(){
// 當(dāng)獲取監(jiān)聽(tīng)對(duì)象的某個(gè) 值 就可以 執(zhí)行g(shù)et函數(shù)
console.log('get 獲取了值')
},
set:function(newval){ // 設(shè)置的新值
console.log('set 設(shè)置了值',newval)
// 當(dāng)然vue 沒(méi)有這么簡(jiǎn)單去找 他寫(xiě)了很多正則表達(dá)式去替換
// 但是思路是這個(gè)
// 我只需要 監(jiān)聽(tīng)到 name值改了 就去頁(yè)面修改 對(duì)應(yīng)的地方就行 變成新值
let con=document.getElementById("con")
// con.innerHTML 獲取內(nèi)容 name的值是:{{name}} .replace("查找的字符串","替換成這個(gè)")
let str=con.innerHTML.replace("{{name}}",newval)
// 重新修內(nèi)容 innerHTML 是獲取內(nèi)容 設(shè)置內(nèi)容的
con.innerHTML=str
}
})
}
let vm=new Vue()
// vm.data
// console.log(data.name) ;// 獲取
// vue 的核心 如果數(shù)據(jù)改變了 那么頁(yè)面就跟著改變成最新數(shù)據(jù)了
// 為什么vue可以知道你的數(shù)據(jù)更新了?
// 因?yàn)関ue 幫我監(jiān)聽(tīng)了 set 然后你只要設(shè)置值 就觸發(fā)set 只需要在set里面找到頁(yè)面對(duì)應(yīng)的數(shù)據(jù)修改就行
document.getElementById("btn").onclick=function(){
// data.name='小雷'
// console.log(data.name) ;// 這就是獲取值
vm.data.name='李四'
}
</script>
</body>
</html>
頁(yè)面刷新了之后vuex中的數(shù)據(jù)消失怎么解決
分析:此題考查 如果將vuex數(shù)據(jù)進(jìn)行本地持久化
解析: vuex數(shù)據(jù)位于內(nèi)存, 頁(yè)面的刷新重置會(huì)導(dǎo)致數(shù)據(jù)的歸零,也就是所謂的消失, 本地持久化可以解決這個(gè)問(wèn)題.本地持久化用到的技術(shù)也就是 本次存儲(chǔ) sesstionStorage 或者 localStorage ,
如果需要保持的更長(zhǎng)久 ,瀏覽器關(guān)掉 再打開(kāi)依然存有數(shù)據(jù),需要使用后者
實(shí)施方案: state的持久化 也就是分別需要在 state數(shù)據(jù)初始化 /更新 的時(shí)候 進(jìn)行讀取和設(shè)置本地存儲(chǔ)操作
代碼如下
export default new Vuex.store({
state: {
user: localStorge.getItem('user') // 初始化時(shí)讀取 本地存儲(chǔ)
},
mutations: {
updateUser (state, payload) {
state.user = payload.user
localStoregae.setItem('user',payload.user) // 數(shù)據(jù)更新時(shí) 設(shè)置本地存儲(chǔ)
}
}
})
vue做服務(wù)端渲染
分析: 為什么要做服務(wù)端渲染, 首先要明白 服務(wù)端渲染解決什么問(wèn)題
解析: vuejs 官網(wǎng)說(shuō)的很明白, 要做服務(wù)端渲染首先必須是有對(duì)應(yīng)的需求,即對(duì) 實(shí)時(shí)到達(dá)時(shí)間(頁(yè)面訪問(wèn)時(shí)間)的絕對(duì)需求. 如果只是簡(jiǎn)單的一個(gè)管理系統(tǒng), 區(qū)區(qū)幾百毫秒的優(yōu)化 顯得十分小題大做.
服務(wù)端渲染這里 有一個(gè)成熟優(yōu)秀的框架 nuxt.js , 正如next.js對(duì)于react,nuxt是vue服務(wù)端渲染的優(yōu)秀解決方案
nuxt的出現(xiàn)可以讓渲染內(nèi)容完全服務(wù)端化,解決seo不夠友好, 首屏渲染速度不夠迅速的問(wèn)題,
但是這里需要注意: 并不是所有頁(yè)面都需要服務(wù)端渲染, 因?yàn)榉?wù)端渲染比重多大 對(duì)于服務(wù)器的訪問(wèn)處理能力 要求也會(huì)急劇增大
步驟這個(gè)nuxt腳手架不需要安裝node,默認(rèn)自帶
1 腳手架 npx create-nuxt-app <項(xiàng)目名>
2 yarn dev 啟動(dòng)開(kāi)發(fā)
上線
yarn build
yarn start
為什么使用nuxt.js?
普通vue項(xiàng)目 打開(kāi)地址查看源代碼 是空 他主要是用切換的時(shí)候才會(huì)有內(nèi)容
nuxt.js項(xiàng)目 查看源代碼 他是已經(jīng)渲染好了很多html了
- 這個(gè)和seo 搜索引擎 比如百度 他會(huì)去 找到所有網(wǎng)站 挨個(gè)看你的網(wǎng)站內(nèi)容 有沒(méi)有 好不好--爬蟲(chóng)
如果普通vue 項(xiàng)目 是 空的 那么 就沒(méi)有內(nèi)容 seo不行 網(wǎng)站就很垃圾
如果nuxt.js項(xiàng)目 有內(nèi)容 就比較好 利于seo
- 普通vue項(xiàng)目 內(nèi)容打包到j(luò)s了 那個(gè)js會(huì)很大 首頁(yè)就顯示很慢
如果nuxt.js項(xiàng)目 只是一些 js 其他的他服務(wù)器端就渲染好了 稍微快
vue單頁(yè)面應(yīng)用渲染是從服務(wù)器獲取所需js心傀,在客戶(hù)端將其解析生成html掛載于
id為app的DOM元素上屈暗,這樣會(huì)存在兩大問(wèn)題。
- 由于資源請(qǐng)求量大脂男,造成網(wǎng)站首屏加載緩慢养叛,不利于用戶(hù)體驗(yàn)。
- 由于頁(yè)面內(nèi)容通過(guò)js插入宰翅,對(duì)于內(nèi)容性網(wǎng)站來(lái)說(shuō)一铅,搜索引擎無(wú)法抓取網(wǎng)站內(nèi)容,不利于SEO堕油。
Nuxt.js 是一個(gè)基于Vue.js的通用應(yīng)用框架潘飘,預(yù)設(shè)了利用Vue.js開(kāi)發(fā)服務(wù)端渲染的應(yīng)用所需要的各種配置〉羧保可以將html在服務(wù)端渲染卜录,合成完整的html文件再輸出到瀏覽器。
除此之外眶明,nuxt與vue還有一些其他方面的區(qū)別艰毒。
-
路由
nuxt按照 pages 文件夾的目錄結(jié)構(gòu)自動(dòng)生成路由
vue需在 src/router/index.js 手動(dòng)配置路由 -
入口頁(yè)面
nuxt頁(yè)面入口為 layouts/default.vue
vue頁(yè)面入口為 src/App.vue -
webpack配置
nuxt內(nèi)置webpack,允許根據(jù)服務(wù)端需求搜囱,在 nuxt.config.js 中的build屬性自定義構(gòu)建webpack的配置丑瞧,覆蓋默認(rèn)配置
vue關(guān)于webpack的配置存放在build文件夾下 - asyncData 里面發(fā)送ajax 這個(gè)東西跟生命周期這些都是平級(jí)的
要理解asyncData方法執(zhí)行時(shí),其實(shí)是在服務(wù)端完成的蜀肘,這個(gè)數(shù)據(jù)是在服務(wù)端渲染好了的
nuxt.js的ajax绊汹,你先別往你那個(gè)異步上去思考,其實(shí)這里面所有的ajax最后都會(huì)形成頁(yè)面扮宠。你別想著西乖,我一點(diǎn)按鈕,調(diào)用一個(gè)方法坛增,然后再ajax去加載數(shù)據(jù)获雕。因?yàn)槲覀冏詈笕慷紩?huì)生成靜態(tài),所以任何的獲取數(shù)據(jù)的操作收捣,最后都會(huì)變成頁(yè)面的跳轉(zhuǎn)届案。
所以,官方給了一套寫(xiě)法罢艾,你必須按照這個(gè)去寫(xiě)楣颠,
并且這里的ajax會(huì)再頁(yè)面渲染之前就執(zhí)行嫁乘。這個(gè)東西跟生命周期這些都是平級(jí)的。
1 npm install @nuxtjs/axios --save
2 .plugins目錄新建axios.js
import * as axios from 'axios'
let options ={}
//需要全路徑才能工作
if(process.server){
options.baseURL=http://${process.env.HOST || 'localhost'}:${process.env.PORT || 3000}/api
}
export default axios.create(options)
3.Nuxt.config.js增加axios配置
modules:[
'@nuxtjs/axios'
],
4 使用 asyncData 里面發(fā)送ajax 這個(gè)東西跟生命周期這些都是平級(jí)的 在頁(yè)面渲染之前
export default {
async asyncData({app}){
let res =await app.$axios({
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
method: 'get',
url: `http://test.yms.cn/testjson.asp`,
data: ''
})
// app.$axios
console.log('res',res.data)
return{
testData:res.data.title
}
},
created(){
console.log('nuxt reg組件')
}
}
下圖為關(guān)于nuxt的簡(jiǎn)單概述
vue-router傳參
分析:考查vue-router的傳值方式
解析 vue-router 傳值 可以通過(guò) 地址傳值
最簡(jiǎn)單的就是url傳值, url傳值又兩種, params 和 query參數(shù)傳值
- params傳值 是指的動(dòng)態(tài)路由傳值
- query傳值,指通過(guò)?后面的拼接參數(shù)傳值
{ path: '/user/:id' } // 定義一個(gè)路由參數(shù)
<router-link to="/user/123"></router-link> // 傳值
this.$route.params.id // 取值 params參數(shù)
<router-link to="/user?id=123"></router-link> // 傳值
this.$route.query.id // 取值 query參數(shù)
前端鑒權(quán)一般思路
以前講過(guò) 我們可以在axios的球碉,請(qǐng)求攔截器里面配置token
- 有些axios請(qǐng)求需要token,我們是可以陪著請(qǐng)求攔截器
- 有些頁(yè)面需要登錄才能看蜓斧,我們也可以路由導(dǎo)航守衛(wèi), router.beforeEach,判斷token
- 導(dǎo)航菜單欄睁冬,一般后臺(tái)側(cè)邊欄挎春,有不同的人登錄,根據(jù)角色權(quán)限看到的欄目不一樣
分析: 考查前后分離的鑒權(quán)思路
**解析**
: 首先要明白 為什么要在前端鑒權(quán)? 因?yàn)閭鹘y(tǒng)項(xiàng)目都是在后端鑒權(quán), 然后通過(guò)進(jìn)行攔截 跳轉(zhuǎn) 對(duì)應(yīng)操作
因?yàn)?我們做的并不是傳統(tǒng)的項(xiàng)目,而是前后分離項(xiàng)目,也就是前端項(xiàng)目和后端服務(wù)進(jìn)行了**剝離**
, 后端沒(méi)有辦法用session來(lái)存儲(chǔ)你任意一個(gè)前端項(xiàng)目域名下的身份信息, 所以jwt 鑒權(quán)模式應(yīng)運(yùn)而生.
也就是后端不再提供會(huì)話的身份存儲(chǔ),而是通過(guò)一個(gè)鑒權(quán)接口將用戶(hù)的身份,登錄時(shí)間,請(qǐng)求端口,協(xié)議頭..等等信息 組裝成一個(gè)加密的串 返給前端請(qǐng)求, 前端拿到了這個(gè)串,就可以認(rèn)為自己登錄成功
那么這個(gè)**加密串**
就成了 前端用戶(hù)是否登錄的成功標(biāo)志, 這就是我們的token , 那么在接下來(lái)的接口請(qǐng)求中,我們幾乎都要攜帶這個(gè)加密串,因?yàn)樗?code>**唯一**能**證明我們身份**
的信息.
為了方便,我們會(huì)一般在請(qǐng)求工具 axios(舉例)的攔截器中**統(tǒng)一注入token**
, 減少代碼的重復(fù)
token 同時(shí)具有時(shí)效性,我們也需要在此時(shí)對(duì)token過(guò)期進(jìn)行處理,一旦出現(xiàn)過(guò)期的請(qǐng)求碼, 就需要進(jìn)行 換取新token 或者重新登錄的解決方案
除此之外,我們還需要依據(jù)**有無(wú)加密串**
在前端對(duì)于某些頁(yè)面的訪問(wèn)進(jìn)行限制, 這個(gè)會(huì)用到我們的Vue-Router中的導(dǎo)航守衛(wèi).
vue 單頁(yè)項(xiàng)目涉及到多角色用戶(hù)權(quán)限問(wèn)題豆拨,不同的角色用戶(hù)擁有不同的功能權(quán)限直奋, 不同的功能權(quán)限對(duì)應(yīng)的不同的頁(yè)面
一開(kāi)始 有一些 默認(rèn)的路由
登錄后 比如你是總經(jīng)理 后臺(tái)會(huì)返回給前端 總經(jīng)理能看見(jiàn)的 路由頁(yè)面地址 數(shù)組
前端在router.beforeEach 路由導(dǎo)航守衛(wèi)里面 拿到返回的地址 使用 router.addRouter 動(dòng)態(tài)加上 這個(gè)項(xiàng)目路由就好了
routes= 后臺(tái)返回的 符合條件的 路由數(shù)據(jù) 類(lèi)似我們自己寫(xiě)的那個(gè)path 等等
this.$router.addRoutes(routes)
例子
router.beforeEach((to, from, next) => {
//判斷user信息是否已經(jīng)獲取
if (token) {
//根據(jù)用戶(hù)的角色類(lèi)型來(lái)生成對(duì)應(yīng)的新路由
const newRouter = [{path:"/xxx" ...} ..]
//將新路由添加到路由中
router.addRoutes(newRouter)
//為了正確渲染導(dǎo)航,將對(duì)應(yīng)的新的路由添加到vuex中
渲染對(duì)應(yīng)的側(cè)邊欄
}
})
獲取路由數(shù)組的流程圖
前端如何做?
- 寫(xiě)一個(gè)所有的路由數(shù)組
- 根據(jù)后臺(tái)返回路由列表權(quán)限施禾,拿著兩個(gè)數(shù)組對(duì)比脚线,處理數(shù)據(jù)得到需要的路由數(shù)組
vue數(shù)據(jù)流 和 react數(shù)據(jù)流
vue,react數(shù)據(jù)流不是雙向的數(shù)據(jù)綁定弥搞,是單向的邮绿。
在vue 、React中數(shù)據(jù)流向是單向的攀例,由父節(jié)點(diǎn)流向子節(jié)點(diǎn)船逮,如果父節(jié)點(diǎn)的props發(fā)生了改變,那么React會(huì)遞歸遍歷整個(gè)組件
父組件通過(guò)綁定 props 的方式粤铭,將數(shù)據(jù)傳遞給子組件挖胃,但是子組件自己并沒(méi)有權(quán)利修改這些數(shù)據(jù),如果要修改梆惯,只能把修改這一個(gè)行為通過(guò) event 的方式報(bào)告給父組件酱鸭,由父組件本身決定改如何處理數(shù)據(jù)。
vue 另一個(gè)概念 v-model雙向數(shù)據(jù) 無(wú)論數(shù)據(jù)改變垛吗,或是用戶(hù)操作凹髓,都能帶來(lái)互相的變動(dòng),自動(dòng)更新职烧。
如何在組件中監(jiān)聽(tīng)Vuex的數(shù)據(jù)變化
分析: 此題考查Vuex的應(yīng)用及 Vue內(nèi)部的監(jiān)聽(tīng)數(shù)據(jù)變化的機(jī)制
解答: 首先確定 Vuex是為了解決什么問(wèn)題而出現(xiàn)的 ? Vuex是為了解決組件間狀態(tài)共享而出現(xiàn)的一個(gè)框架.
其中有幾個(gè)要素 是組成Vuex的關(guān)鍵, state(狀態(tài)) mutations actions ,
- state 表示 需要共享的狀態(tài)數(shù)據(jù)
- mutations 表示 更改 state的方法集合 只能是同步更新 不能寫(xiě)ajax等異步請(qǐng)求
- actions 如果需要做異步請(qǐng)求 可以在actions中發(fā)起 然后提交給 mutations mutation再做同步更新
也就是 state 負(fù)責(zé)管理狀態(tài) , mutation負(fù)責(zé)同步更新?tīng)顟B(tài) action負(fù)責(zé) 異步獲取數(shù)據(jù) 同提交給mutation
所以 組件監(jiān)聽(tīng)Vuex數(shù)據(jù)變化 就是 監(jiān)聽(tīng) Vuex中state的變化,
1. 我們可以在組件中通過(guò)組件的 watch方法來(lái)做, 因?yàn)榻M件可以將state數(shù)據(jù)映射到 組件的計(jì)算屬性上,
然后 監(jiān)聽(tīng) 映射的計(jì)算屬性即可 代碼如下
// vuex中的state數(shù)據(jù)
state: {
count: 0
},
// A組件中映射 state數(shù)據(jù)到計(jì)算屬性
computed: {
...mapState(['count'])
}
// A組件監(jiān)聽(tīng) count計(jì)算屬性的變化
watch: {
count () {
// 用本身的數(shù)據(jù)進(jìn)行一下計(jì)數(shù)
this.changeCount++
}
}
2. vuex中store對(duì)象本身提供了watch
函數(shù) ,可以利用該函數(shù)進(jìn)行監(jiān)聽(tīng)
- watch(fn: Function, callback: Function, options?: Object): Function
響應(yīng)式地偵聽(tīng) fn
的返回值扁誓,當(dāng)值改變時(shí)調(diào)用回調(diào)函數(shù)防泵。fn
接收 store 的 state 作為第一個(gè)參數(shù)蚀之,其 getter 作為第二個(gè)參數(shù)。最后接收一個(gè)可選的對(duì)象參數(shù)表示 Vue 的 [vm.$watch](https://cn.vuejs.org/v2/api/#vm-watch)
方法的參數(shù)捷泞。
代碼
created () {
this.$store.watch((state, getters) => {
return state.count
}, () => {
this.changeCount++
})
}
Vue單頁(yè)面和多頁(yè)面的使用
<>
分析: 首先分析,單頁(yè)面應(yīng)用和 多頁(yè)面應(yīng)用的根本區(qū)別
**解答**
: 單頁(yè)面即所有的模塊統(tǒng)統(tǒng)置于一個(gè)html文件之上,切換模塊,不會(huì)重新對(duì)html文件和資源進(jìn)行再次請(qǐng)求,服務(wù)器不會(huì)對(duì)我們**換頁(yè)面**
的動(dòng)作 產(chǎn)生任何反應(yīng), 所以我們感覺(jué)不到任何的刷新動(dòng)作,速度和體驗(yàn)很暢快多頁(yè)面應(yīng)用 即多個(gè)html頁(yè)面 共同的使用, 可以認(rèn)為一個(gè)頁(yè)面即一個(gè)模塊,但是不排除 多個(gè)單頁(yè)應(yīng)用混合到一起的組合情況 , 多頁(yè)面切換一定會(huì)造成 頁(yè)面資源的重新加載, 這也就意味著 如果 多頁(yè)面之間切換,一定會(huì)造成很數(shù)據(jù)的
**重置**
一個(gè)項(xiàng)目分成很多 小vue項(xiàng)目 你去其實(shí)也可以直接創(chuàng)建兩個(gè)項(xiàng)目
1 **新建多個(gè)頁(yè)面 每個(gè)頁(yè)面是一個(gè)單獨(dú)的小vue類(lèi)型 **
2 配置 多入口頁(yè)面在vue.config.js里寫(xiě)上這些 重點(diǎn)是入口選擇對(duì)應(yīng)頁(yè)面的main.js
// vue.config.js
module.exports = {
// 我配置完成 和 文件夾 匹配好
// 相當(dāng)于 寫(xiě)了兩套項(xiàng)目 vue代碼
// pages 配置 多頁(yè)面入口 index 和ui
// 配置和 你的文件夾匹配 兩套 文件
pages: {
index: {
// page 的入口
entry: "src/views/index/main.js",
// 模板來(lái)源
template: "public/index.html",
// 在 dist/index.html 的輸出
filename: "index.html",
// 當(dāng)使用 title 選項(xiàng)時(shí)足删,
// template 中的 title 標(biāo)簽需要是 <title><%= htmlWebpackPlugin.options.title %></title>
title: "Index Page"
},
ui: {
// page 的入口
entry: "src/views/ui/main.js",
// 模板來(lái)源
template: "public/ui.html",
// 在 dist/ui.html 的輸出
filename: "ui.html",
// 當(dāng)使用 title 選項(xiàng)時(shí),
// template 中的 title 標(biāo)簽需要是 <title><%= htmlWebpackPlugin.options.title %></title>
title: "ui Page"
}
// 锁右。失受。讶泰。。
}
};
3 public 寫(xiě)上不同的渲染的 html
4 main.js 不同的入口 對(duì)應(yīng)上自己的 根組件和 頁(yè)面元素
5 通過(guò)a標(biāo)簽跳轉(zhuǎn)
<div id="app">
ui頁(yè)面啊啊啊
<a href="home.html">去home頁(yè)面</a>
</div>
關(guān)注:程序員石磊拂到,獲取更多面試資料