Vue 开发规范(中)
上一篇:https://www.imgeek.org/article/825358938
将 this 赋值给 component 变量
在 Vue.js 组件上下文中,this指向了组件实例。因此当你切换到了不同的上下文时,要确保 this 指向一个可用的 component 变量。
换句话说,如果你正在使用 ES6 的话,就不要再编写 var self = this; 这样的代码了,您可以安全地使用 Vue 组件。
为什么?
- 使用 ES6,就不再需要将 this 保存到一个变量中了。
- 一般来说,当你使用箭头函数时,会保留 this 的作用域。(译者注:箭头函数没有它自己的 this 值,箭头函数内的 this 值继承自外围作用域。)
- 如果你没有使用 ES6,当然也就不会使用 箭头函数 啦,那你必须将 “this” 保存到到某个变量中。这是唯一的例外。
怎么做?
<script type="text/javascript">
export default { methods: { hello() { return 'hello'; }, printHello() { console.log(this.hello()); }, }, };
</script>
<!-- 避免 -->
<script type="text/javascript">
export default { methods: { hello() { return 'hello'; }, printHello() { const self = this; // 没有必要 console.log(self.hello()); }, }, };
</script>
组件结构化
按照一定的结构组织,使得组件便于理解。
为什么?
- 导出一个清晰、组织有序的组件,使得代码易于阅读和理解。同时也便于标准化。
- 按首字母排序 properties、data、computed、watches 和 methods 使得这些对象内的属性便于查找。
- 合理组织,使得组件易于阅读。(name; extends; props, data 和 computed; components; watch 和 methods; lifecycle methods 等)。
- 使用 name 属性。借助于 vue devtools 可以让你更方便的测试。
- 合理的 CSS 结构,如 BEM 或 rscss - 详情?。
- 使用单文件 .vue 文件格式来组件代码。
怎么做?
组件结构化
<template lang="html">
<div class="Ranger__Wrapper">
<!-- ... -->
</div>
</template>
<script type="text/javascript">
export default {
// 不要忘记了 name 属性 name: 'RangeSlider',
// 组合其它组件 extends: {},
// 组件属性、变量 props: { bar: {},
// 按字母顺序 foo: {}, fooBar: {}, },
// 变量 data() {}, computed: {},
// 使用其它组件 components: {},
// 方法 watch: {}, methods: {},
// 生命周期函数 beforeCreate() {}, mounted() {}, };
</script>
<style scoped> .Ranger__Wrapper { /* ... */ } </style>
组件事件命名
Vue.js 提供的处理函数和表达式都是绑定在 ViewModel 上的,组件的每一个事件都应该按照一个好的命名规范来,这样可以避免不少的开发问题,具体可见如下 为什么。
为什么?
- 开发者可以随意给事件命名,即使是原生事件的名字,这样会带来迷惑性。
- 过于宽松的事件命名可能与 DOM 模板不兼容。
怎么做?
- 事件名也使用连字符命名。
- 一个事件的名字对应组件外的一组意义操作,如:upload-success、upload-error 以及 dropzone-upload-success、dropzone-upload-error (如果需要前缀的话)。
- 事件命名应该以动词(如 client-api-load) 或是 形容词(如 drive-upload-success)结尾。(出处)
避免 this.$parent
Vue.js 支持组件嵌套,并且子组件可访问父组件的上下文。访问组件之外的上下文违反了基于模块开发的第一原则。因此你应该尽量避免使用 this.$parent。
为什么?
- 组件必须相互保持独立,Vue 组件也是。如果组件需要访问其父层的上下文就违反了该原则。
- 如果一个组件需要访问其父组件的上下文,那么该组件将不能在其它上下文中复用。
怎么做?
- 通过
props
将值传递给子组件。 - 通过
props
传递回调函数给子组件来达到调用父组件方法的目的。 - 通过在子组件触发事件来通知父组件。
谨慎使用 this.$refs
Vue.js
支持通过 ref
属性来访问其它组件和 HTML
元素。并通过 this.$refs
可以得到组件或 HTML
元素的上下文。在大多数情况下,通过 this.$refs
来访问其它组件的上下文是可以避免的。在使用的的时候你需要注意避免调用了不恰当的组件 API
,所以应该尽量避免使用 this.$refs
。
为什么?
- 组件必须是保持独立的,如果一个组件的
API
不能够提供所需的功能,那么这个组件在设计、实现上是有问题的。 - 组件的属性和事件必须足够的给大多数的组件使用。
怎么做?
- 提供良好的组件
API
。 - 总是关注于组件本身的目的。
- 拒绝定制代码。如果你在一个通用的组件内部编写特定需求的代码,那么代表这个组件的
API
不够通用,或者你可能需要一个新的组件来应对该需求。 - 检查所有的
props
是否有缺失的,如果有提一个issue
或是完善这个组件。 - 检查所有的事件。子组件向父组件通信一般是通过事件来实现的,但是大多数的开发者更多的关注于
props
从忽视了这点。 - Props向下传递,事件向上传递!。以此为目标升级你的组件,提供良好的 API 和 独立性。
- 当遇到
props
和events
难以实现的功能时,通过this.$refs
来实现。 - 当需要操作
DOM
无法通过指令来做的时候可使用this.$ref
而不是JQuery、document.getElement*、document.queryElement
。 - 基础使用准则是,能不用
ParseError: KaTeX parse error: Expected 'EOF', got '就' at position 5: refs就̲
尽量不用,如果用,尽量不要通过refs
操作状态,可以通过$refs
调用methods
。
<!-- 推荐,并未使用 this.$refs -->
<range :max="max" :min="min" @current-value="currentValue" :step="1"></range>
<!-- 使用 this.$refs 的适用情况-->
<modal ref="basicModal">
<h4>Basic Modal</h4>
<button class="primary" @click="$refs.basicModal.hide()">Close</button>
</modal>
<button @click="$refs.basicModal.open()">Open modal</button>
<!-- Modal component -->
<template>
<div v-show="active">
<!-- ... -->
</div>
</template>
<script>
export default { // ... data() { return { active: false, }; }, methods: { open() { this.active = true; }, hide() { this.active = false; }, }, // ... };
</script>
<!-- 这里是应该避免的 -->
<!-- 如果可通过 emited 来做则避免通过 this.$refs 直接访问 -->
<template>
<range :max="max" :min="min" ref="range" :step="1"></range>
</template>
<script>
export default { // ... methods: { getRangeCurrentValue() { return this.$refs.range.currentValue; }, }, // ... };
</script>
使用组件名作为样式作用域空间
Vue.js 的组件是自定义元素,这非常适合用来作为样式的根作用域空间。可以将组件名作为 CSS 类的命名空间。
为什么?
- 给样式加上作用域空间可以避免组件样式影响外部的样式。
- 保持模块名、目录名、样式根作用域名一样,可以很好的将其关联起来,便于开发者理解。
怎么做?
使用组件名作为样式命名的前缀,可基于 BEM 或 OOCSS 范式。同时给 style 标签加上 scoped 属性。加上 scoped 属性编译后会给组件的 class 自动加上唯一的前缀从而避免样式的冲突。
<style scoped> /* 推荐 */
.MyExample { }
.MyExample li { }
.MyExample__item { }
/* 避免 */
.My-Example { }
/* 没有用组件名或模块名限制作用域, 不符合 BEM 规范 */
</style>
作者:_Battle
链接:https://juejin.cn/post/7023548108214648863