欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

vuex實(shí)現(xiàn)及簡(jiǎn)略解析(小結(jié))

 更新時(shí)間:2019年03月01日 10:41:15   作者:naice  
這篇文章主要介紹了vuex實(shí)現(xiàn)及簡(jiǎn)略解析(小結(jié)),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧

大家都知道vuexvue的一個(gè)狀態(tài)管理器,它采用集中式存儲(chǔ)管理應(yīng)用的所有組件的狀態(tài),并以相應(yīng)的規(guī)則保證狀態(tài)以一種可預(yù)測(cè)的方式發(fā)生變化。先看看vuex下面的工作流程圖


通過(guò)官方文檔提供的流程圖我們知道,vuex的工作流程,

1、數(shù)據(jù)從state中渲染到頁(yè)面;

2、在頁(yè)面通過(guò)dispatch來(lái)觸發(fā)action;

3、action通過(guò)調(diào)用commit,來(lái)觸發(fā)mutation;

4、mutation來(lái)更改數(shù)據(jù),數(shù)據(jù)變更之后會(huì)觸發(fā)dep對(duì)象的notify,通知所有Watcher對(duì)象去修改對(duì)應(yīng)視圖(vue的雙向數(shù)據(jù)綁定原理)。

使用vuex

理解vuex的工作流程我們就看看vuexvue中是怎么使用的。

首先用vue-cli創(chuàng)建一個(gè)項(xiàng)目工程,如下圖,選擇vuex,然后就是一路的回車鍵

安裝好之后,就有一個(gè)帶有vuexvue項(xiàng)目了。

進(jìn)入目錄然后看到,src/store.js,在里面加了一個(gè)狀態(tài){count: 100},如下

import Vue from 'vue'
import Vuex from 'vuex' // 引入vuex

Vue.use(Vuex) // 使用插件

export default new Vuex.Store({
 state: {
  count: 100 // 加一個(gè)狀態(tài)
 },
 getter: {
 
 },
 mutations: {
 
 },
 actions: {
 
 }
})

最后在App.vue文件里面使用上這個(gè)狀態(tài),如下

<template>
 <div id="app">
  這里是stort------->{{this.$store.state.count}}
 </div>
</template>

<script>
export default {
 name: 'app'
}
</script>

<style>
</style>

項(xiàng)目跑起來(lái)就會(huì)看到頁(yè)面上看到,頁(yè)面上會(huì)有100了,如下圖

到這里我們使用vuex創(chuàng)建了一個(gè)store,并且在我們的App組件視圖中使用,但是我們會(huì)有一些列的疑問(wèn)。

  • store是如何被使用到各個(gè)組件上的??
  • 為什么state的數(shù)據(jù)是雙向綁定的??
  • 在組件中為什么用this.$store.dispch可以觸發(fā)storeactions??
  • 在組件中為什么用this.$store.commit可以觸發(fā)storemutations??
  • ....等等等等

帶著一堆問(wèn)題,我們來(lái)自己實(shí)現(xiàn)一個(gè)vuex,來(lái)理解vuex的工作原理。

安裝并使用store

src下新建一個(gè)vuex.js文件,然后代碼如下

'use strict'

let Vue = null

class Store {
 constructor (options) {
  let { state, getters, actions, mutations } = options
 }
}
// Vue.use(Vuex)
const install = _Vue => {
 // 避免vuex重復(fù)安裝
 if (Vue === _Vue) return
 Vue = _Vue
 Vue.mixin({
  // 通過(guò)mixins讓每個(gè)組件實(shí)例化的時(shí)候都會(huì)執(zhí)行下面的beforeCreate
  beforeCreate () {
   // 只有跟節(jié)點(diǎn)才有store配置,所以這里只走一次
   if (this.$options && this.$options.store) {
    this.$store = this.$options.store
   } else if (this.$parent && this.$parent.$store) { // 子組件深度優(yōu)先 父 --> 子---> 孫子
    this.$store = this.$parent.$store
   }
  }
 })
}

export default { install, Store }

然后修改store.js中的引入vuex模塊改成自己的vuex.js

