Vuejs技術(shù)棧知識(shí)點(diǎn)小結(jié)

Vuejs技術(shù)棧知識(shí)點(diǎn)小結(jié)

閱讀目錄

前言

上家公司的項(xiàng)目主要是使用jQuery和Angular1,然后自己學(xué)了React,沒想到來(lái)到這家公司突然開始做vue,不過(guò)vue還是挺容易上手的。下面是vue技術(shù)棧的一些總結(jié),都是來(lái)自官網(wǎng),主要是自己對(duì)vue技術(shù)棧知識(shí)點(diǎn)的一些整理,因此此文很水,建議閱讀我的上一篇文章Vuejs技術(shù)棧從CLI到打包上線實(shí)戰(zhàn)全解析

Vue

獨(dú)立構(gòu)建和運(yùn)行時(shí)構(gòu)建

有兩種構(gòu)建方式,獨(dú)立構(gòu)建和運(yùn)行構(gòu)建。它們的區(qū)別在于前者包含模板編譯器而后者不包含。

模板編譯器的職責(zé)是將模板字符串編譯為純JavaScript的渲染函數(shù)。如果你想要在組件中使用template選項(xiàng),你就需要編譯器。

生命周期

具體查看官網(wǎng)的流程圖,要注意的是created和mounted區(qū)別,created是vm實(shí)例已創(chuàng)建但未掛載,因此一些DOM操作應(yīng)該放在mounted中。異步請(qǐng)求放在created或者mounted暫時(shí)沒發(fā)現(xiàn)什么區(qū)別,如您知道有什么區(qū)別,請(qǐng)?jiān)u論指出。

計(jì)算(computed)屬性

模板內(nèi)的表達(dá)式不應(yīng)該包含太多的邏輯,對(duì)于任何復(fù)雜邏輯,都應(yīng)當(dāng)使用計(jì)算屬性

computed屬性和methods不同的是計(jì)算屬性是基于它們的依賴進(jìn)行緩存的。

computed屬性和computed屬性,通常更好的想法是使用computed屬性而不是命令式的watch回調(diào)。雖然計(jì)算屬性在大多數(shù)情況下更合適,但有時(shí)也需要一個(gè)自定義的watcher。當(dāng)你想要在數(shù)據(jù)變化響應(yīng)時(shí),執(zhí)行異步操作或開銷較大的操作,這是很有用的。

數(shù)組更新檢測(cè)

數(shù)組的變異方法(mutation method,會(huì)改變被這些方法調(diào)用的原始數(shù)組)會(huì)觸發(fā)視圖更新,有以下七個(gè):

push()
pop()
shift()
unshift()
splice()
sort()
reverse()

當(dāng)使用非變異方法時(shí),可以用新數(shù)組替換舊數(shù)組,或者使用Vue.set方法。

對(duì)象更新

可以用新對(duì)象替換舊對(duì)象,或者使用Vue.set方法

Vue.set(vm.someObject, 'foo', 'bar')

this.someObject = Object.assign({}, this.someObject, { a:1, b:2 })

事件處理器

Vue.js為v-on提供了事件修飾符和按鍵修飾符

表單控件綁定

可以用v-model指令在表單控件元素上創(chuàng)建雙向數(shù)據(jù)綁定。常見修飾符有.lazy、.number、.trim。

也可以使用自定義事件的表單輸入組件。

組件

Vue組件的API來(lái)自三部分:props,events和slots:

  • Props允許外部環(huán)境傳遞數(shù)據(jù)給組件
  • Events允許組件觸發(fā)外部環(huán)境的副作用
  • Slots允許外部環(huán)境將額外的內(nèi)容組合在組件中。

1)組件的data屬性必須是函數(shù)

2)父子組件

在Vue.js中,父子組件的關(guān)系可以總結(jié)為 props down, events up 。父組件通過(guò)props向下傳遞數(shù)據(jù)給子組件,子組件通過(guò)events給父組件發(fā)送消息。

prop是單向綁定的:當(dāng)父組件的屬性變化時(shí),將傳導(dǎo)給子組件,但是不會(huì)反過(guò)來(lái)。這是為了防止子組件無(wú)意修改了父組件的狀態(tài)——這會(huì)讓應(yīng)用的數(shù)據(jù)流難以理解。

另外,每次父組件更新時(shí),子組件的所有prop都會(huì)更新為最新值。這意味著你不應(yīng)該在子組件內(nèi)部改變prop。如果你這么做了,Vue會(huì)在控制臺(tái)給出警告。

為什么我們會(huì)有修改prop中數(shù)據(jù)的沖動(dòng)呢?通常是這兩種原因:

