VueJS - 示例
Vue 3 - 实用示例
Section titled “Vue 3 - 实用示例”本节提供了一些实用示例,演示了 Vue 3 的常用特性,如计算属性(computed properties)、数据绑定(data binding)、循环(loops)和组件通信(component communication)。
示例 1:动态货币转换器
Section titled “示例 1:动态货币转换器”此示例使用计算属性创建了一个实时货币转换器。它演示了 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)将结果格式化为小数点后两位。- 添加了基本样式以获得更好的展示效果。
此示例突出了计算属性如何简化响应式计算,使模板更整洁,逻辑更易于管理。
示例 2:简单的客户列表与组件
Section titled “示例 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 向上通信事件。