Skip to content

VueJS - 示例

本节提供了一些实用示例,演示了 Vue 3 的常用特性,如计算属性(computed properties)、数据绑定(data binding)、循环(loops)和组件通信(component communication)。

此示例使用计算属性创建了一个实时货币转换器。它演示了 v-model、v-for 以及基于用户输入的动态计算。

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue 3 Currency Converter</title>
<script src="https://unpkg.com/vue@3"></script>
<style>
#currency-converter {
padding: 20px;
margin: 20px;
background-color: #f0f0f0;
border-radius: 8px;
}
label, select, input, span {
font-size: 1.1em;
margin-right: 10px;
margin-bottom: 10px;
display: inline-block; /* Better layout */
/* 更好的布局 */
}
select {
min-width: 150px;
}
.result {
margin-top: 20px;
font-weight: bold;
font-size: 1.2em;
}
</style>
</head>
<body>
<div id="currency-converter">
<h1>Currency Converter</h1>
<div>
<label for="amount">Amount:</label>
<input id="amount" type="number" v-model.number="amount" placeholder="Enter amount" />
<!-- 输入金额 -->
</div>
<div>
<label for="from">From:</label>
<!-- 从: -->
<select id="from" v-model="convertFrom">
<option v-for="currency in currencies" :key="currency.code" :value="currency.code">
{{ currency.name }} ({{ currency.code }})
</option>
</select>
</div>
<div>
<label for="to">To:</label>
<!-- 到: -->
<select id="to" v-model="convertTo">
<option v-for="currency in currencies" :key="currency.code" :value="currency.code">
{{ currency.name }} ({{ currency.code }})
</option>
</select>
</div>
<div class="result" v-if="amount > 0">
<span>{{ amount }} {{ convertFrom }} = {{ convertedAmount }} {{ convertTo }}</span>
</div>
<div class="result" v-else>
<span>Enter an amount to see the conversion.</span>
<!-- 输入金额以查看转换结果。 -->
</div>
</div>
<script>
const { createApp, ref, computed } = Vue;
const app = createApp({
setup() {
const amount = ref(1); // Default amount
// 默认金额
const convertFrom = ref('USD');
const convertTo = ref('EUR');
// In a real app, fetch these rates from an API
// 在实际应用中,应从 API 获取这些汇率
const rates = ref({
'USD': 1,
'EUR': 0.92,
'INR': 83.3,
'GBP': 0.79
});
const currencies = ref([
{ code: 'USD', name: 'US Dollar' },
{ code: 'EUR', name: 'Euro' },
{ code: 'INR', name: 'Indian Rupee' },
{ code: 'GBP', name: 'British Pound' }
]);
const convertedAmount = computed(() => {
if (!amount.value || !rates.value[convertFrom.value] || !rates.value[convertTo.value]) {
return 0;
}
// Convert 'from' amount to base currency (USD in this case)
// 将“从”金额转换为基础货币(本例中为美元)
const amountInBase = amount.value / rates.value[convertFrom.value];
// Convert base amount to 'to' currency
// 将基础金额转换为“到”货币
const finalAmount = amountInBase * rates.value[convertTo.value];
// Format to 2 decimal places
// 格式化为小数点后两位
return finalAmount.toFixed(2);
});
return {
amount,
convertFrom,
convertTo,
currencies,
convertedAmount
};
}
});
app.mount('#currency-converter');
</script>
</body>
</html>
  • 使用组合式 API(setup、ref、computed)。
  • amount、convertFrom、convertTo 是绑定到表单元素上的响应式 refs,使用了 v-model。
  • currencies 是一个数组,与 v-for 一起用于填充选择下拉菜单。
  • rates 存放了转换汇率(相对于基础货币,此处为美元)。重要提示: 在实际应用中,这些汇率应从可靠的 API 获取。
  • convertedAmount 是一个 computed 属性。每当 amount、convertFrom 或 convertTo 改变时,它都会自动重新计算。
  • 转换逻辑首先将输入的金额转换为基础货币(美元),然后将该基础金额转换为目标货币。
  • .toFixed(2) 将结果格式化为小数点后两位。
  • 添加了基本样式以获得更好的展示效果。

此示例突出了计算属性如何简化响应式计算,使模板更整洁,逻辑更易于管理。

