2019年第14周前端學習記錄

### css

#### linear-gradient() 函數

linear-gradient() 函數用於創建一個線性漸變的 "圖像"。

為了創建一個線性漸變,你需要設置一個起始點和一個方向(指定為一個角度)的漸變效果。你還要定義終止色。終止色就是你想讓Gecko去平滑的過渡,並且你必須指定至少兩種,當然也會可以指定更多的顏色去創建更復雜的漸變效果。

如:background: linear-gradient(to left, #334b72, #fff, #334b72);

### js

#### toString(radix) 方法

value.toString()把數字轉換為字符串:

radix可選。規定表示數字的基數,是 2 ~ 36 之間的整數。若省略該參數,則使用基數 10。但是要注意,如果該參數是 10 以外的其他值,則 ECMAScript 標準允許實現返回任意值。

如: var num =15;

var a = num.toString(); 15 10 - 數字默認是以二進制值顯示

var b = num.toString(2); 1111 2 - 數字以二進制值顯示

var c = num.toString(8); 17 8 - 數字以八進制值顯示

var d = num.toString(16); f 16 - 數字以十六進制值顯示

#### toUpperCase() 方法

string.toUpperCase() 方法用於把字符串轉換為大寫。

toUpperCase() 方法用於把字符串轉換為大寫。

#### slice() 方法

slice() 方法可從已有的數組中返回選定的元素。

arrayObject.slice(start,end)

start: 必需。規定從何處開始選取。如果是負數,那麼它規定從數組尾部開始算起的位置。也就是說,-1 指最後一個元素,-2 指倒數第二個元素,以此類推。

end : 可選。規定從何處結束選取。該參數是數組片斷結束處的數組下標。如果沒有指定該參數,那麼切分的數組包含從 start 到數組結束的所有元素。如果這個參數是負數,那麼它規定的是從數組尾部開始算起的元素。

返回值: 返回一個新的數組,包含從 start 到 end (不包括該元素)的 arrayObject 中的元素。

說明 : 請注意,該方法並不會修改數組,而是返回一個子數組。如果想刪除數組中的一段元素,應該使用方法 Array.splice()。

#### splice()方法

splice() 方法向/從數組中添加/刪除項目,然後返回被刪除的項目。

splice() 方法向/從數組中添加/刪除項目,然後返回被刪除的項目。該方法會改變原始數組。

arrayObject.splice(index,howmany,item1,.....,itemX)

index 必需。整數,規定添加/刪除項目的位置,使用負數可從數組結尾處規定位置。

howmany 必需。要刪除的項目數量。如果設置為 0,則不會刪除項目。

item1, ..., itemX 可選。向數組添加的新項目。

splice() 方法可刪除從 index 處開始的零個或多個元素,並且用參數列表中聲明的一個或多個值來替換那些被刪除的元素。

如果從 arrayObject 中刪除了元素,則返回的是含有被刪除的元素的數組。

#### filter() 方法

filter() 方法創建一個新的數組,新數組中的元素是通過檢查指定數組中符合條件的所有元素。

注意: filter() 不會對空數組進行檢測。

注意: filter() 不會改變原始數組。

array.filter(function(currentValue,index,arr), thisValue)

currentValue 必須。當前元素的值

index 可選。當前元素的索引值

arr 可選。當前元素屬於的數組對象

thisValue 可選。對象作為該執行回調時使用,傳遞給函數,用作 "this" 的值。如果省略了 thisValue ,"this" 的值為 "undefined"

返回值: 返回數組,包含了符合條件的所有元素。如果沒有符合條件的元素則返回空數組。

### vue

#### vuex

Vuex 應用的核心就是 store(倉庫)。“store”基本上就是一個容器,它包含著你的應用中大部分的狀態 (state)。Vuex 和單純的全局對象有以下兩點不同:

Vuex 的狀態存儲是響應式的。當 Vue 組件從 store 中讀取狀態的時候,若 store 中的狀態發生變化,那麼相應的組件也會相應地得到高效更新。

你不能直接改變 store 中的狀態。改變 store 中的狀態的唯一途徑就是顯式地提交 (commit) mutation。這樣使得我們可以方便地跟蹤每一個狀態的變化,從而讓我們能夠實現一些工具幫助我們更好地瞭解我們的應用。

##### state

Vuex 使用單一狀態樹——是的,用一個對象就包含了全部的應用層級狀態。至此它便作為一個“唯一數據源 (SSOT)”而存在。這也意味著,每個應用將僅僅包含一個 store 實例。

由於 Vuex 的狀態存儲是響應式的,從 store 實例中讀取狀態最簡單的方法就是在計算屬性中返回某個狀態:

```

// 創建一個 Counter 組件

const Counter = {

template: `

{{ count }}
`,

computed: {

count () {

return store.state.count

}

}

}

```

然而,這種模式導致組件依賴全局狀態單例。在模塊化的構建系統中,在每個需要使用 state 的組件中需要頻繁地導入,並且在測試組件時需要模擬狀態。

Vuex 通過 store 選項,提供了一種機制將狀態從根組件“注入”到每一個子組件中(需調用 Vue.use(Vuex)):

```

import store from './store'

const app = new Vue({

el: '#app',

// 把 store 對象提供給 “store” 選項,這可以把 store 的實例注入所有的子組件

store,

components: { Counter },

template: `

<counter>

`

})

```

通過在根實例中註冊 store 選項,該 store 實例會注入到根組件下的所有子組件中,且子組件能通過 this.$store 訪問到。讓我們更新下 Counter 的實現:

```

const Counter = {

template: `

{{ count }}
`,

computed: {

count () {

return this.$store.state.count

}

}

}

```

##### getter

有時候我們需要從 store 中的 state 中派生出一些狀態,例如對列表進行過濾並計數:

```

computed: {

doneTodosCount () {

return this.$store.state.todos.filter(todo => todo.done).length

}

}

```

如果有多個組件需要用到此屬性,我們要麼複製這個函數,或者抽取到一個共享函數然後在多處導入它——無論哪種方式都不是很理想。

Vuex 允許我們在 store 中定義“getter”(可以認為是 store 的計算屬性)。就像計算屬性一樣,getter 的返回值會根據它的依賴被緩存起來,且只有當它的依賴值發生了改變才會被重新計算。

Getter 接受 state 作為其第一個參數:

```

const store = new Vuex.Store({

state: {

todos: [

{ id: 1, text: '...', done: true },

{ id: 2, text: '...', done: false }

]

},

getters: {

doneTodos: state => {

return state.todos.filter(todo => todo.done)

}

}

})

```

通過屬性訪問

Getter 會暴露為 store.getters 對象,你可以以屬性的形式訪問這些值:

```

store.getters.doneTodos // -> [{ id: 1, text: '...', done: true }]

```

Getter 也可以接受其他 getter 作為第二個參數:

```

getters: {

// ...

doneTodosCount: (state, getters) => {

return getters.doneTodos.length

}

}

store.getters.doneTodosCount // -> 1

```

我們可以很容易地在任何組件中使用它:

```

computed: {

doneTodosCount () {

return this.$store.getters.doneTodosCount

}

}

```

注意,getter 在通過屬性訪問時是作為 Vue 的響應式系統的一部分緩存其中的。

通過方法訪問

你也可以通過讓 getter 返回一個函數,來實現給 getter 傳參。在你對 store 裡的數組進行查詢時非常有用。

```

getters: {

// ...

getTodoById: (state) => (id) => {

return state.todos.find(todo => todo.id === id)

}

}

```

store.getters.getTodoById(2) // -> { id: 2, text: '...', done: false }

注意,getter 在通過方法訪問時,每次都會去進行調用,而不會緩存結果。

##### mutation

更改 Vuex 的 store 中的狀態的唯一方法是提交 mutation。Vuex 中的 mutation 非常類似於事件:每個 mutation 都有一個字符串的 事件類型 (type) 和 一個 回調函數 (handler)。這個回調函數就是我們實際進行狀態更改的地方,並且它會接受 state 作為第一個參數:

```

const store = new Vuex.Store({

state: {

count: 1

},

mutations: {

increment (state) {

// 變更狀態

state.count++

}

}

})

```

你不能直接調用一個 mutation handler。這個選項更像是事件註冊:“當觸發一個類型為 increment 的 mutation 時,調用此函數。”要喚醒一個 mutation handler,你需要以相應的 type 調用 store.commit 方法:

```

store.commit('increment')

```

提交載荷(Payload)

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

```

mutations: {

increment (state, n) {

state.count += n

}

}

store.commit('increment', 10)

```

在大多數情況下,載荷應該是一個對象,這樣可以包含多個字段並且記錄的 mutation 會更易讀:

```

mutations: {

increment (state, payload) {

state.count += payload.amount

}

}

store.commit('increment', {

amount: 10

})

```

對象風格的提交方式

提交 mutation 的另一種方式是直接使用包含 type 屬性的對象:

```

store.commit({

type: 'increment',

amount: 10

})

```

當使用對象風格的提交方式,整個對象都作為載荷傳給 mutation 函數,因此 handler 保持不變:

```

mutations: {

increment (state, payload) {

state.count += payload.amount

}

}

```

Mutation 需遵守 Vue 的響應規則

既然 Vuex 的 store 中的狀態是響應式的,那麼當我們變更狀態時,監視狀態的 Vue 組件也會自動更新。這也意味著 Vuex 中的 mutation 也需要與使用 Vue 一樣遵守一些注意事項:

最好提前在你的 store 中初始化好所有所需屬性。

當需要在對象上添加新屬性時,你應該

使用 Vue.set(obj, 'newProp', 123), 或者

以新對象替換老對象。例如,利用 stage-3 的對象展開運算符我們可以這樣寫:

```

state.obj = { ...state.obj, newProp: 123 }

```

Mutation 必須是同步函數

一條重要的原則就是要記住 mutation 必須是同步函數。為什麼?請參考下面的例子:

```

mutations: {

someMutation (state) {

api.callAsyncMethod(() => {

state.count++

})

}

}

```

現在想象,我們正在 debug 一個 app 並且觀察 devtool 中的 mutation 日誌。每一條 mutation 被記錄,devtools 都需要捕捉到前一狀態和後一狀態的快照。然而,在上面的例子中 mutation 中的異步函數中的回調讓這不可能完成:因為當 mutation 觸發的時候,回調函數還沒有被調用,devtools 不知道什麼時候回調函數實際上被調用——實質上任何在回調函數中進行的狀態的改變都是不可追蹤的

在 mutation 中混合異步調用會導致你的程序很難調試。例如,當你調用了兩個包含異步回調的 mutation 來改變狀態,你怎麼知道什麼時候回調和哪個先回調呢?這就是為什麼我們要區分這兩個概念。在 Vuex 中,mutation 都是同步事務:

```

store.commit('increment')

// 任何由 "increment" 導致的狀態變更都應該在此刻完成。

```

在組件中提交 Mutation

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

```

import { mapMutations } from 'vuex'

export default {

methods: {

...mapMutations([

'increment', // 將 `this.increment()` 映射為 `this.$store.commit('increment')`

// `mapMutations` 也支持載荷:

'incrementBy' // 將 `this.incrementBy(amount)` 映射為 `this.$store.commit('incrementBy', amount)`

]),

...mapMutations({

add: 'increment' // 將 `this.add()` 映射為 `this.$store.commit('increment')`

})

}

}

```

##### Action

Action 類似於 mutation,不同在於:

* Action 提交的是 mutation,而不是直接變更狀態。

* Action 可以包含任意異步操作

```

const store = new Vuex.Store({

state: {

count: 0

},

mutations: {

increment (state) {

state.count++

}

},

actions: {

increment (context) {

context.commit('increment')

}

}

})

```

Action 函數接受一個與 store 實例具有相同方法和屬性的 context 對象,因此你可以調用 context.commit 提交一個 mutation,或者通過 context.state 和 context.getters 來獲取 state 和 getters。當我們在之後介紹到 Modules 時,你就知道 context 對象為什麼不是 store 實例本身了。

分發 Action : Action 通過 store.dispatch 方法觸發:

```

actions: {

increment ({ commit }) {

commit('increment')

}

}

store.dispatch('increment')

```

Actions 支持同樣的載荷方式和對象方式進行分發:

```

// 以載荷形式分發

store.dispatch('incrementAsync', {

amount: 10

})

// 以對象形式分發

store.dispatch({

type: 'incrementAsync',

amount: 10

})

```

##### module

使用單一狀態樹,應用的所有狀態會集中到一個比較大的對象。當應用變得非常複雜時,store 對象就有可能變得相當臃腫。

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

```

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 的狀態

store.state.b // -> moduleB 的狀態

```

模塊的局部狀態

對於模塊內部的 mutation 和 getter,接收的第一個參數是模塊的局部狀態對象。

```

const moduleA = {

state: { count: 0 },

mutations: {

increment (state) {

// 這裡的 `state` 對象是模塊的局部狀態

state.count++

}

},

getters: {

doubleCount (state) {

return state.count * 2

}

}

}

```

#### 計算屬性 computed

模板內的表達式非常便利,但是設計它們的初衷是用於簡單運算的。在模板中放入太多的邏輯會讓模板過重且難以維護。當在模板中使用複雜的邏輯時,應當使用計算屬性;

```

Original message: "{{ message }}"

Computed reversed message: "{{ reversedMessage }}"

var vm = new Vue({

el: '#example',

data: {

message: 'Hello'

},

computed: {

// 計算屬性的 getter

reversedMessage: function () {

// `this` 指向 vm 實例

return this.message.split('').reverse().join('')

}

}

})

```

##### 計算屬性緩存 vs 方法

你可能已經注意到我們可以通過在表達式中調用方法來達到同樣的效果:我們可以將同一函數定義為一個方法而不是一個計算屬性。兩種方式的最終結果確實是完全相同的。

```

Reversed message: "{{ reversedMessage() }}"

// 在組件中

methods: {

reversedMessage: function () {

return this.message.split('').reverse().join('')

}

}

```

然而,不同的是計算屬性是基於它們的響應式依賴進行緩存的。只在相關響應式依賴發生改變時它們才會重新求值。這就意味著只要 message 還沒有發生改變,**多次訪問 reversedMessage 計算屬性會立即返回之前的計算結果,而不必再次執行函數**。相比之下,**每當觸發重新渲染時,調用方法將總會再次執行函數**

注意:如果你不希望有緩存,請用方法來替代。

##### 計算屬性 vs 偵聽屬性

Vue 提供了一種更通用的方式來觀察和響應 Vue 實例上的數據變動:偵聽屬性。

當你有一些數據需要隨著其它數據變動而變動時,你很容易濫用 watch 。 然而,通常更好的做法是使用計算屬性而不是命令式的 watch 回調。

```

{{ fullName }}

var vm = new Vue({

el: '#demo',

data: {

firstName: 'Foo',

lastName: 'Bar',

fullName: 'Foo Bar'

},

watch: {

firstName: function (val) {

this.fullName = val + ' ' + this.lastName

},

lastName: function (val) {

this.fullName = this.firstName + ' ' + val

}

}

})

上面代碼是命令式且重複的。將它與計算屬性的版本進行比較:

var vm = new Vue({

el: '#demo',

data: {

firstName: 'Foo',

lastName: 'Bar'

},

computed: {

fullName: function () {

return this.firstName + ' ' + this.lastName

}

}

})

```

##### 計算屬性的 setter

計算屬性默認只有 getter ,不過在需要時你也可以提供一個 setter :

```

computed: {

fullName: {

// getter

get: function () {

return this.firstName + ' ' + this.lastName

},

// setter

set: function (newValue) {

var names = newValue.split(' ')

this.firstName = names[0]

this.lastName = names[names.length - 1]

}

}

}

```

現在再運行 vm.fullName = 'John Doe' 時,setter 會被調用,vm.firstName 和 vm.lastName 也會相應地被更新。


分享到:


相關文章: