vue相關知識點

vue中的MVVM模式

即Model-View-ViewModel。vue

Vue是以數據爲驅動的,Vue自身將DOM和數據進行綁定,一旦建立綁定,DOM和數據將保持同步,每當數據發生變化,DOM會跟着變化。ios

ViewModel是Vue的核心,它是Vue的一個實例。Vue實例時做用域某個HTML元素上的,這個HTML元素能夠是body,也能夠是某個id所指代的元素。ajax

DOM Listeners和Data Bindings是實現雙向綁定的關鍵。vue-router

DOM Listeners監聽頁面全部View層DOM元素的變化,當發生變化,Model層的數據隨之變化;Data Bindings監聽Model層的數據,當數據發生變化,View層的DOM元素隨之變化。vuex

vue的生命週期

beforeCreate階段: vue實例的掛載元素$el和數據對象data都爲undefined,還爲初始化。

created階段:vue實例的數據對象data有了,$el尚未

beforeMount階段:vue實例的$el和data都初始化了,但仍是掛載以前爲虛擬的DOM節點,data還沒有替換。

mounted階段:vue實例掛載完成,data成功渲染。

beforeUpdate/updated階段:
當data變化時,會觸發beforeUpdate和updated方法。這兩個不經常使用,不推薦使用。

beforeDestory/destoryed階段:
beforeDestory是在vue實例銷燬前觸發,通常在這裏要經過removeEventListener解除手動綁定的事件。實例銷燬後,觸發的destroyed。
複製代碼

vue的數據雙向綁定原理

vue.js 是採用數據劫持結合發佈者-訂閱者模式的方式,經過Object.defineProperty()來劫持各個屬性的setter,getter,在數據變更時發佈消息給訂閱者,觸發相應的監聽回調。json

具體步驟:axios

第一步:須要observe的數據對象進行遞歸遍歷,包括子屬性對象的屬性,都加上 setter和getter 這樣的話,給這個對象的某個值賦值,就會觸發setter,那麼就能監聽到了數據變化後端

第二步:compile解析模板指令,將模板中的變量替換成數據,而後初始化渲染頁面視圖,並將每一個指令對應的節點綁定更新函數,添加監聽數據的訂閱者,一旦數據有變更,收到通知,更新視圖api

第三步:Watcher訂閱者是Observer和Compile之間通訊的橋樑,主要作的事情是: 一、在自身實例化時往屬性訂閱器(dep)裏面添加本身 二、自身必須有一個update()方法 三、待屬性變更dep.notice()通知時,能調用自身的update()方法,並觸發Compile中綁定的回調,則功成身退。緩存

第四步:MVVM做爲數據綁定的入口,整合Observer、Compile和Watcher三者,經過Observer來監聽本身的model數據變化,經過Compile來解析編譯模板指令,最終利用Watcher搭起Observer和Compile之間的通訊橋樑,達到數據變化 -> 視圖更新;視圖交互變化(input) -> 數據model變動的雙向綁定效果。

組件中 data 爲何是函數

由於組件是用來複用的,JS 裏對象是引用關係,這樣做用域沒有隔離,而 new Vue 的實例,是不會被複用的,所以不存在引用對象的問題。

v-model是什麼?怎麼使用? vue中標籤怎麼綁定事件?

答:能夠實現雙向綁定,指令(v-class、v-for、v-if、v-show、v-on)。vue的model層的data屬性。綁定事件:<input @click=doLog() />

v-show和v-if指令的共同點和不一樣點?

v-show指令是經過修改元素的displayCSS屬性讓其顯示或者隱藏

v-if指令是直接銷燬和重建DOM達到讓元素顯示和隱藏的效果

如何讓CSS只在當前組件中起做用?

將當前組件的<style>修改成<style scoped>

<keep-alive></keep-alive>的做用是什麼?

<keep-alive></keep-alive> 包裹動態組件時,會緩存不活動的組件實例,主要用於保留組件狀態或避免從新渲染。

指令v-el的做用是什麼?

提供一個在頁面上已存在的 DOM 元素做爲 Vue 實例的掛載目標.能夠是 CSS 選擇器,也能夠是一個 HTMLElement 實例

自定義指令(v-check、v-focus)的方法有哪些?它有哪些鉤子函數?還有哪些鉤子函數參數?