1.prop作為初始值傳入后,子組件想把它當(dāng)作局部數(shù)據(jù)來(lái)用;

2.prop作為初始值傳入,由子組件處理成其它數(shù)據(jù)輸出。

對(duì)這兩種原因,正確的應(yīng)對(duì)方式是:

1.定義一個(gè)局部變量,并用prop的值初始化它:

props: ['initialCounter'],
data: function () {
  return { counter: this.initialCounter }
}

2.定義一個(gè)計(jì)算屬性,處理prop的值并返回。

props: ['size'],
computed: {
  normalizedSize: function () {
    return this.size.trim().toLowerCase()
  }
}

注意在JavaScript中對(duì)象和數(shù)組是引用類型,指向同一個(gè)內(nèi)存空間,如果prop是一個(gè)對(duì)象或數(shù)組,在子組件內(nèi)部改變它會(huì)影響父組件的狀態(tài)。

3)非父子組件

有時(shí)候兩個(gè)組件也需要通信(非父子關(guān)系)。在簡(jiǎn)單的場(chǎng)景下,可以使用一個(gè)空的Vue實(shí)例作為中央事件總線。在復(fù)雜的情況下,我們應(yīng)該考慮使用專門的狀態(tài)管理模式。

4).sync修飾符

在一些情況下,我們可能會(huì)需要對(duì)一個(gè)prop進(jìn)行『雙向綁定』。

2.0中移除了.sync,Vue2.3.0+又將其添加回來(lái)了,但是這次它只是作為一個(gè)編譯時(shí)的語(yǔ)法糖存在,它會(huì)被擴(kuò)展為一個(gè)自動(dòng)更新父組件屬性的v-on偵聽器。如下代碼

<comp :foo.sync="bar"></comp>

會(huì)被擴(kuò)展為:

<comp :foo="bar" @update:foo="val => bar = val"></comp>

當(dāng)子組件需要更新foo的值時(shí),它需要顯式地觸發(fā)一個(gè)更新事件:

this.$emit('update:foo', newValue)

5)使用slot進(jìn)行內(nèi)容分發(fā)

作用域插槽:接收從子組件中傳遞的prop對(duì)象。作用域插槽更具代表性的用例是列表組件,允許組件自定義應(yīng)該如何渲染列表每一項(xiàng)

6)動(dòng)態(tài)組件、is特性和keep-alive指令

7)子組件索引

盡管有props和events,但是有時(shí)仍然需要JavaScript中直接訪問子組件。為此可以使用ref為子組件指定一個(gè)索引ID。

異步更新隊(duì)列

雖然 Vue.js 通常鼓勵(lì)開發(fā)人員沿著“數(shù)據(jù)驅(qū)動(dòng)”的方式思考,避免直接接觸 DOM,但是有時(shí)我們確實(shí)要這么做。為了在數(shù)據(jù)變化之后等待 Vue 完成更新 DOM ,可以在數(shù)據(jù)變化之后立即使用 Vue.nextTick(callback) 。這樣回調(diào)函數(shù)在 DOM 更新完成后就會(huì)調(diào)用。

過(guò)渡效果

Vue在插入、更新或者移除DOM時(shí),提供多種不同方式的應(yīng)用過(guò)渡效果。包括以下工具:

  • 在CSS過(guò)渡和動(dòng)畫中自動(dòng)應(yīng)用class
  • 可以配合使用第三方CSS動(dòng)畫庫(kù),如Animate.css
  • 在過(guò)渡鉤子函數(shù)中使用JavaScript直接操作DOM
  • 可以配合使用第三方JavaScript動(dòng)畫庫(kù),如Velocity.js

1)單元素/組件的過(guò)渡

Vue提供了transition的封裝組件,在下列情形中,可以給任何元素和組件添加過(guò)渡

  • 條件渲染(使用v-if)
  • 條件展示(使用v-show)
  • 動(dòng)態(tài)組件
  • 組件根節(jié)點(diǎn)

2)多個(gè)元素的過(guò)渡

對(duì)于原生標(biāo)簽可以使用 v-if/v-else

3)多個(gè)組件的過(guò)渡

多個(gè)組件的過(guò)渡我們可以使用動(dòng)態(tài)組件。

4)列表過(guò)渡

Render函數(shù)和JSX

自定義指令

和Angular的指令類似,主要操作DOM,下面是一個(gè)滾動(dòng)加載的指令,holder暫時(shí)沒想到什么更好的處理方法:

let scrollCallback = function (callback) {
  let windowH = window.innerHeight
  let getDocumentHeight = function () {
    var body = document.body
    var html = document.documentElement
    return Math.max(
      body.offsetHeight,
      body.scrollHeight,
      html.clientHeight,
      html.offsetHeight,
      html.scrollHeight
    )
  }
  let scrollH = document.documentElement.scrollTop || document.body.scrollTop
  if (windowH + scrollH >= getDocumentHeight() - (this.holder || 20)) {
    callback()
  }
}

let callBackWarpped

export default {
  bind (el, binding, vnode) {
    let holder
    if (vnode.data && vnode.data.attrs && vnode.data.attrs['scroll-placeholder']) {
      holder = parseInt(vnode.data.attrs['scroll-placeholder'])
    } else {
      holder = 20
    }
    callBackWarpped = scrollCallback.bind({el, holder}, binding.value)
    window.addEventListener('scroll', callBackWarpped, false)
  },

  unbind: function () {
    window.removeEventListener('scroll', callBackWarpped, false)
  }
}

混合

混合是一種靈活的分布式復(fù)用Vue組件的方式?;旌蠈?duì)象可以包含任意組件選項(xiàng)。以組件使用混合對(duì)象時(shí),所有混合對(duì)象的選項(xiàng)將被混入該組件本身的選項(xiàng)。

插件

1)創(chuàng)建插件

Vue.js的插件應(yīng)當(dāng)有一個(gè)公開方法install。這個(gè)方法的第一個(gè)參數(shù)是Vue構(gòu)造器 , 第二個(gè)參數(shù)是一個(gè)可選的選項(xiàng)對(duì)象。

2)使用插件

通過(guò)全局方法Vue.use()使用插件:

// 調(diào)用 `MyPlugin.install(Vue)`
Vue.use(MyPlugin)

也可以傳入一個(gè)選項(xiàng)對(duì)象:

Vue.use(MyPlugin, { someOption: true })

vue-router

兩種導(dǎo)航方式

1)router-link聲明式導(dǎo)航

<router-link to="/foo">Go to Foo</router-link>

router-link對(duì)應(yīng)的路由匹配成功,將自動(dòng)設(shè)置class屬性值.router-link-active。

2)編程式導(dǎo)航

// 字符串
router.push('home')

// 對(duì)象
router.push({ path: 'home' })

// 命名的路由
router.push({ name: 'user', params: { userId: 123 }})

// 帶查詢參數(shù),變成 /register?plan=private
router.push({ path: 'register', query: { plan: 'private' }})

重命名(redirect)和別名(alias)

兩種路由模式

vue-router默認(rèn)hash模式,也可以設(shè)置為路由的history模式。

導(dǎo)航鉤子

vue-router提供的導(dǎo)航鉤子主要用來(lái)攔截導(dǎo)航,讓它完成跳轉(zhuǎn)或取消。有多種方式可以在路由導(dǎo)航發(fā)生時(shí)執(zhí)行鉤子:全局的, 單個(gè)路由獨(dú)享的, 或者組件級(jí)的。

路由meta

一個(gè)路由匹配到的所有路由記錄會(huì)暴露為route對(duì)象(還有在導(dǎo)航鉤子中的route對(duì)象)的route.matched數(shù)組。因此,我們需要遍歷$route.matched來(lái)檢查路由記錄中的meta字段。

過(guò)渡動(dòng)效

router-view是基本的動(dòng)態(tài)組件,所以我們可以用transition組件給它添加一些過(guò)渡效果。

數(shù)據(jù)獲取

有時(shí)候,進(jìn)入某個(gè)路由后,需要從服務(wù)器獲取數(shù)據(jù)。例如,在渲染用戶信息時(shí),你需要從服務(wù)器獲取用戶的數(shù)據(jù)。我們可以通過(guò)兩種方式來(lái)實(shí)現(xiàn):

導(dǎo)航完成之后獲?。合韧瓿蓪?dǎo)航,然后在接下來(lái)的組件生命周期鉤子中獲取數(shù)據(jù)。在數(shù)據(jù)獲取期間顯示『加載中』之類的指示。

導(dǎo)航完成之前獲?。簩?dǎo)航完成前,在路由的enter鉤子中獲取數(shù)據(jù),在數(shù)據(jù)獲取成功后執(zhí)行導(dǎo)航。

滾動(dòng)行為(scrollBehavior)

注意: 這個(gè)功能只在HTML5 history模式下可用。

路由懶加載

當(dāng)打包構(gòu)建應(yīng)用時(shí),Javascript包會(huì)變得非常大,影響頁(yè)面加載。如果我們能把不同路由對(duì)應(yīng)的組件分割成不同的代碼塊,然后當(dāng)路由被訪問的時(shí)候才加載對(duì)應(yīng)組件,這樣就更加高效了。

