# Vue 编码规范
TIP
Vue
规范主要包含编码风格, 其中编码风格 参考 eslint-plugin-vue (opens new window)。
# 1. 📚 编码风格
- 【推荐】防止 JSX 中使用的变量被标记为未使用
import HelloWorld from './HelloWorld';
export default {
render () {
return (
<HelloWorld msg="world"/>
)
},
};
- 【推荐】组件的 data 必须是一个函数
<script>
/* ✗ BAD */
Vue.component('some-comp', {
data: {
foo: 'bar'
}
})
export default {
data: {
foo: 'bar'
}
}
</script>
<script>
/* ✓ GOOD */
Vue.component('some-comp', {
data: function () {
return {
foo: 'bar'
}
}
})
export default {
data() {
return {
foo: 'bar'
}
}
}
</script>
- 【推荐】Prop 定义类型应该是构造函数
<script>
export default {
props: {
/* ✓ GOOD */
myProp: Number,
anotherProp: [Number, String],
myFieldWithBadType: {
type: Object,
default: function () {
return {}
},
},
myOtherFieldWithBadType: {
type: Number,
default: 1,
},
/* ✗ BAD */
myProp: 'Number',
anotherProp: ['Number', 'String'],
myFieldWithBadType: {
type: 'Object',
default: function () {
return {}
},
},
myOtherFieldWithBadType: {
type: 'Number',
default: 1,
},
}
}
</script>
- 【推荐】Prop 的默认值必须匹配它的类型
<script>
export default {
props: {
/* ✓ GOOD */
// basic type check (`null` means accept any type)
propA: Number,
// multiple possible types
propB: [String, Number],
// a number with default value
propD: {
type: Number,
default: 100
},
// object/array defaults should be returned from a factory function
propE: {
type: Object,
default() {
return { message: 'hello' }
}
},
propF: {
type: Array,
default() {
return []
}
},
/* ✗ BAD */
propA: {
type: String,
default: {}
},
propB: {
type: String,
default: []
},
propC: {
type: Object,
default: []
},
propD: {
type: Array,
default: []
},
propE: {
type: Object,
default: { message: 'hello' }
}
}
}
</script>
- 【推荐】计算属性禁止包含异步方法
<script>
import { computed } from 'vue'
export default {
setup() {
/* ✓ GOOD */
const foo = computed(() => {
var bar = 0
try {
bar = bar / this.a
} catch (e) {
return 0
} finally {
return bar
}
})
/* ✗ BAD */
const pro = computed(() =>
Promise.all([new Promise((resolve, reject) => {})])
)
const foo1 = computed(async () => await someFunc())
const bar = computed(() => {
return fetch(url).then((response) => {})
})
const tim = computed(() => {
setTimeout(() => {}, 0)
})
const inter = computed(() => {
setInterval(() => {}, 0)
})
const anim = computed(() => {
requestAnimationFrame(() => {})
})
}
}
</script>
- 【推荐】禁止在对象字面量中出现重复的键
<script>
/* ✗ BAD */
export default {
props: {
foo: String
},
computed: {
foo: {
get() {}
}
},
data: {
foo: null
},
methods: {
foo() {}
}
}
</script>
- 【错误】禁止出现语法错误
<template>
<!-- ✗ BAD -->
{{ . }}
{{ foo bar }}
<div :class="*abc*" / @click="def(">
</span>
</div id="ghi">
</template>
# 2. ❌ 错误提示
- 【error】禁止使用
vue
关键字
<script>
/* ✗ BAD */
export default {
props: {
$el: String
},
computed: {
$on: {
get() {}
}
},
data: {
_foo: null
},
methods: {
$nextTick() {}
}
}
</script>
- 【error】禁止计算属性种对属性修改
<script>
/* ✓ GOOD */
export default {
computed: {
fullName() {
return `${this.firstName} ${this.lastName}`
},
reversedArray() {
return this.array.slice(0).reverse() // .slice makes a copy of the array, instead of mutating the orginal
}
}
}
</script>
<script>
/* ✗ BAD */
export default {
computed: {
fullName() {
this.firstName = 'lorem' // <- side effect
return `${this.firstName} ${this.lastName}`
},
reversedArray() {
return this.array.reverse() // <- side effect - orginal array is being mutated
}
}
}
</script>
<script>
import { computed } from 'vue'
/* ✓ GOOD */
export default {
setup() {
const foo = useFoo()
const fullName = computed(() => `${foo.firstName} ${foo.lastName}`)
const reversedArray = computed(() => {
return foo.array.slice(0).reverse() // .slice makes a copy of the array, instead of mutating the orginal
})
}
}
</script>
<script>
import { computed } from 'vue'
/* ✗ BAD */
export default {
setup() {
const foo = useFoo()
const fullName = computed(() => {
foo.firstName = 'lorem' // <- side effect
return `${foo.firstName} ${foo.lastName}`
})
const reversedArray = computed(() => {
return foo.array.reverse() // <- side effect - orginal array is being mutated
})
}
}
</script>
- 【推荐】 禁止在
<textarea>
中出现变量
<template>
<!-- ✓ GOOD -->
<textarea v-model="message" />
<!-- ✗ BAD -->
<textarea>{{ message }}</textarea>
</template>
- 【推荐】禁止注册没有使用的组件
<!-- ✓ GOOD -->
<template>
<div>
<h2>Lorem ipsum</h2>
<the-modal>
<component is="TheInput" />
<component :is="'TheDropdown'" />
<TheButton>CTA</TheButton>
</the-modal>
</div>
</template>
<script>
import TheButton from 'components/TheButton.vue'
import TheModal from 'components/TheModal.vue'
import TheInput from 'components/TheInput.vue'
import TheDropdown from 'components/TheDropdown.vue'
export default {
components: {
TheButton,
TheModal,
TheInput,
TheDropdown,
}
}
</script>
<!-- ✗ BAD -->
<template>
<div>
<h2>Lorem ipsum</h2>
<TheModal />
</div>
</template>
<script>
import TheButton from 'components/TheButton.vue'
import TheModal from 'components/TheModal.vue'
export default {
components: {
TheButton, // Unused component
'the-modal': TheModal // Unused component
}
}
</script>
- 【error】render 函数必须有返回值
<script>
export default {
/* ✓ GOOD */
render(h) {
return h('div', 'hello')
}
}
</script>
<script>
export default {
/* ✗ BAD */
render(h) {
if (foo) {
return h('div', 'hello')
}
}
}
</script>