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 也会相应地被更新。


分享到:


相關文章: