一、概述
看着别人写的组件,各种知识点不懂,难以理解其中的逻辑,实在没法工作,今天学习下组件传值,子组件既能接收父组件的值,也能返回更新后的值给父组件。
刚好最近看了Cursor,下载试用了下,真是太好用了,对于我这种前端小白来说,大大提升了学习的效率。
二、金额币种输入组件开发
Cursor怎么使用就不说了,大家可以自行搜索,下载后的IDE跟VS简直一模一样,按上Ctrl+L快捷键,快速和AI对话,轻轻松松实现了如下金额币种组件的实现。
<template>
<div class="input-money">
<el-select v-model="selectedCurrency" @change="handleCurrencyChange" class="currency-select">
<el-option v-for="currency in currencies" :key="currency.code" :label="`${currency.code} - ${currency.name}`"
:value="currency.code" />
</el-select>
<el-input v-model="displayValue" @input="handleInput" @blur="handleBlur" @focus="handleFocus" class="money-input" />
</div>
</template>
<script>
export default {
name: 'InputMoney',
props: {
// ... 现有的 props ...
value: {
type: [String, Number],
default: ''
},
currency: {
type: String,
default: 'USD' // 设置默认货币为美元
}
},
data() {
return {
displayValue: this.formatValue(this.value),
selectedCurrency: this.currency, // 使用 props 中的 currency 初始化
currencies: [
{ code: 'USD', name: '美元' },
{ code: 'EUR', name: '欧元' },
{ code: 'JPY', name: '日元' },
{ code: 'GBP', name: '英镑' },
{ code: 'CNY', name: '人民币' },
// 可以根据需要添加更多货币
]
}
},
methods: {
formatValue(value) {
if (!value) return '';
value = value.toString().replace(/[^\d.]/g, '');
const parts = value.split('.');
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ',');
return parts.join('.');
},
handleCurrencyChange() {
this.$emit('update:currency', this.selectedCurrency);
},
handleInput(value) {
const formattedValue = this.formatValue(value);
this.displayValue = formattedValue;
this.$emit('input', formattedValue.replace(/,/g, ''));
},
handleBlur() {
let value = this.displayValue.replace(/[^\d.]/g, '');
const parts = value.split('.');
if (parts.length > 1) {
parts[1] = parts[1].slice(0, 2); // 保留两位小数
}
const formattedValue = this.formatValue(parts.join('.'));
this.displayValue = formattedValue;
this.$emit('blur', formattedValue.replace(/,/g, ''));
},
handleFocus() {
// 获得焦点时的处理
this.$emit('focus');
}
},
watch: {
// ... 现有的 watch ...
value(newVal) {
this.displayValue = this.formatValue(newVal);
},
currency(newVal) {
this.selectedCurrency = newVal;
}
}
}
</script>
<style scoped>
.input-money {
display: flex;
align-items: center;
}
.currency-select {
width: 150px;
margin-right: 10px;
}
.money-input {
flex-grow: 1;
}
/* 移除 Element UI 默认样式 */
.input-money :deep(.el-input__inner),
.input-money :deep(.el-select .el-input__inner) {
border: 1px solid #ccc;
border-radius: 4px;
}
.input-money :deep(.el-input__inner:focus),
.input-money :deep(.el-select .el-input__inner:focus) {
border-color: #007bff;
box-shadow: 0 0 0 2px rgba(0, 123, 255, 0.25);
}
</style>
父组件引用也特别方便
<template lang="">
<div>
<input-money v-model="amount" :currency="currency" @update:currency="val => currency = val" />
<div>
{{currency}} - {{amount}}
</div>
</div>
</template>
<script>
import InputMoney from '@/views/input-money/input-money.vue' // 假设组件路径
export default {
components: {
InputMoney
},
data() {
return {
amount: 2112341234,
currency: "EUR"
}
}
}
</script>
<style lang="">
</style>
在父组件中就可以通过访问amount和currency变量,轻松初始化组件的值以及获取子组件修改后的值,实现双向绑定。
三、总结
本次复习的关键知识点为组件双向绑定,有如下两个知识点。
3.1 v-model双向绑定
默认就实现了双向绑定,无需特殊处理。子组件中需要定义value属性,与v-model对应。
props: {
// ... 现有的 props ...
value: {
type: [String, Number],
default: ''
},
currency: {
type: String,
default: 'USD' // 设置默认货币为美元
}
},
3.2 currency实现双向绑定
有两种方法,一种使用.sync语法糖实现,这种比较简单,实际使用这种也比较多。本次采用另外一种复杂的写法。 在父组件中定义:currency 以及@update:currency属性。
<input-money v-model="amount" :currency="currency" @update:currency="val => currency = val" />
在子组件中生命emit方法,通过币种下拉框的change事件,调用到emit方法。
<el-select v-model="selectedCurrency" @change="handleCurrencyChange" class="currency-select">
<el-option v-for="currency in currencies" :key="currency.code" :label="`${currency.code} - ${currency.name}`"
:value="currency.code" />
</el-select>
handleCurrencyChange() {
this.$emit('update:currency', this.selectedCurrency);
},
3.3 夸一夸Cursor
首次使用AI进行编程,体验真的很好,好的工具真的能提升工作效率,也会帮助我们更高效的学习。Cursor有点贵,先试用两周看看。