2021前端面試題系列: VUE相關(guān)的基礎(chǔ)面試題

大家好,我是前端嵐楓铐刘,今天主要跟大家分享我整理的筆記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傳值‘

  1. 父 子 傳值 使用props接受
  2. 子 父 傳值 父親寫(xiě)事件函數(shù) 子 $emit觸發(fā) 傳值
  3. 兄弟傳值 $bus 中轉(zhuǎn)站
  4. 如果組件之間 關(guān)系很遠(yuǎn) 是很多組件都要用的值 vuex
  5. provide, inject注入方式

vuex 就是一個(gè)全局狀態(tài)數(shù)據(jù)管理 簡(jiǎn)單來(lái)說(shuō) 他的數(shù)據(jù)類(lèi)似全局變量 哪個(gè)組件都可以使用

在項(xiàng)目中使用vuex

  1. 下載 vuex 包 并導(dǎo)入 use一下
import Vuex from 'vuex'
Vue.use(Vuex)
  1. 需要new 一下 寫(xiě)上全局?jǐn)?shù)據(jù)
// store
new Vuex.Store({
state: {
count:1 //這個(gè)count 就是全局的數(shù)據(jù)
},
mutations: {
},
actions: {
}
})

  1. 需要掛載到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)題的方式有幾種,

  1. 一種是服務(wù)端設(shè)置 , 但這種方式依賴(lài)服務(wù)端的設(shè)置,在前后分離的場(chǎng)景下 ,不太方便
  2. 還有一種jsonp形式, 可以利用script標(biāo)簽 的特性解決同源策略帶來(lái)的跨域問(wèn)題,但這是這種方案對(duì)于請(qǐng)求的類(lèi)型有限制,只能get
  3. 還有一種就可以在開(kāi)發(fā)環(huán)境(本地調(diào)試)期間,進(jìn)行代理, 說(shuō)白了 就是通過(guò) 在本地通過(guò)nodejs 啟動(dòng)一個(gè)微型服務(wù),
  4. 然后我們先請(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ì)象 ,兩種方式

  1. 字符串嵌套方式
  2. 啟用深度監(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ō)明

image.png

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ù)端渲染

nuxt官網(wǎng)文檔

分析: 為什么要做服務(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了

  1. 這個(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

  1. 普通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)題。

  1. 由于資源請(qǐng)求量大脂男,造成網(wǎng)站首屏加載緩慢养叛,不利于用戶(hù)體驗(yàn)。
  2. 由于頁(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ū)別艰毒。

  1. 路由
    nuxt按照 pages 文件夾的目錄結(jié)構(gòu)自動(dòng)生成路由
    vue需在 src/router/index.js 手動(dòng)配置路由
  2. 入口頁(yè)面
    nuxt頁(yè)面入口為 layouts/default.vue
    vue頁(yè)面入口為 src/App.vue
  3. webpack配置
    nuxt內(nèi)置webpack,允許根據(jù)服務(wù)端需求搜囱,在 nuxt.config.js 中的build屬性自定義構(gòu)建webpack的配置丑瞧,覆蓋默認(rèn)配置
    vue關(guān)于webpack的配置存放在build文件夾下
  4. asyncData 里面發(fā)送ajax 這個(gè)東西跟生命周期這些都是平級(jí)的
image.png

要理解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)單概述

image.png

vue-router傳參

分析:考查vue-router的傳值方式

解析 vue-router 傳值 可以通過(guò) 地址傳值

最簡(jiǎn)單的就是url傳值, url傳值又兩種, params 和 query參數(shù)傳值

  1. params傳值 是指的動(dòng)態(tài)路由傳值
  2. 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

  1. 有些axios請(qǐng)求需要token,我們是可以陪著請(qǐng)求攔截器
  2. 有些頁(yè)面需要登錄才能看蜓斧,我們也可以路由導(dǎo)航守衛(wèi), router.beforeEach,判斷token
  3. 導(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ù)組的流程圖

image.png

前端如何做?

  1. 寫(xiě)一個(gè)所有的路由數(shù)組
  2. 根據(jù)后臺(tái)返回路由列表權(quán)限施禾,拿著兩個(gè)數(shù)組對(duì)比脚线,處理數(shù)據(jù)得到需要的路由數(shù)組

vue數(shù)據(jù)流 和 react數(shù)據(jù)流

vue,react數(shù)據(jù)流不是雙向的數(shù)據(jù)綁定弥搞,是單向的邮绿。
vueReact數(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ù)。