結(jié)合Vue的異步組件和Webpack的code splitting功能,輕松實(shí)現(xiàn)路由組件的懶加載。

const Foo = resolve => require(['./Foo.vue'], resolve)

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

router-link

可以設(shè)置tag、append、active-class、exact等屬性

有時(shí)候我們要讓 "激活時(shí)的CSS類名" 應(yīng)用在外層元素,而不是a標(biāo)簽本身,那么可以用router-link渲染外層元素,包裹著內(nèi)層的原生a標(biāo)簽:

<router-link tag="li" to="/foo">
  <a>/foo</a>
</router-link>

在這種情況下,a將作為真實(shí)的鏈接(它會(huì)獲得正確的 href 的),而"激活時(shí)的CSS類名"則設(shè)置到外層的li。

Router構(gòu)造配置

routes、mode、base、linkActiveClass、scrollBehavior

對(duì)組件注入

1)注入的屬性

通過(guò)在Vue根實(shí)例的router配置傳入router實(shí)例,下面兩個(gè)屬性成員會(huì)被注入到每個(gè)子組件。

$router:router實(shí)例

$route:當(dāng)前激活的路由信息對(duì)象。這個(gè)屬性是只讀的,里面的屬性是immutable(不可變)的,不過(guò)你可以watch(監(jiān)測(cè)變化)它。

2)允許的額外配置:beforeRouteEnter、beforeRouteLeave

vuex

state

1)單一狀態(tài)樹

Vuex使用單一狀態(tài)樹--是的,用一個(gè)對(duì)象就包含了全部的應(yīng)用層級(jí)狀態(tài)。至此它便作為一個(gè)『唯一數(shù)據(jù)源(SSOT)』而存在。這也意味著,每個(gè)應(yīng)用將僅僅包含一個(gè)store實(shí)例。單一狀態(tài)樹讓我們能夠直接地定位任一特定的狀態(tài)片段,在調(diào)試的過(guò)程中也能輕易地取得整個(gè)當(dāng)前應(yīng)用狀態(tài)的快照。

2)在Vue組件中獲得Vuex狀態(tài)

最好在根實(shí)例中注冊(cè)store選項(xiàng),該store實(shí)例會(huì)注入到根組件下的所有子組件中,且子組件能通過(guò)this.$store訪問到。而不是在每個(gè)需要使用state的組件中需要頻繁地導(dǎo)入。

3)mapState輔助函數(shù)

當(dāng)一個(gè)組件需要獲取多個(gè)狀態(tài)時(shí)候,可以使用mapState輔助函數(shù)幫助我們生成計(jì)算屬性,這樣可以簡(jiǎn)化代碼書寫。mapState函數(shù)會(huì)返回一個(gè)對(duì)象,然后可以使用對(duì)象展開運(yùn)算符將它與局部計(jì)算屬性混合使用。

4)不要濫用vuex

使用Vuex并不意味著你需要將所有的狀態(tài)放入Vuex。雖然將所有的狀態(tài)放到Vuex會(huì)使?fàn)顟B(tài)變化更顯式和易調(diào)試,但也會(huì)使代碼變得冗長(zhǎng)和不直觀。如果有些狀態(tài)嚴(yán)格屬于單個(gè)組件,最好還是作為組件的局部狀態(tài)。你應(yīng)該根據(jù)你的應(yīng)用開發(fā)需要進(jìn)行權(quán)衡和確定。

getters

getters用來(lái)從store中的state中派生出一些狀態(tài),例如對(duì)列表進(jìn)行過(guò)濾并計(jì)數(shù):

computed: {
  doneTodosCount () {
    return this.$store.state.todos.filter(todo => todo.done).length
  }
}

getters可以認(rèn)為是store的計(jì)算屬性。和state類似,有mapGetters輔助函數(shù)。

mutations

更改Vuex的store中的狀態(tài)的唯一方法是提交mutation。Vuex中的mutations非常類似于事件:每個(gè)mutation都有一個(gè)字符串的事件類型(type)和一個(gè)回調(diào)函數(shù)(handler)。這個(gè)回調(diào)函數(shù)就是我們實(shí)際進(jìn)行狀態(tài)更改的地方,并且它會(huì)接受state作為第一個(gè)參數(shù)

1)提交載荷(Payload)

你可以向store.commit傳入額外的參數(shù),即mutation的載荷(payload):

// ...
mutations: {
  increment (state, n) {
    state.count += n
  }
}
store.commit('increment', 10)

