代码优化
- 增加代码可读性,增加代码可维护性
- 封装公共方法的时候,要保证方法的通用性,尽量不要把业务的一些逻辑写在里面
- 熟悉array的api也是很有必要的
消除多级if嵌套
ts
import { ref } from 'vue'
const count = ref(0)
const isActive = ref(false)
function test() {
if (count.value < 5)
return
if (isActive.value)
return
add()
}
function add() {
count.value++
// 其他逻辑
}ts
function checkStatus() {
if (isLogin()) {
if (isVip()) {
if (isDoubleCheck()) {
done()
}
else {
throw new Error('不要重复点击')
}
}
else {
throw new Error('不是会员')
}
}
else {
throw new Error('未登录')
}
}
function checkStatus() {
if (!isLogin())
throw new Error('未登录')
if (!isVip())
throw new Error('不是会员')
if (!isDoubleCheck())
throw new Error('不要重复点击')
done()
}- 在函数体中,先把否定的条件提前,
return掉,后面只处理正面的逻辑。好处就是,写的时候思维不容易分散,写起来更清晰。 - 这就是
卫语句风格。
可选链简化判断和调用
ts
if (
store.getters
&& store.getters.userInfo
&& store.getters.userInfo.menus
) {
// 逻辑...//
}
if (store?.getters?.userInfo?.menus) {
// 逻辑...//
}
// 函数调用
props.onChange && props.onChange(e)
props?.onChange?.(e) 函数拆分
ts
function checkGameStatus() {
if (remaining === 0
|| (remaining === 1 && remainingPlayers === 1)
|| remainingPlayers === 0) {
quitGame()
}
}
function isGameOver() {
return (
remaining === 0
|| (remaining === 1 && remainingPlayers === 1)
|| remainingPlayers === 0
)
}
function checkGameStatus() {
if (isGameOver()) {
quitGame()
}
} - 代码逻辑复杂,可以按逻辑拆分成多个函数,方便维护。
函数传参优化
ts
function getMyInfo(name, age, gender, address, phone, email) {
// ...
}
// 行参封装成对象,对象函数内部解构
function getMyInfo(options) {
const { name, age, gender, address, phone, email } = options
// ...
}
getMyInfo(
{
name: '鸽鸽',
age: 18,
gender: '男',
address: '新世界',
phone: '123456789',
email: '123456789@email.com'
}
) include 代替 ||
ts
import { ref } from 'vue'
const type = ref(0)
function test() {
if (type === 1 || type === 2 || type === 3) {
console.log('ok')
}
if ([1, 2, 3].includes(type.value)) {
console.log('ok')
}
}- 可以用
includes消除||,后续添加新类型,只需要在数组中添加即可。
ts
import { ref } from 'vue'
type Type = 1 | 2
const type = ref<Type>()
const typeMap: Record<`${Type}`, () => void> = {
1: add,
2: mise,
}
function add() {
console.log('add')
}
function mise() {
console.log('mise')
}
function test(val: Type) {
const fn = typeMap[val]
fn?.()
}ts
// switch case
function statusMap(status: string) {
switch (status) {
case 'success':
return 'SuccessFully'
case 'fail':
return 'failed'
case 'danger':
return 'dangerous'
case 'info':
return 'information'
case 'text':
return 'texts'
default:
return status
}
}
// if else
function statusMap(status: string) {
if (status === 'success')
return 'SuccessFully'
else if (status === 'fail')
return 'failed'
else if (status === 'danger')
return 'dangerous'
else if (status === 'info')
return 'information'
else if (status === 'text')
return 'texts'
else return status
}
// 使用映射进行优化
const STATUS_MAP = {
success: 'SuccessFully',
fail: 'failed',
warn: 'warning',
danger: 'dangerous',
info: 'information',
text: 'texts'
}
function statusMap(status: string) {
return STATUS_MAP[status] ?? status
} switch语法在javascript中,看起来层级很深,完全可以用映射代替- 可以用对象来代替多级
if,后续添加新类型,只需要在对象中添加即可。 - 也可以用
new Map(),道理是一样的
熟练使用array api
ts
const list = [0, 1, 2, 3]
const isAdd = ref(false)
async function test() {
const userList = list.filter(Boolean) // [1, 2, 3]
const userObj = userList.map(item => ({
id: item,
name: `${item} - ${item}`,
}))
const params = isAdd.value ? userList : userObj
const requestFn = isAdd.value ? addUser : editUser
await requestFn(params)
}- 用array 的 api,每个变量单独写出来,不要揉到一个for循环里面,代码可读性更好
- 合理使用三目运算符,也能提高可读性
- 代码换行分块
- MDN Array
操作符
js
const obj = {}
const test = obj.a?.b // undefined
let val = null
val = val ?? 'default' // default
// 等同于
val = (val === undefined || val === null) ? 'default' : val
// 等同于
val ??= 'default'
// 同理还有`&&=`, `||=`, `??=`, `+=`, 等等
// `?.`
const obj2 = { a: { b: 1 } }
const val2 = obj2.a?.b // 1
// 函数调用
const fn = val || (() => 2)
const val3 = fn?.() // 2??操作符,可以判断一个值是否为null或者undefined,如果是,则返回后面的值。?.可选链操作符,用来读取一个数据中的某一个属性,如果属性不存在,则返回undefined。也可以用来调用函数, 比如fn?.(),函数不存在,则返回undefined。
promise
- 建议精读文档:
async/await
ts
async function test() {
const num = await test2()
console.log(num) // 6
}
async function test2() {
const num = await test3()
return num + 1
}
function test3() {
// `number` 是Promise的返回值,通过泛型传入
return new Promise<number>((resolve) => {
setTimeout(() => {
resolve(5)
}, 1000)
})
}- 异步操作,使用
async/await,可以避免回调地狱。 - 什么情况下只能用
new Promise,那就是需要拿到一个callback内部的数据的时候,这个callback调用不一定是同步的,比如setTimeout、onload等。
try/catch
ts
async function test() {
try {
const data = await fetchFn()
// 这里相当于promise.then里
// 这里可以手动throw一个错误,会执行下面catch 里面的代码
throw new Error('error')
}
catch (error) {
// 这里相当于promise.catch里
console.log(error)
}
finally {
// 这里相当于promise.finally里
console.log('finally')
}
}
async function fetchFn() {
return axios.get('/api')
}async/await和try/catch配套使用
try/catch 返回值探索
ts
function test() {
try {
return 1
}
catch (error) {
return 2
}
finally {
// eslint-disable-next-line no-unsafe-finally
return 3
}
return 4
}
test() // 3ts
function test() {
try {
return 1
}
catch (error) {
return 2
}
finally {
console.log('finally')
}
return 4
}
test() // 1try/catch在函数中return的返回值,建议精读文档