image.png

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 ,

  1. state 表示 需要共享的狀態(tài)數(shù)據(jù)
  2. mutations 表示 更改 state的方法集合 只能是同步更新 不能寫(xiě)ajax等異步請(qǐng)求
  3. 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++
    }
  }
image.png

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)型 **

image.png

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

image.png

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)注:程序員石磊拂到,獲取更多面試資料

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末痪署,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子兄旬,更是在濱河造成了極大的恐慌狼犯,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,214評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件领铐,死亡現(xiàn)場(chǎng)離奇詭異悯森,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)绪撵,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)瓢姻,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人音诈,你說(shuō)我怎么就攤上這事幻碱。” “怎么了细溅?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,543評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵收班,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我谒兄,道長(zhǎng)摔桦,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,221評(píng)論 1 279
  • 正文 為了忘掉前任承疲,我火速辦了婚禮邻耕,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘燕鸽。我一直安慰自己兄世,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布啊研。 她就那樣靜靜地躺著御滩,像睡著了一般。 火紅的嫁衣襯著肌膚如雪党远。 梳的紋絲不亂的頭發(fā)上削解,一...
    開(kāi)封第一講書(shū)人閱讀 49,007評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音沟娱,去河邊找鬼氛驮。 笑死,一個(gè)胖子當(dāng)著我的面吹牛济似,可吹牛的內(nèi)容都是我干的矫废。 我是一名探鬼主播盏缤,決...
    沈念sama閱讀 38,313評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼蓖扑!你這毒婦竟也來(lái)了唉铜?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 36,956評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤律杠,失蹤者是張志新(化名)和其女友劉穎打毛,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體俩功,經(jīng)...
    沈念sama閱讀 43,441評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡幻枉,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了诡蜓。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片熬甫。...
    茶點(diǎn)故事閱讀 38,018評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖蔓罚,靈堂內(nèi)的尸體忽然破棺而出椿肩,到底是詐尸還是另有隱情,我是刑警寧澤豺谈,帶...
    沈念sama閱讀 33,685評(píng)論 4 322
  • 正文 年R本政府宣布郑象,位于F島的核電站,受9級(jí)特大地震影響茬末,放射性物質(zhì)發(fā)生泄漏厂榛。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評(píng)論 3 307
  • 文/蒙蒙 一丽惭、第九天 我趴在偏房一處隱蔽的房頂上張望击奶。 院中可真熱鬧,春花似錦责掏、人聲如沸柜砾。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,240評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)痰驱。三九已至,卻和暖如春瞳浦,著一層夾襖步出監(jiān)牢的瞬間担映,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,464評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工术幔, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留另萤,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,467評(píng)論 2 352
  • 正文 我出身青樓诅挑,卻偏偏與公主長(zhǎng)得像四敞,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子拔妥,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • 1忿危、說(shuō)一下Vue的優(yōu)點(diǎn) 體積小,更高的運(yùn)行效率没龙,雙向數(shù)據(jù)綁定铺厨,生態(tài)豐富、學(xué)習(xí)成本低 2硬纤、v-show和v-if的共...
    瘋的很理智閱讀 3,245評(píng)論 0 21
  • 1解滓、移動(dòng)端你遇到過(guò)什么兼容問(wèn)題?1、如果在input設(shè)置邊框顏色在ios系統(tǒng)里會(huì)出現(xiàn)兼容性問(wèn)題筝家,需要在外面加一個(gè)d...
    阿帕奇喲閱讀 795評(píng)論 0 8
  • 1洼裤、移動(dòng)端你遇到過(guò)什么兼容問(wèn)題? 1、如果在input設(shè)置邊框顏色在ios系統(tǒng)里會(huì)出現(xiàn)兼容性問(wèn)題溪王,需要在外面加一個(gè)...
    青青菜鳥(niǎo)閱讀 4,399評(píng)論 0 28
  • 一腮鞍、CSS問(wèn)題 1.flex布局 display:flex; 在父元素設(shè)置,子元素受彈性盒影響莹菱,默認(rèn)排成一行移国,如果...
    陳二狗想吃肉閱讀 551評(píng)論 0 9
  • 談?wù)勀銓?duì)MVVM開(kāi)發(fā)模式的理解 MVVM分為Model、View道伟、ViewModel三者迹缀。 Model 代表數(shù)據(jù)模...
    廖若晨閱讀 1,283評(píng)論 0 4