import Vuex from './vuex' // 自己創(chuàng)建的vuex文件

在我們的代碼中export default { install, Store }導(dǎo)出了一個(gè)對(duì)象,分別是installStore

install的作用是,當(dāng)Vue.use(Vuex)就會(huì)自動(dòng)調(diào)用install方法,在install方法里面,我們用mixin混入了一個(gè)beforeCreate的生命周期的鉤子函數(shù),使得當(dāng)每個(gè)組件實(shí)例化的時(shí)候都會(huì)調(diào)用這個(gè)函數(shù)。

beforeCreate中,第一次根組件通過(guò)store屬性掛載$store,后面子組件調(diào)用beforeCreate掛載的$store都會(huì)向上找到父級(jí)的$store,這樣子通過(guò)層層向上尋找,讓每個(gè)組件都掛上了一個(gè)$store屬性,而這個(gè)屬性的值就是我們的new Store({...})的實(shí)例。如下圖

通過(guò)層層向上尋找,讓每個(gè)組件都掛上了一個(gè)$store屬性

設(shè)置state響應(yīng)數(shù)據(jù)

通過(guò)上面,我們已經(jīng)從每個(gè)組件都通過(guò)this.$store來(lái)訪問(wèn)到我們的store的實(shí)例,下面我們就編寫state數(shù)據(jù),讓其變成雙向綁定的數(shù)據(jù)。下面我們改寫store

class Store {
 constructor (options) {
  let { state, getters, actions, mutations } = options // 拿到傳進(jìn)來(lái)的參數(shù)
  this.getters = {}
  this.mutations = {}
  this.actions = {}
  // vuex的核心就是借用vue的實(shí)例,因?yàn)関uex的數(shù)據(jù)更改回更新視圖
  this._vm = new Vue({
   data: {
    state
   }
  })
 }
 // 訪問(wèn)state對(duì)象時(shí)候,就直接返回響應(yīng)式的數(shù)據(jù)
 get state() { // Object.defineProperty get 同理
  return this._vm.state
 }
}

傳進(jìn)來(lái)的state對(duì)象,通過(guò)new Vue({data: {state}})的方式,讓數(shù)據(jù)變成響應(yīng)式的。當(dāng)訪問(wèn)state對(duì)象時(shí)候,就直接返回響應(yīng)式的數(shù)據(jù),這樣子在App.vue中就可以通過(guò)this.$store.state.count拿到state的數(shù)據(jù)啦,并且是響應(yīng)式的呢。

編寫mutations、actions、getters

上面我們已經(jīng)設(shè)置好state為響應(yīng)式的數(shù)據(jù),這里我們?cè)?code>store.js里面寫上mutations、actions、getters,如下

import Vue from 'vue'
import Vuex from './vuex' // 引入我們的自己編寫的文件

Vue.use(Vuex) // 安裝store
// 實(shí)例化store,參數(shù)數(shù)對(duì)象
export default new Vuex.Store({
 state: {
  count : 1000
 },
 getters : {
  newCount (state) {
   return state.count + 100
  }
 },
 mutations: {
  change (state) {
   console.log(state.count)
   state.count += 10
  }
 },
 actions: {
  change ({commit}) {
   // 模擬異步
   setTimeout(() => {
    commit('change')
   }, 1000)
  }
 }
})

配置選項(xiàng)都寫好之后,就看到getters對(duì)象里面有個(gè)newCount函數(shù),mutationsactions對(duì)象里面都有個(gè)change函數(shù),配置好store之后我們?cè)?code>App.vue就可以寫上,dispatchcommit,分別可以觸發(fā)actionsmutations,代碼如下

<template>
 <div id="app">
  這里是store的state------->{{this.$store.state.count}} <br/>
  這里是store的getter------->{{this.$store.getters.newCount}} <br/>
  <button @click="change">點(diǎn)擊觸發(fā)dispach--> actions</button>
  <button @click="change1">點(diǎn)擊觸發(fā)commit---> mutations</button>
 </div>
</template>