答:全局定義指令:在vue對象的directive方法裏面有兩個參數,一個是指令名稱,另一個是函數。組件內定義指令:directives

鉤子函數:bind(綁定事件觸發)、inserted(節點插入的時候觸發)、update(組件內相關更新)

鉤子函數參數:el、binding

Vue.js中ajax請求代碼應該寫在組件的methods中仍是vuex的actions中?

若是請求來的數據是否是要被其餘組件公用,僅僅在請求的組件內使用,就不須要放入vuex 的state裏。

若是被其餘地方複用,這個很大概率上是須要的,若是須要,請將請求放入action裏,方便複用.

computed 和 watch 的區別:

computed 是計算屬性,依賴其餘屬性計算值,而且 computed 的值有緩存,只有當計算值變化纔會返回內容。

watch 監聽到值的變化就會執行回調,在回調中能夠進行一些邏輯操做。因此通常來講須要依賴別的屬性來動態得到值的時候可使用 computed,對於監聽到值的變化須要作一些複雜業務邏輯的狀況可使用 watch。

Vue中給data中的對象屬性添加一個新的屬性時會發生什麼,如何解決?

問題: obj.b已經成功添加,可是視圖並未刷新

緣由:緣由在於在Vue實例建立時,obj.b並未聲明,所以就沒有被Vue轉換爲響應式的屬性,天然就不會觸發視圖的更新,這時就須要使用Vue的全局api $set()

方法:$set()方法至關於手動的去把obj.b處理成一個響應式的屬性,此時視圖也會跟着改變了

Vue組件間的參數傳遞

父組件與子組件傳值

父組件傳給子組件:子組件經過props方法接受數據;

子組件傳給父組件:$emit方法傳遞參數

非父子組件間的數據傳遞,兄弟組件傳值

eventBus,就是建立一個事件中心,至關於中轉站,能夠用它來傳遞事件和接收事件。項目比較小時,用這個比較合適。

vuex是什麼?怎麼使用?哪一種功能場景使用它?

只用來讀取的狀態集中放在store中; 改變狀態的方式是提交mutations,這是個同步的事物; 異步邏輯應該封裝在action中。

在main.js引入store,注入。新建了一個目錄store,….. export 。

場景有:單頁應用中,組件之間的狀態、音樂播放、登陸狀態、加入購物車 圖片描述

state

Vuex 使用單一狀態樹,即每一個應用將僅僅包含一個store 實例,但單一狀態樹和模塊化並不衝突。存放的數據狀態,不能夠直接修改裏面的數據。

mutations

mutations定義的方法動態修改Vuex 的 store 中的狀態或數據。

getters

相似vue的計算屬性,主要用來過濾一些數據。

action

actions能夠理解爲經過將mutations裏面處裏數據的方法變成可異步的處理數據的方法,簡單的說就是異步操做數據。view 層經過 store.dispath 來分發 action。

const store = new Vuex.Store({ //store實例
      state: {
         count: 0
             },
      mutations: {                
         increment (state) {
          state.count++
         }
          },
      actions: { 
         increment (context) {
          context.commit('increment')
   }
 }
})
複製代碼

vue-router

  1. 動態路由設置
const User = {
  template: '<div>User</div>'
}

const router = new VueRouter({
  routes: [
    // 動態路徑參數 以冒號開頭
    { path: '/user/:id', component: User }
  ]
})
一個「路徑參數」使用冒號 : 標記。當匹配到一個路由時,參數值會被設置到 this.$route.params,能夠在每一個組件內使用。
複製代碼
  1. 響應路由參數的變化

提醒一下,當使用路由參數時,例如從 /user/foo 導航到 /user/bar,原來的組件實例會被複用。由於兩個路由都渲染同個組件,比起銷燬再建立,複用則顯得更加高效。不過,這也意味着組件的生命週期鉤子不會再被調用。

複用組件時,想對路由參數的變化做出響應的話,你能夠簡單地 watch (監測變化) $route 對象:

const User = {
  template: '...',
  watch: {
    '$route' (to, from) {
      // 對路由變化做出響應...
    }
  }
}
複製代碼
  1. 路由導航鉤子

全局前置守衛

const router = new VueRouter({ ... })

