Vue cookbook 读书笔记

添加实例属性

基本的示例

你可能会在很多组件里用到数据/实用工具,为避免 污染全局作用域 可以通过在原型上定义它们使其在每个 Vue 的实例中可用。

1
2
3
4
5
6
7
8
Vue.prototype.$appName = 'My App'// $ 符号是为了避免和已被定义的数据、方法、计算属性产生冲突,在 Vue 所有实例中都可用的属性的一个简单约定

// 这样 $appName 就在所有的 Vue 实例中可用了,甚至在实例被创建之前就可以
new Vue({
beforeCreate: function () {
console.log(this.$appName)
}
})

这确实是个好办法,在不知道可以这么做的时候我经常会在一些公用方法上使用全局作用域来调用。有时候公用方法多了,很容易造成命名冲突,造成混乱。

原型方法的上下文

在 JavaScript 中一个原型的方法会获得该实例的上下文。也就是说它们可以使用 this 访问数据、计算属性、方法或其它任何定义在实例上的东西。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Vue.prototype.$reverseText = function (propertyName) {
this[propertyName] = this[propertyName]
.split('')
.reverse()
.join('')
}

new Vue({
data: {
message: 'Hello'
},
created: function () {
console.log(this.message) // => "Hello"
this.$reverseText('message')
console.log(this.message) // => "olleH"
}
})

注意如果你使用了 ES6/2015 的箭头函数,则其绑定的上下文不会正常工作,因为它们会隐式地绑定其父级作用域。

1
2
3
4
5
6
7
8
9
Vue.prototype.$reverseText = propertyName => {
this[propertyName] = this[propertyName]
.split('')
.reverse()
.join('')
}

//会抛出一个错误:
//Uncaught TypeError: Cannot read property 'split' of undefined

何时避免使用这个模式

  • 何时避免使用这个模式
  • 这种便利是以显性表达为代价的。当我们查阅一个组件的时候,要注意交代清楚 $http 是从哪来的:Vue 自身、一个插件、还是一个辅助库?

替代方案(说实话看到这里的我是有点懵的)

没有使用模块系统时

(原文档还有个使用模块系统时,其实就是推荐使用模块化开发,模块分的越细越好,尤其是多人开发时,会更好维护)

cookbook 中给出的代替方案是创建一个全局 App 对象。???? 所以开始说的会污染作用域是什么鬼?是我没理解作者的意图?

原文:在没有模块系统 (比如 webpack 或 Browserify) 的应用中,存在一种任何重 JS 前端应用都常用的模式:一个全局的 App 对象。

例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var App = Object.freeze({// Object.freeze 是为了将 App 的属性变为常量,避免在未来出现状态的 bug。
name: 'My App',
version: '2.1.4',
helpers: {
// 这我们之前见到过的 `$reverseText` 方法
// 的一个纯函数版本
reverseText: function (text) {
return text
.split('')
.reverse()
.join('')
}
}
})

好处是:

  1. 共享的属性的来源就更加明显
  2. 可以在你代码的任何地方使用

调用:

1
2
3
4
5
6
7
8
new Vue({
data: {
appVersion: App.version
},
methods: {
reverseText: App.helpers.reverseText
}
})

现在容我捋一捋

前面说的应该是 那些只在 vue 实例里应用的工具,推荐使用 实例属性 创建,这样就能保证全局作用域减少污染,还能解决工具调用的上下文问题(这里使用的是原型方法)。

而最后推荐的代替方案 创建全局对象 则是 没有模块系统,在我们所对该工具的使用情景模糊的情况下(跟 vue 本身没他多关系,使用场景也模糊不定),所以就没有必要非得跟 vue 扯上关系,强加给人家一个属性方法。做成 全局对象 想用哪里用哪里,妈妈再也不用担心的我 vue 了…

我目前学的还很浅,可能也就是目前的我的理解(连蒙带猜)了,希望以后我能回过头来还能有更深、思路更清晰的理解。