一、为啥我们需要这些“语法糖”?
记得我刚学编程那会儿,写个函数都得像老妈子一样操心各种参数情况:
function greet(name, age, city) {
if (!name) name = '陌生人'
if (!age) age = '未知'
if (!city) city = '某个神秘地带'
return `你好,我是${name},今年${age}岁,来自${city}`
}
每多一个参数,就得多写一行判断,累不累啊?而且万一漏了一个,bug就找上门了!
ES6带来的默认参数和rest参数,简直就是程序员的“防秃利器”。它们不是花里胡哨的新功能,而是实实在在能让你少写代码、减少bug的实用特性。
在Vue开发中,这两个特性尤其有用。想想你写的methods方法,是不是经常需要处理各种参数情况?computed属性计算时,是不是经常要处理不定数量的数据?掌握了今天这两个技巧,你的Vue代码质量能直接提升一个档次!
二、默认参数:函数的“智能默认值”
2.1 基本用法:告别if判断的噩梦
默认参数的使用简单到哭:
// ES6的优雅写法
function greet(name = '陌生人', age = '未知', city = '某个神秘地带') {
return `你好,我是${name},今年${age}岁,来自${city}`
}
// 测试一下
console.log(greet()) // "你好,我是陌生人,今年未知岁,来自某个神秘地带"
console.log(greet('小明')) // "你好,我是小明,今年未知岁,来自某个神秘地带"
console.log(greet('小红', 18)) // "你好,我是小红,今年18岁,来自某个神秘地带"
看到没?一行判断都不用写!函数自己就知道该用什么默认值。
2.2 在Vue中的实战应用
场景1:方法参数的智能处理
<template>
<div>
<button @click="handleClick">默认点击</button>
<button @click="handleClick('自定义消息')">带参点击</button>
</div>
</template>
<script>
export default {
methods: {
// 默认参数让方法更健壮
handleClick(message = '默认点击消息', event = null) {
console.log(message)
if (event) {
console.log('点击位置:', event.clientX, event.clientY)
}
}
}
}
</script>
场景2:computed属性的优雅降级
<template>
<div>
<p>价格:{{ formattedPrice }}</p>
<p>折扣价:{{ formattedPrice(80, '¥') }}</p>
</div>
</template>
<script>
export default {
data() {
return {
product: {
price: 100,
name: 'Vue实战教程'
}
}
},
computed: {
// 带默认参数的computed
formattedPrice() {
return (price = this.product.price, currency = '$') => {
return `${currency}${price.toFixed(2)}`
}
}
}
}
</script>
2.3 高级玩法:表达式和函数调用
默认参数还可以是表达式甚至是函数调用:
function createUser(
name = '匿名用户',
id = Math.random().toString(36).substr(2, 9),
registerTime = new Date().toISOString()
) {
return { name, id, registerTime }
}
console.log(createUser()) // 自动生成完整用户信息
2.4 坑点提醒:这些情况要注意!
坑1:默认参数只在undefined时生效
function tricky(name = '默认名', age = 0) {
console.log(name, age)
}
tricky(undefined, null) // "默认名" null
tricky('', 0) // "" 0
坑2:参数默认值不是传默认值
let defaultValue = 1
function test(value = defaultValue) {
defaultValue = 2
console.log(value)
}
test() // 1,不是2!默认值在函数定义时确定
三、rest参数:不定参数的“收纳大师”
3.1 什么是rest参数?
rest参数用三个点...表示,能把多个参数收集到一个数组中:
// 以前要用arguments,很麻烦
function sum() {
let total = 0
for (let i = 0; i < arguments.length; i++) {
total += arguments[i]
}
return total
}
// 现在用rest参数,清爽!
function sum(...numbers) {
return numbers.reduce((total, num) => total + num, 0)
}
console.log(sum(1, 2, 3, 4, 5)) // 15
3.2 Vue中的rest参数实战
场景1:事件处理的多参数传递
<template>
<div>
<button @click="logEventInfo('click', $event, '额外信息')">点击事件</button>
<input @input="logEventInfo('input', $event, '用户输入', timestamp())">
</div>
</template>
<script>
export default {
methods: {
timestamp() {
return new Date().toISOString()
},
// rest参数收集所有事件相关信息
logEventInfo(eventType, ...eventDetails) {
console.log(`事件类型:${eventType}`)
console.log('事件详情:', eventDetails)
// 上报事件数据
this.$emit('event-log', {
type: eventType,
details: eventDetails
})
}
}
}
</script>
场景2:动态组件属性传递
<template>
<div>
<component
:is="currentComponent"
v-bind="componentProps"
@custom-event="handleCustomEvent"
/>
</div>
</template>
<script>
export default {
data() {
return {
currentComponent: 'UserCard',
baseProps: {
title: '用户信息',
theme: 'dark'
}
}
},
methods: {
// 合并多个属性源
prepareComponentProps(...propsSources) {
return Object.assign({}, ...propsSources)
},
handleCustomEvent(...eventArgs) {
console.log('收到自定义事件:', eventArgs)
}
},
computed: {
componentProps() {
const extraProps = {
user: this.currentUser,
size: 'large'
}
return this.prepareComponentProps(
this.baseProps,
extraProps,
this.dynamicProps
)
}
}
}
</script>
3.3 rest参数的限制和技巧
必须放在最后:
// ✅ 正确
function correct(a, b, ...rest) {}
// ❌ 错误
function wrong(...rest, a) {}
与解构结合使用:
function processUser({name, age, ...otherInfo}) {
console.log(`姓名:${name}`)
console.log('其他信息:', otherInfo)
}
processUser({
name: '小明',
age: 18,
hobby: '编程',
level: '高级'
})
四、默认参数 + rest参数:强强联合
当这两个特性结合使用时,威力更大:
<template>
<div>
<button @click="apiCall('获取用户')">简单调用</button>
<button @click="apiCall('更新用户', {name: '新名字'}, true)">完整调用</button>
</div>
</template>
<script>
export default {
methods: {
// 默认参数 + rest参数的完美结合
async apiCall(
action = '默认操作',
payload = {},
showLoading = true,
...otherOptions
) {
if (showLoading) {
this.showLoading = true
}
try {
const result = await this.$http.post('/api', {
action,
payload,
options: otherOptions
})
return result
} catch (error) {
console.error('API调用失败:', error, ...otherOptions)
throw error
} finally {
this.showLoading = false
}
}
}
}
</script>
五、真实项目案例:一个智能表单验证器
让我们用默认参数和rest参数构建一个实用的表单验证器:
<template>
<form @submit="handleSubmit">
<input v-model="formData.username" placeholder="用户名">
<input v-model="formData.email" placeholder="邮箱">
<input v-model="formData.age" type="number" placeholder="年龄">
<button type="submit">提交</button>
</form>
</template>
<script>
// 验证器工具函数
const validators = {
required(value = '', fieldName = '字段') {
if (!value.trim()) {
return `${fieldName}是必填的`
}
},
minLength(value = '', minLen = 1, fieldName = '字段') {
if (value.length < minLen) {
return `${fieldName}至少需要${minLen}个字符`
}
},
email(value = '') {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
if (value && !emailRegex.test(value)) {
return '请输入有效的邮箱地址'
}
},
between(value = 0, min = 0, max = 100, fieldName = '字段') {
const numValue = Number(value)
if (numValue < min || numValue > max) {
return `${fieldName}必须在${min}到${max}之间`
}
}
}
export default {
data() {
return {
formData: {
username: '',
email: '',
age: ''
}
}
},
methods: {
// 使用rest参数接收多个验证规则
validateField(value = '', ...validators) {
for (const validator of validators) {
const error = validator(value)
if (error) return error
}
return null
},
handleSubmit(event) {
event.preventDefault()
const errors = this.validateForm()
if (Object.keys(errors).length === 0) {
this.submitForm()
} else {
this.showErrors(errors)
}
},
validateForm() {
const errors = {}
// 对每个字段应用多个验证规则
errors.username = this.validateField(
this.formData.username,
value => validators.required(value, '用户名'),
value => validators.minLength(value, 3, '用户名')
)
errors.email = this.validateField(
this.formData.email,
value => validators.required(value, '邮箱'),
validators.email
)
errors.age = this.validateField(
this.formData.age,
value => validators.required(value, '年龄'),
value => validators.between(value, 1, 150, '年龄')
)
// 过滤掉没有错误的字段
return Object.fromEntries(
Object.entries(errors).filter(([_, error]) => error)
)
},
submitForm() {
console.log('表单提交:', this.formData)
// 实际提交逻辑...
},
showErrors(errors) {
alert(`请纠正以下错误:\n${Object.values(errors).join('\n')}`)
}
}
}
</script>
六、总结:为什么这俩特性这么香?
默认参数和rest参数可能看起来只是语法糖,但它们带来的好处是实实在在的:
- 代码更简洁:少写很多样板代码
- 可读性更强:函数签名直接表达了参数需求
- 更少bug:自动处理边界情况
- 更易维护:参数逻辑集中管理
在Vue项目中,这两个特性尤其有用。无论是处理用户交互、API调用还是数据转换,都能让你的代码更加优雅和健壮。
最佳实践建议:
- 公共方法尽量使用默认参数,提高复用性
- 事件处理函数多用rest参数,灵活接收各种事件数据
- 复杂的参数逻辑可以用默认参数+解构来简化
从现在开始,告别那些繁琐的参数判断吧!让你的代码因为ES6的这两个特性而变得更加简洁和强大。
879

被折叠的 条评论
为什么被折叠?