<script>
export default {
 name: 'app',
 methods: {
  change () {
   this.$store.dispatch('change') // 觸發(fā)actions對(duì)應(yīng)的change
  },
  change1 () {
   this.$store.commit('change') // 觸發(fā)mutations對(duì)應(yīng)的change
  }
 },
 mounted () {
  console.log(this.$store)
 }
}
</script>

數(shù)據(jù)都配置好之后,我們開始編寫store類,在此之前我們先編寫一個(gè)循環(huán)對(duì)象工具函數(shù)。

const myforEach = (obj, callback) => Object.keys(obj).forEach(key => callback(key, obj[key]))
// 作用:
// 例如{a: '123'}, 把對(duì)象的key和value作為參數(shù)
// 然后就是函數(shù)運(yùn)行callback(a, '123')

工具函數(shù)都準(zhǔn)備好了,之后,下面直接縣編寫gettersmutationsactions的實(shí)現(xiàn)

class Store {
 constructor (options) {
  let { state = {}, getters = {}, actions = {}, mutations = {} } = options
  this.getters = {}
  this.mutations = {}
  this.actions = {}
  // vuex的核心就是借用vue的實(shí)例,因?yàn)関uex的數(shù)據(jù)更改回更新視圖
  this._vm = new Vue({
   data: {
    state
   }
  })
  // 循環(huán)getters的對(duì)象
  myforEach(getters, (getterName, getterFn) => {
   // 對(duì)this.getters對(duì)象進(jìn)行包裝,和vue的computed是差不多的
   // 例如 this.getters['newCount'] = fn(state)
   // 執(zhí)行 this.getters['newCount']()就會(huì)返回計(jì)算的數(shù)據(jù)啦
   Object.defineProperty(this.getters, getterName, {
    get: () => getterFn(state)
   })
  })
  // 這里是mutations各個(gè)key和值都寫到,this.mutations對(duì)象上面
  // 執(zhí)行的時(shí)候就是例如:this.mutations['change']()
  myforEach(mutations, (mutationName, mutationsFn) => {
   // this.mutations.change = () => { change(state) }
   this.mutations[mutationName] = () => {
    mutationsFn.call(this, state)
   }
  })
  // 原理同上
  myforEach(actions, (actionName, actionFn) => {
   // this.mutations.change = () => { change(state) }
   this.actions[actionName] = () => {
    actionFn.call(this, this)
   }
  })
  const {commit , dispatch} = this // 先存一份,避免this.commit會(huì)覆蓋原型上的this.commit
  // 解構(gòu) 把this綁定好
  // 通過(guò)結(jié)構(gòu)的方式也要先調(diào)用這類,然后在下面在調(diào)用原型的對(duì)應(yīng)函數(shù)
  this.commit = type => {
   commit.call(this, type)
  }
  this.dispatch = type => {
   dispatch.call(this, type)
  }
 }
 get state() { // Object.defineProperty 同理
  return this._vm.state
 }
 // commi調(diào)用
 commit (type) {
  this.mutations[type]()
 }
 // dispatch調(diào)用
 dispatch (type) {
  this.actions[type]()
 }
}

通過(guò)上面的,我們可以看出,其實(shí)mutationsactions都是把傳入的參數(shù),賦值到store實(shí)例上的this.mutationsthis.actions對(duì)象里面。

當(dāng)組件中this.$store.commit('change')的時(shí)候 其實(shí)是調(diào)用this.mutations.change(state),就達(dá)到了改變數(shù)據(jù)的效果,actions同理。

getters是通過(guò)對(duì)Object.defineProperty(this.getters, getterName, {})
對(duì)this.getters進(jìn)行包裝當(dāng)組件中this.$store.getters.newCount其實(shí)是調(diào)用getters對(duì)象里面的newCount(state),然后返回計(jì)算結(jié)果。就可以顯示到界面上了。

大家看看完成后的效果圖。

到這里大家應(yīng)該懂了vuex的內(nèi)部代碼的工作流程了,vuex的一半核心應(yīng)該在這里了。為什么說(shuō)一半,因?yàn)檫€有一個(gè)核心概念module,也就是vuex的數(shù)據(jù)的模塊化。

vuex數(shù)據(jù)模塊化