router.beforeEach((to, from, next) => {
  // ...
})
to: Route: 即將要進入的目標 路由對象

from: Route: 當前導航正要離開的路由

next: Function: 必定要調用該方法來 resolve 這個鉤子。執行效果依賴 next 方法的調用參數。
複製代碼

全局後置鉤子

router.afterEach((to, from) => {
  // ...
})
複製代碼

路由獨享的守衛

你能夠在路由配置上直接定義 beforeEnter 守衛:

const router = new VueRouter({
  routes: [
    {
      path: '/foo',
      component: Foo,
      beforeEnter: (to, from, next) => {
        // ...
      }
    }
  ]
})
複製代碼

組件內的守衛

  • beforeRouteEnter
  • beforeRouteUpdate (2.2 新增)
  • beforeRouteLeave
const Foo = {
  template: `...`,
  beforeRouteEnter (to, from, next) {
    // 在渲染該組件的對應路由被 confirm 前調用
    // 不!能!獲取組件實例 `this`
    // 由於當守衛執行前,組件實例還沒被建立
  },
  beforeRouteUpdate (to, from, next) {
    // 在當前路由改變,可是該組件被複用時調用
    // 舉例來講,對於一個帶有動態參數的路徑 /foo/:id,在 /foo/1 和 /foo/2 之間跳轉的時候,
    // 因爲會渲染一樣的 Foo 組件,所以組件實例會被複用。而這個鉤子就會在這個狀況下被調用。
    // 能夠訪問組件實例 `this`
  },
  beforeRouteLeave (to, from, next) {
    // 導航離開該組件的對應路由時調用
    // 能夠訪問組件實例 `this`
  }
}
複製代碼
  1. 路由懶加載
結合 Vue 的異步組件和 Webpack 的代碼分割功能,輕鬆實現路由組件的懶加載。

這就是如何定義一個可以被 Webpack 自動代碼分割的異步組件。

const Foo = () => import('./Foo.vue')
在路由配置中什麼都不須要改變,只須要像往常同樣使用 Foo:

const router = new VueRouter({
  routes: [
    { path: '/foo', component: Foo }
  ]
})
複製代碼

axios(登陸攔截)

第一步: 路由 多添加一個自定義字段 requireAuth

path: '/repository',
name: 'repository',
meta: {
    requireAuth: true,  // 添加該字段,表示進入這個路由是須要登陸的
    },
component: Repository
複製代碼

第二步:

router.beforeEach((to, from, next) => {
   if (to.meta.requireAuth) {  // 判斷該路由是否須要登陸權限
       if (store.state.token) {  // 經過vuex state獲取當前的token是否存在
           next();
       }
       else {
           next({
               path: '/login',
               query: {redirect: to.fullPath}  // 將跳轉的路由path做爲參數,登陸成功後跳轉到該路由
           })
       }
   }
   else {
       next();
   }
複製代碼

第三步

// 建立axios實例
let server=axios.create({
    baseURL: process.env.BASE_URL,  // api的base_url
    timeout: 5000  // 請求超時時間
})
// axios實例建立好以後,開始使用request攔截器對axios請求配置作統一處理,具體以下:
server.interceptors.request.use(config => {
    config.method === 'post'
        ? config.data = qs.stringify({...config.data})
        : config.params = {...config.params};
    config.headers['Content-Type'] = 'application/json';
    
    if (store.state.token) {  // 判斷是否存在token,若是存在的話,則每一個http header都加上token
        config.headers.Authorization = `token ${store.state.token}`;
    }
    return config;
},error => {
// 返回錯誤處理
    Promise.reject(error);
});
// 而後是對response作統一處理
server.interceptors.response.use(response => {
    //這裏根據後端提供的數據進行對應的處理
    if (response.data.result === 'TRUE') {
        return response.data;
    } else {
        //常規錯誤處理
    }
},error => {
    let text = error.response.status;
    switch (text) {
        case 401:
            // 返回 401 清除token信息並跳轉到登陸頁面
            store.commit(types.LOGOUT);
            router.replace({
                path: 'login',
                query: {redirect: router.currentRoute.fullPath}
            })
    }
 
    return Promise.reject(error)
})
複製代碼
相關文章
相關標籤/搜索