2)Mutations需遵守Vue的響應(yīng)規(guī)則

3)使用常量替代Mutation事件類型

4)mutation必須是同步函數(shù)

5)在組件中提交Mutations

你可以在組件中使用this.$store.commit('xxx')提交mutation,或者使用mapMutations輔助函數(shù)將組件中的methods映射為store.commit調(diào)用(需要在根節(jié)點(diǎn)注入store)。

actions

actions類似于mutation,不同在于:

  • actions提交的是mutation,而不是直接變更狀態(tài)。
  • actions可以包含任意異步操作。

1)在組件中分發(fā)Action

你在組件中使用this.$store.dispatch('xxx')分發(fā)action,或者使用mapActions輔助函數(shù)將組件的methods映射為store.dispatch調(diào)用(需要先在根節(jié)點(diǎn)注入store)

2)組合Actions

Action通常是異步的,那么如何知道action什么時(shí)候結(jié)束呢?更重要的是,我們?nèi)绾尾拍芙M合多個(gè)action,以處理更加復(fù)雜的異步流程?

首先,你需要明白store.dispatch可以處理被觸發(fā)的action的回調(diào)函數(shù)返回的Promise,并且store.dispatch仍舊返回Promise。

使用async/await會(huì)更加簡(jiǎn)單:

// 假設(shè) getData() 和 getOtherData() 返回的是 Promise

actions: {
  async actionA ({ commit }) {
    commit('gotData', await getData())
  },
  async actionB ({ dispatch, commit }) {
    await dispatch('actionA') // 等待 actionA 完成
    commit('gotOtherData', await getOtherData())
  }
}

Modules

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

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

const moduleA = {
  state: { ... },
  mutations: { ... },
  actions: { ... },
  getters: { ... }
}

const moduleB = {
  state: { ... },
  mutations: { ... },
  actions: { ... }
}

const store = new Vuex.Store({
  modules: {
    a: moduleA,
    b: moduleB
  }
})

store.state.a // -> moduleA 的狀態(tài)
store.state.b // -> moduleB 的狀態(tài)

插件

Vuex的store接受plugins選項(xiàng),這個(gè)選項(xiàng)暴露出每次mutation的鉤子。Vuex插件就是一個(gè)函數(shù),它接收store作為唯一參數(shù)。

嚴(yán)格模式

開啟嚴(yán)格模式,僅需在創(chuàng)建store的時(shí)候傳入strict:true

在嚴(yán)格模式下,無(wú)論何時(shí)發(fā)生了狀態(tài)變更且不是由mutation函數(shù)引起的,將會(huì)拋出錯(cuò)誤。這能保證所有的狀態(tài)變更都能被調(diào)試工具跟蹤到。

不要在發(fā)布環(huán)境下啟用嚴(yán)格模式!嚴(yán)格模式會(huì)深度監(jiān)測(cè)狀態(tài)樹來(lái)檢測(cè)不合規(guī)的狀態(tài)變更--請(qǐng)確保在發(fā)布環(huán)境下關(guān)閉嚴(yán)格模式,以避免性能損失。

表單處理

測(cè)試

熱重載

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • VUE Vue :數(shù)據(jù)驅(qū)動(dòng)的M V Vm框架 m :model(后臺(tái)提供數(shù)據(jù)),v :view(頁(yè)面),vM(模板...
    wudongyu閱讀 5,527評(píng)論 0 11
  • 使用說(shuō)明-Vuex 安裝 直接下載 / CDN 引用 Unpkg.com 提供了基于 NPM 的 CDN 鏈接。以...
    滿是裂縫的花卷閱讀 1,078評(píng)論 0 8
  • Vue知識(shí)點(diǎn)的總結(jié) Vue中的指令及其基本語(yǔ)法: 第一步:從官網(wǎng)上下載vue開發(fā)版本的js文件 引入js文件 ...
    往前走莫回頭_2cd6閱讀 1,545評(píng)論 0 1
  • 計(jì)算屬性如何使用 一般我們?cè)趯憊ue的時(shí)候,在模板內(nèi)寫的表達(dá)式非常便利,它運(yùn)用于簡(jiǎn)單的運(yùn)算,但是他也有一些復(fù)雜的邏...
    X秀秀閱讀 13,819評(píng)論 1 19
  • 今天晨讀里感觸最深的一點(diǎn)是要關(guān)注結(jié)果。現(xiàn)在做事之前,會(huì)列計(jì)劃,做規(guī)劃,讓自己明確要做什么,要先做什么后做什么。但是...
    趙三多閱讀 266評(píng)論 0 2

友情鏈接更多精彩內(nèi)容