由于使用單一狀態(tài)樹,應(yīng)用的所有狀態(tài)會(huì)集中到一個(gè)比較大的對(duì)象。當(dāng)應(yīng)用變得非常復(fù)雜時(shí),store 對(duì)象就有可能變得相當(dāng)臃腫。

為了解決以上問(wèn)題,Vuex 允許我們將 store 分割成模塊(module)。每個(gè)模塊擁有自己的 state、mutation、action、getter、甚至是嵌套子模塊——從上至下進(jìn)行同樣方式的分割

例如下面的store.js

// 實(shí)例化store,參數(shù)數(shù)對(duì)象
export default new Vuex.Store({
 modules: {
  // 模塊a
  a: {
   state: {
    count: 4000
   },
   actions: {
    change ({state}) {
     state.count += 21
    }
   },
   modules: {
    // 模塊b
    b: {
     state: {
      count: 5000
     }
    }
   }
  }
 },
 state: {
  count : 1000
 },
 getters : {
  newCount (state) {
   return state.count + 100
  }
 },
 mutations: {
  change (state) {
   console.log(state.count)
   state.count += 10
  }
 },
 actions: {
  change ({commit}) {
   // 模擬異步
   setTimeout(() => {
    commit('change')
   }, 1000)
  }
 }
})

然后就可以在界面上就可以寫上this.$store.state.a.count(顯示a模塊count),this.$store.state.a.b.count(顯示a模塊下,b模塊的count),這里還有一個(gè)要注意的,其實(shí)在組件中調(diào)用this.$store.dispatch('change')會(huì)同時(shí)觸發(fā),根的actionsa模塊actions里面的change函數(shù)。

下面我們就直接去實(shí)現(xiàn)models的代碼,也就是整個(gè)vuex的實(shí)現(xiàn)代碼,

'use strict'

let Vue = null
const myforEach = (obj, callback) => Object.keys(obj).forEach(key => callback(key, obj[key]))

class Store {
 constructor (options) {
  let state = options.state
  this.getters = {}
  this.mutations = {}
  this.actions = {}
  // vuex的核心就是借用vue的實(shí)例,因?yàn)関uex的數(shù)據(jù)更改回更新視圖
  this._vm = new Vue({
   data: {
    state
   }
  })

  // 把模塊之間的關(guān)系進(jìn)行整理, 自己根據(jù)用戶參數(shù)維護(hù)了一個(gè)對(duì)象
  // root._children => a._children => b
  this.modules = new ModulesCollections(options)
  // 無(wú)論子模塊還是 孫子模塊 ,所有的mutations 都是根上的
  // 安裝模塊
  installModules(this, state, [], this.modules.root)

  // 解構(gòu) 把this綁定好
  const {commit , dispatch} = this
  // 通過(guò)結(jié)構(gòu)的方式也要先調(diào)用這類,然后在下面在調(diào)用原型的對(duì)應(yīng)函數(shù)
  this.commit = type => {
   commit.call(this, type)
  }
  this.dispatch = type => {
   dispatch.call(this, type)
  }
 }
 get state() { // Object.defineProperty 同理
  return this._vm.state
 }
 commit (type) {
  // 因?yàn)槭菙?shù)組,所以要遍歷執(zhí)行
  this.mutations[type].forEach(fn => fn())
 }
 dispatch (type) {
  // 因?yàn)槭菙?shù)組,所以要遍歷執(zhí)行
  this.actions[type].forEach(fn => fn())
 }
}

class ModulesCollections {
 constructor (options) { // vuex []
  // 注冊(cè)模塊
  this.register([], options)
 }
 register (path, rawModule) {
  // path 是空數(shù)組, rawModule 就是個(gè)對(duì)象
  let newModule = {
   _raw: rawModule, // 對(duì)象
   _children: {}, // 把子模塊掛載到這里
   state: rawModule.state
  }
  if (path.length === 0) { // 第一次
   this.root = newModule
  } else {
   // [a, b] ==> [a]
   let parent = path.slice(0, -1).reduce((root, current) => {
    return root._children[current]
   }, this.root)
   parent._children[path[path.length - 1]] = newModule
  }
  if (rawModule.modules) {
   // 遍歷注冊(cè)子模塊
   myforEach(rawModule.modules, (childName, module) => {
    this.register(path.concat(childName), module)
   })
  }
 }
}