此示例演示了如何创建客户列表、通过表单添加新客户以及删除客户。它介绍了基本的组件用法、props 和用于子组件到父组件通信的事件发射($emit)。

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue 3 Customer List</title>
<script src="https://unpkg.com/vue@3"></script>
<style>
#customer-app { padding: 20px; margin: 20px; background-color: #f9f9f9; border-radius: 8px; }
.customer-form input, .customer-form button { margin-right: 10px; margin-bottom: 15px; padding: 8px; font-size: 1em; }
.customer-list { margin-top: 20px; }
.customer-item { display: flex; justify-content: space-between; align-items: center; padding: 10px; border: 1px solid #eee; margin-bottom: 5px; background-color: white; }
.customer-item span { flex-grow: 1; margin-right: 10px; }
.customer-item button { padding: 5px 10px; background-color: #ff4d4d; color: white; border: none; cursor: pointer; border-radius: 4px; }
.customer-item:nth-child(even) { background-color: #fdfdfd; }
</style>
</head>
<body>
<div id="customer-app">
<h1>Customer Management</h1>
<!-- Form to add new customers -->
<!-- 添加新客户的表单 -->
<div class="customer-form">
<input type="text" v-model="newCustomer.firstName" placeholder="First Name" />
<!-- 名 -->
<input type="text" v-model="newCustomer.lastName" placeholder="Last Name" />
<!-- 姓 -->
<input type="text" v-model="newCustomer.address" placeholder="Address" />
<!-- 地址 -->
<button @click="addCustomer">Add Customer</button>
<!-- 添加客户 -->
</div>
<!-- List of customers -->
<!-- 客户列表 -->
<div class="customer-list" v-if="customers.length > 0">
<h2>Customer List</h2>
<!-- 客户列表 -->
<!-- Customer Item Component -->
<!-- 客户项组件 -->
<customer-item
v-for="(customer, index) in customers"
:key="customer.id"
:customer-data="customer"
@delete-customer="deleteCustomer(index)">
</customer-item>
</div>
<p v-else>No customers added yet.</p>
<!-- 暂无客户添加。 -->
</div>
<script>
const { createApp, ref, reactive } = Vue;
const app = createApp({
setup() {
const customers = ref([
{ id: 1, firstName: 'John', lastName: 'Doe', address: '123 Main St' },
{ id: 2, firstName: 'Jane', lastName: 'Smith', address: '456 Oak Ave' }
]);
const newCustomer = reactive({
firstName: '',
lastName: '',
address: ''
});
let nextId = 3; // Simple ID generation
// 简单的 ID 生成
function addCustomer() {
if (newCustomer.firstName && newCustomer.lastName) { // Basic validation
// 基本验证
customers.value.push({
id: nextId++, // Assign and increment ID
// 赋值并递增 ID
firstName: newCustomer.firstName,
lastName: newCustomer.lastName,
address: newCustomer.address
});
// Clear the form
// 清空表单
newCustomer.firstName = '';
newCustomer.lastName = '';
newCustomer.address = '';
}
}
function deleteCustomer(index) {
customers.value.splice(index, 1);
}
return {
customers,
newCustomer,
addCustomer,
deleteCustomer
};
}
});
// Define the Customer Item Child Component
// 定义客户项子组件
app.component('customer-item', {
props: {
customerData: { // Use camelCase for JS prop name
// 在 JS 中使用 camelCase 作为 prop 名称
type: Object,
required: true
}
},
emits: ['delete-customer'], // Declare emitted events
// 声明发射的事件
// Use kebab-case for HTML attribute: :customer-data
// 在 HTML 属性中使用 kebab-case::customer-data
template: `
<div class="customer-item">
<span>{{ customerData.firstName }} {{ customerData.lastName }}</span>
<span>{{ customerData.address }}</span>
<button @click="$emit('delete-customer')">Delete</button>
<!-- 删除 -->
</div>
`
// Note: The alternating background color is handled by CSS :nth-child selector
// 注意:交替的背景色由 CSS 的 :nth-child 选择器处理
});
app.mount('#customer-app');
</script>
</body>
</html>
  • 主应用使用 ref 处理 customers 数组,使用 reactive 处理 newCustomer 表单对象。
  • addCustomer 函数将一个新的客户对象(带有唯一的 ID)推送到 customers 数组中并清空表单。
  • v-for 指令迭代 customers 数组以显示每个客户。
  • 使用 app.component 定义了一个名为 customer-item 的子组件。
  • Props (customerData):父应用使用 :customer-data="customer" 将客户数据传递给每个 customer-item 组件。在组件定义内部,使用 props: { customerData: {...} } 声明该 prop。
  • 事件发射($emit):当 customer-item 内部的“删除”按钮被点击时,它使用 $emit('delete-customer') 发射一个名为 delete-customer 的自定义事件。
  • 监听事件(@delete-customer):父应用在组件标签上使用 @delete-customer="deleteCustomer(index)" 监听此事件。当事件接收到时,将调用父应用的 deleteCustomer 方法,并传入要删除的客户的索引。
  • :key 属性对于 Vue 的列表渲染性能和状态管理至关重要,使用 customer.id 提供了稳定的键。
  • 子组件中的 emits: ['delete-customer'] 选项明确声明了它可以发射的事件,这在 Vue 3 中是一个良好的实践。

此示例展示了 Vue 的基础概念:管理列表、处理用户输入、创建组件、使用 props 向下传递数据以及使用 $emit 向上通信事件。