共计 6868 个字符,预计需要花费 18 分钟才能阅读完成。
不要在选项 property 或回调上应用箭头函数,比方:
created: () => console.log(this.a)
或
vm.$watch('a', newValue => this.myMethod())。因为箭头函数并没有 this,this 会作为变量始终向下级词法作用域查找,直至找到为止,常常导致
Uncaught TypeError: Cannot read property of undefined
或
Uncaught TypeError: this.myMethod is not a function
之类的谬误。
你的站点上动静渲染的任意 HTML 可能会十分危险,因为它很容易导致 XSS 攻打。请只对可信内容应用 HTML 插值,绝不要对用户提供的内容应用插值。
模板表达式都被放在沙盒中,只能拜访全局变量的一个白名单,如 Math 和 Date。你不应该在模板表达式中试图拜访用户定义的全局变量。
在 DOM 中应用模板时 (间接在一个 HTML 文件里撰写模板),还须要防止应用大写字符来命名键名,因为浏览器会把 attribute 名全副强制转为小写:
<!--
在 DOM 中应用模板时这段代码会被转换为 `v-bind:[someattr]`。除非在实例中有一个名为“someattr”的 property,否则代码不会工作。-->
<a v-bind:[someAttr]="value"> ... </a>
留神,v-show 不反对 <template> 元素,也不反对 v-else。
v-if 是“真正”的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。v-if 也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。相比之下,v-show 就简略得多——不论初始条件是什么,元素总是会被渲染,并且只是简略地基于 CSS 进行切换。一般来说,v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。因而,如果须要十分频繁地切换,则应用 v-show 较好;如果在运行时条件很少扭转,则应用 v-if 较好。
防止 v-if 和 v-for 用在一起
当它们处于同一节点,v-for 的优先级比 v-if 更高,这意味着 v-if 将别离反复运行于每个 v-for 循环中。当你只想为局部项渲染节点时,这种优先级的机制会非常有用,如下:
<li v-for="todo in todos" v-if="!todo.isComplete">
{{todo}}
</li>
下面的代码将只渲染未实现的 todo。
而如果你的目标是有条件地跳过循环的执行,那么能够将 v-if 置于外层元素 (或 <template>) 上。如:
<ul v-if="todos.length">
<li v-for="todo in todos">
{{todo}}
</li>
</ul>
<p v-else>No todos left!</p>
为组件款式设置作用域
对于利用来说,顶级 App 组件和布局组件中的款式能够是全局的,然而其它所有组件都应该是有作用域的。
这条规定只和单文件组件无关。你不肯定要应用 scoped attribute。设置作用域也能够通过 CSS Modules,那是一个基于 class 的相似 BEM 的策略,当然你也能够应用其它的库或约定。
<template>
<button class="button button-close">X</button>
</template>
<!-- 应用 `scoped` attribute -->
<style scoped>
.button {
border: none;
border-radius: 2px;
}
.button-close {background-color: red;}
</style>
<template>
<button :class="[$style.button, $style.buttonClose]">X</button>
</template>
<!-- 应用 CSS Modules -->
<style module>
.button {
border: none;
border-radius: 2px;
}
.buttonClose {background-color: red;}
</style>
<template>
<button class="c-Button c-Button--close">X</button>
</template>
<!-- 应用 BEM 约定 -->
<style>
.c-Button {
border: none;
border-radius: 2px;
}
.c-Button--close {background-color: red;}
</style>
公有 property 名
应用模块作用域放弃不容许内部拜访的函数的公有性。如果无奈做到这一点,就始终为插件、混入等不思考作为对外公共 API 的自定义公有 property 应用 $_ 前缀。并附带一个命名空间以回避和其它作者的抵触 (比方 $_yourPluginName_)。
var myGreatMixin = {
// ...
methods: {$_myGreatMixin_update: function () {// ...}
}
}
// 甚至更好!var myGreatMixin = {
// ...
methods: {publicMethod() {
// ...
myPrivateFunction()}
}
}
function myPrivateFunction() {// ...}
export default myGreatMixin
单文件组件文件的大小写
单文件组件的文件名应该要么始终是单词大写结尾 (PascalCase),要么始终是横线连贯 (kebab-case)。
单词大写结尾对于代码编辑器的主动补全最为敌对,因为这使得咱们在 JS(X) 和模板中援用组件的形式尽可能的统一。然而,混用文件命名形式有的时候会导致大小写不敏感的文件系统的问题,这也是横线连贯命名同样齐全可取的起因。
components/
|- MyComponent.vue
components/
|- my-component.vue
根底组件名
利用特定款式和约定的根底组件 (也就是展现类的、无逻辑的或无状态的组件) 应该全副以一个特定的前缀结尾,比方 Base、App 或 V。
components/
|- BaseButton.vue
|- BaseTable.vue
|- BaseIcon.vue
components/
|- AppButton.vue
|- AppTable.vue
|- AppIcon.vue
components/
|- VButton.vue
|- VTable.vue
|- VIcon.vue
单例组件名
只应该领有单个沉闷实例的组件应该以 The 前缀命名,以示其唯一性。
这不意味着组件只可用于一个单页面,而是每个页面只应用一次。这些组件永远不承受任何 prop,因为它们是为你的利用定制的,而不是它们在你的利用中的上下文。如果你发现有必要增加 prop,那就表明这实际上是一个可复用的组件,只是目前在每个页面里只应用一次。
components/
|- TheHeading.vue
|- TheSidebar.vue
严密耦合的组件名
和父组件严密耦合的子组件应该以父组件名作为前缀命名。
如果一个组件只在某个父组件的场景下有意义,这层关系应该体现在其名字上。因为编辑器通常会按字母程序组织文件,所以这样做能够把相关联的文件排在一起。
components/
|- TodoList.vue
|- TodoListItem.vue
|- TodoListItemButton.vue
components/
|- SearchSidebar.vue
|- SearchSidebarNavigation.vue
组件名中的单词程序
组件名应该以高级别的 (通常是一般化形容的) 单词结尾,以描述性的修饰词结尾。
components/
|- SearchButtonClear.vue
|- SearchButtonRun.vue
|- SearchInputQuery.vue
|- SearchInputExcludeGlob.vue
|- SettingsCheckboxTerms.vue
|- SettingsCheckboxLaunchOnStartup.vue
自闭合组件
在单文件组件、字符串模板和 JSX 中没有内容的组件应该是自闭合的——但在 DOM 模板里永远不要这样做。
自闭合组件示意它们不仅没有内容,而且刻意没有内容。其不同之处就如同书上的一页白纸比照贴有“本页无意留白”标签的白纸。而且没有了额定的闭合标签,你的代码也更简洁。
可怜的是,HTML 并不反对自闭合的自定义元素——只有官网的“空”元素。所以上述策略仅实用于进入 DOM 之前 Vue 的模板编译器可能触达的中央,而后再产出合乎 DOM 标准的 HTML。
<!-- 在单文件组件、字符串模板和 JSX 中 -->
<MyComponent/>
<!-- 在 DOM 模板中 -->
<my-component></my-component>
模板中的组件名大小写
对于绝大多数我的项目来说,在单文件组件和字符串模板中组件名应该总是 PascalCase 的——然而在 DOM 模板中总是 kebab-case 的。
PascalCase 相比 kebab-case 有一些劣势:
编辑器能够在模板里主动补全组件名,因为 PascalCase 同样实用于 JavaScript。
<MyComponent> 视觉上比 <my-component> 更可能和单个单词的 HTML 元素区别开来,因为前者的不同之处有两个大写字母,后者只有一个横线。
如果你在模板中应用任何非 Vue 的自定义元素,比方一个 Web Component,PascalCase 确保了你的 Vue 组件在视觉上依然是易辨认的。
可怜的是,因为 HTML 是大小写不敏感的,在 DOM 模板中必须仍应用 kebab-case。
还请留神,如果你曾经是 kebab-case 的重度用户,那么与 HTML 保持一致的命名约定且在多个我的项目中放弃雷同的大小写规定就可能比上述劣势更为重要了。在这些状况下,在所有的中央都应用 kebab-case 同样是能够承受的。
<!-- 在单文件组件和字符串模板中 -->
<MyComponent/>
<!-- 在 DOM 模板中 -->
<my-component></my-component>
或者
<!-- 在所有中央 -->
<my-component></my-component>
JS/JSX 中的组件名大小写
JS/JSX 中的组件名应该始终是 PascalCase 的,只管在较为简单的利用中只应用 Vue.component 进行全局组件注册时,能够应用 kebab-case 字符串。
Vue.component('MyComponent', {// ...})
Vue.component('my-component', {// ...})
import MyComponent from './MyComponent.vue'
export default {
name: 'MyComponent',
// ...
}
Prop 名大小写
在申明 prop 的时候,其命名应该始终应用 camelCase,而在模板和 JSX 中应该始终应用 kebab-case。
咱们单纯的遵循每个语言的约定。在 JavaScript 中更天然的是 camelCase。而在 HTML 中则是 kebab-case。
props: {greetingText: String}
<WelcomeMessage greeting-text="hi"/>
模板中简略的表达式
组件模板应该只蕴含简略的表达式,简单的表达式则应该重构为计算属性或办法。
<!-- 在模板中 -->
{{normalizedFullName}}
// 简单表达式曾经移入一个计算属性
computed: {normalizedFullName: function () {return this.fullName.split(' ').map(function (word) {return word[0].toUpperCase() + word.slice(1)
}).join(' ')
}
}
简略的计算属性
应该把简单计算属性宰割为尽可能多的更简略的 property。
computed: {basePrice: function () {return this.manufactureCost / (1 - this.profitMargin)
},
discount: function () {return this.basePrice * (this.discountPercent || 0)
},
finalPrice: function () {return this.basePrice - this.discount}
}
带引号的 attribute 值
非空 HTML attribute 值应该始终带引号 (单引号或双引号,选你 JS 里不必的那个)。
<input type="text">
<AppSidebar :style="{width: sidebarWidth +'px'}">
指令缩写
指令缩写 (用 : 示意 v-bind:、用 @ 示意 v-on: 和用 # 示意 v-slot:) 应该要么都用要么都不必。
隐性的父子组件通信
应该优先通过 prop 和事件进行父子组件之间的通信,而不是 this.$parent 或变更 prop。
2.2.0+ 的版本里,当在组件上应用 v-for 时,key 当初是必须的。
事件修饰符
在事件处理程序中调用 event.preventDefault() 或 event.stopPropagation() 是十分常见的需要。只管咱们能够在办法中轻松实现这点,但更好的形式是:办法只有纯正的数据逻辑,而不是去解决 DOM 事件细节。
为了解决这个问题,Vue.js 为 v-on 提供了事件修饰符。之前提过,修饰符是由点结尾的指令后缀来示意的。
.stop
.prevent
.capture
.self
.once
.passive
<!-- 阻止单击事件持续流传 -->
<a v-on:click.stop="doThis"></a>
<!-- 提交事件不再重载页面 -->
<form v-on:submit.prevent="onSubmit"></form>
<!-- 修饰符能够串联 -->
<a v-on:click.stop.prevent="doThat"></a>
<!-- 只有修饰符 -->
<form v-on:submit.prevent></form>
<!-- 增加事件监听器时应用事件捕捉模式 -->
<!-- 即外部元素触发的事件先在此解决,而后才交由外部元素进行解决 -->
<div v-on:click.capture="doThis">...</div>
<!-- 只当在 event.target 是以后元素本身时触发处理函数 -->
<!-- 即事件不是从外部元素触发的 -->
<div v-on:click.self="doThat">...</div>
值得注意的是:
应用修饰符时,程序很重要;相应的代码会以同样的程序产生。因而,用 v-on:click.prevent.self 会阻止所有的点击,而 v-on:click.self.prevent 只会阻止对元素本身的点击。
其中:
<!-- 点击事件将只会触发一次 -->
<a v-on:click.once="doThis"></a>
<!-- 不像其它只能对原生的 DOM 事件起作用的修饰符,.once 修饰符还能被用到自定义的组件事件上。如果你还没有浏览对于组件的文档,当初大可不必放心。-->
Vue 还对应 addEventListener 中的 passive 选项提供了 .passive 修饰符。
<!-- 滚动事件的默认行为 (即滚动行为) 将会立刻触发 -->
<!-- 而不会期待 `onScroll` 实现 -->
<!-- 这其中蕴含 `event.preventDefault()` 的状况 -->
<div v-on:scroll.passive="onScroll">...</div>
这个 .passive 修饰符尤其可能晋升挪动端的性能。不要把 .passive 和 .prevent 一起应用,因为 .prevent 将会被疏忽,同时浏览器可能会向你展现一个正告。请记住,.passive 会通知浏览器你不想阻止事件的默认行为。
按键修饰符
在监听键盘事件时,咱们常常须要查看具体的按键。Vue 容许为 v-on 在监听键盘事件时增加按键修饰符:
<!-- 只有在 `key` 是 `Enter` 时调用 `vm.submit()` -->
<input v-on:keyup.enter="submit">
你能够间接将 KeyboardEvent.key 裸露的任意无效按键名转换为 kebab-case 来作为修饰符。
<input v-on:keyup.page-down="onPageDown">
在上述示例中,处理函数只会在 $event.key 等于 PageDown 时被调用。
更多键盘按键、零碎润饰键、鼠标按键的管制监听请拜访 vue 官网文档:https://cn.vuejs.org/v2/guide…