// rootModule {_raw, _children, state }
function installModules (store, rootState, path, rootModule) {
 // rootState.a = {count:200}
 // rootState.a.b = {count: 3000}
 if (path.length > 0) {
  // 根據(jù)path找到對(duì)應(yīng)的父級(jí)模塊
  // 例如 [a] --> path.slice(0, -1) --> [] 此時(shí)a模塊的父級(jí)模塊是跟模塊
  // 例如 [a,b] --> path.slice(0, -1) --> [a] 此時(shí)b模塊的父級(jí)模塊是a模塊
  let parent = path.slice(0, -1).reduce((root, current) => {
   return root[current]
  }, rootState)
  // 通過(guò)Vue.set設(shè)置數(shù)據(jù)雙向綁定
  Vue.set(parent, path[path.length - 1], rootModule.state)
 }
 // 設(shè)置getter
 if (rootModule._raw.getters) {
  myforEach(rootModule._raw.getters, (getterName, getterFn) => {
   Object.defineProperty(store.getters, getterName, {
    get: () => {
     return getterFn(rootModule.state)
    }
   })
  })
 }
 // 在跟模塊設(shè)置actions
 if (rootModule._raw.actions) {
  myforEach(rootModule._raw.actions, (actionName, actionsFn) => {
   // 因?yàn)橥窃诟K設(shè)置,子模塊也有能相同的key
   // 所有把所有的都放到一個(gè)數(shù)組里面
   // 就變成了例如 [change, change] , 第一個(gè)是跟模塊的actions的change,第二個(gè)是a模塊的actions的change
   let entry = store.actions[actionName] || (store.actions[actionName] = [])
   entry.push(() => {
    const commit = store.commit
    const state = rootModule.state
    actionsFn.call(store, {state, commit})
   })
  })
 }
 // 在跟模塊設(shè)置mutations, 同理上actions
 if (rootModule._raw.mutations) {
  myforEach(rootModule._raw.mutations, (mutationName, mutationFn) => {
   let entry = store.mutations[mutationName] || (store.mutations[mutationName] = [])
   entry.push(() => {
    mutationFn.call(store, rootModule.state)
   })
  })
 }
 // 遞歸遍歷子節(jié)點(diǎn)的設(shè)置
 myforEach(rootModule._children, (childName, module) => {
  installModules(store, rootState, path.concat(childName), module)
 })
}

const install = _Vue => {
 // 避免vuex重復(fù)安裝
 if (Vue === _Vue) return
 Vue = _Vue
 Vue.mixin({
  // 通過(guò)mixins讓每個(gè)組件實(shí)例化的時(shí)候都會(huì)執(zhí)行下面的beforeCreate
  beforeCreate () {
   // 只有跟節(jié)點(diǎn)才有store配置
   if (this.$options && this.$options.store) {
    this.$store = this.$options.store
   } else if (this.$parent && this.$parent.$store) { // 子組件深度優(yōu)先 父 --> 子---> 孫子
    this.$store = this.$parent.$store
   }
  }
 })
}

export default { install, Store }

看到代碼以及注釋,主要流程就是根據(jù)遞歸的方式,處理數(shù)據(jù),然后根據(jù)傳進(jìn)來(lái)的配置,進(jìn)行操作數(shù)據(jù)。

至此,我們把vuex的代碼實(shí)現(xiàn)了一遍,在我們App.vue的代碼里添加

<template>
 <div id="app">
  這里是store的state------->{{this.$store.state.count}} <br/>
  這里是store的getter------->{{this.$store.getters.newCount}} <br/>
  這里是store的state.a------->{{this.$store.state.a.count}} <br/>
  <button @click="change">點(diǎn)擊觸發(fā)dispach--> actions</button>
  <button @click="change1">點(diǎn)擊觸發(fā)commit---> mutations</button>
 </div>
</template>

最后查看結(jié)果。

源碼地址:https://github.com/naihe138/write-vuex

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • vue實(shí)現(xiàn)實(shí)時(shí)搜索顯示功能

    vue實(shí)現(xiàn)實(shí)時(shí)搜索顯示功能

    這篇文章主要為大家詳細(xì)介紹了vue實(shí)現(xiàn)實(shí)時(shí)搜索顯示功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-04-04
  • Vue 項(xiàng)目中如何使用fullcalendar 時(shí)間段選擇插件(類似課程表格)

    Vue 項(xiàng)目中如何使用fullcalendar 時(shí)間段選擇插件(類似課程表格)

    最近完成一個(gè)項(xiàng)目,需要選擇一個(gè)會(huì)議室,但是最好能夠通過(guò)在圖上顯示出該 會(huì)議室在某某時(shí)間段內(nèi)已經(jīng)被預(yù)定了,初看這個(gè)功能感覺很棘手,仔細(xì)分析下實(shí)現(xiàn)起來(lái)還是挺容易的,下面通過(guò)示例代碼講解Vue項(xiàng)目中使用fullcalendar時(shí)間段選擇插件,感興趣的朋友一起看看吧
    2024-07-07
  • vue3項(xiàng)目使用pinia狀態(tài)管理器的使用

    vue3項(xiàng)目使用pinia狀態(tài)管理器的使用

    Pinia是一個(gè)專為Vue3設(shè)計(jì)的現(xiàn)代化狀態(tài)管理庫(kù),本文主要介紹了vue3項(xiàng)目使用pinia狀態(tài)管理器的使用,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-05-05
  • Vue計(jì)算屬性與監(jiān)視屬性實(shí)現(xiàn)方法詳解

    Vue計(jì)算屬性與監(jiān)視屬性實(shí)現(xiàn)方法詳解

    最近在學(xué)習(xí)vue,學(xué)習(xí)中遇到了一些感覺挺重要的知識(shí)點(diǎn),感覺有必要整理下來(lái),這篇文章主要給大家介紹了關(guān)于Vue.js中計(jì)算屬性、監(jiān)視屬性的相關(guān)資料,需要的朋友可以參考下
    2022-08-08
  • 如何管理Vue中的緩存頁(yè)面

    如何管理Vue中的緩存頁(yè)面

    這篇文章主要介紹了如何管理Vue中的緩存頁(yè)面,幫助大家更好的理解和學(xué)習(xí)使用vue框架,感興趣的朋友可以了解下
    2021-02-02
  • vue 驗(yàn)證兩次輸入的密碼是否一致的方法示例

    vue 驗(yàn)證兩次輸入的密碼是否一致的方法示例

    這篇文章主要介紹了vue 驗(yàn)證兩次輸入的密碼是否一致的方法示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • Vue如何整合mavon-editor編輯器(markdown編輯和預(yù)覽)

    Vue如何整合mavon-editor編輯器(markdown編輯和預(yù)覽)

    這篇文章主要介紹了Vue整合mavon-editor編輯器(markdown編輯和預(yù)覽)的相關(guān)知識(shí),mavon-editor是目前比較主流的markdown編輯器,重點(diǎn)介紹它的使用方法,需要的朋友可以參考下
    2022-10-10
  • vue2.0的contextmenu右鍵彈出菜單的實(shí)例代碼

    vue2.0的contextmenu右鍵彈出菜單的實(shí)例代碼

    本篇文章主要介紹了vue2.0的contextmenu右鍵彈出菜單的實(shí)例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-07-07
  • 詳解Vue使用 vue-cli 搭建項(xiàng)目

    詳解Vue使用 vue-cli 搭建項(xiàng)目

    本篇文章主要介紹了詳解Vue使用 vue-cli 搭建項(xiàng)目,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-04-04
  • 詳解vue-router導(dǎo)航守衛(wèi)

    詳解vue-router導(dǎo)航守衛(wèi)

    今天小編就為大家分享一篇關(guān)于詳解vue-router導(dǎo)航守衛(wèi),小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2019-01-01

最新評(píng)論