前言
在现代的前端开发中,Vue.js 是一个非常流行的 JavaScript 框架,用于构建用户界面。Vue 提供了一种简洁的方式来构建交互式和动态的网页应用。在这个例子中,我们将探讨如何使用 Vue 3 和 Composition API 来创建一个简单的搜索功能,允许用户根据不同的条件过滤和显示数据。
用法
在这个例子中,我们有一个包含多个订单信息的数组 `data`。每个订单都有一个 ID、昵称、手机号、标题等属性。我们提供了四个输入框,允许用户输入 ID、昵称、手机号和标题的搜索条件。根据用户的输入,订单列表将实时更新以显示匹配的结果。
1. 数据绑定和事件处理
使用 `v-model` 指令,我们可以创建双向数据绑定,将输入框的值绑定到 Vue 实例的数据属性上。当输入框的值发生变化时,绑定的数据属性也会相应地更新。
<input id="searchId" v-model="searchId" placeholder="ID" /> <input id="searchNickname" v-model="searchNickname" placeholder="Nickname" /> <input id="searchTel" v-model="searchTel" placeholder="Tel" /> <input id="searchTitle" v-model="searchTitle" placeholder="Title" />
在这里,`searchId`、`searchNickname`、`searchTel` 和 `searchTitle` 都是响应式的数据属性,它们的初始值都设置为空字符串。
2. 列表渲染和条件过滤
使用 `v-for` 指令,我们可以遍历 `data` 数组,并为数组中的每个元素渲染一个列表项。
<ul> <li v-for="item in filteredData" :key="item.id"> ID: {{ item.id }}, 名称: {{ item.nickname }}, 手机号: {{ item.tel }}, Title: {{ item.title }} </li> </ul>
在这里,`filteredData` 是一个计算属性,它基于 `data` 和搜索条件来返回过滤后的订单列表。使用 `Array.prototype.filter` 方法,我们可以根据用户输入的搜索条件来过滤订单列表。
const filteredData = computed(() => { return data.value.filter(item => { return ( (!searchId.value || item.id.toString().includes(searchId.value)) && (!searchNickname.value || item.nickname.toLowerCase().includes(searchNickname.value.toLowerCase())) && (!searchTel.value || item.tel.includes(searchTel.value)) && (!searchTitle.value || item.title.toLowerCase().includes(searchTitle.value.toLowerCase())) ); }); });
在这个计算属性中,我们检查每个订单的 ID、昵称、手机号和标题是否包含用户输入的搜索条件。如果用户没有输入搜索条件,或者订单的相应属性包含搜索条件,则该订单会被包含在过滤后的结果中。
解析
这个例子展示了 Vue 3 和 Composition API 的强大功能,提供了一种简洁和声明式的方式来构建动态和响应式的用户界面。
1. **响应式数据**: 使用 `ref` 函数,我们可以创建响应式的数据属性。当这些属性的值发生变化时,Vue 会自动更新 DOM,确保用户界面与数据保持同步。
2. **计算属性**: 使用 `computed` 函数,我们可以创建依赖于响应式数据的计算属性。计算属性的值会根据其依赖的数据自动更新,并且它们是惰性求值的,只有在需要时才会重新计算。
3. **双向数据绑定**: 使用 `v-model` 指令,我们可以实现输入框和 Vue 实例数据之间的双向数据绑定。这使得实现表单和用户输入的处理变得非常简单和直观。
4. **条件渲染和列表渲染**: 使用 `v-if`、`v-else-if`、`v-else` 和 `v-for` 指令,我们可以根据数据的状态在 DOM 中渲染不同的内容或列表。
5. **事件处理**: Vue 也提供了一种简洁的方式来处理用户输入和其他 DOM 事件。
通过这个例子,我们可以看到 Vue 3 和 Composition API 提供了一种非常高效和灵活的方式来构建复杂的用户界面,使得开发者能够以声明式的方式描述用户界面应该如何根据数据的变化来更新,而不是手动操作 DOM。这不仅使得代码更加简洁和易于理解,也提高了开发效率和应用性能。
完整代码
<template> <div> <div> <label for="searchId">ID:</label> <input id="searchId" v-model="searchId" placeholder="ID" /> </div> <br> <div> <label for="searchNickname">名称:</label> <input id="searchNickname" v-model="searchNickname" placeholder="Nickname" /> </div> <br> <div> <label for="searchTel">手机号:</label> <input id="searchTel" v-model="searchTel" placeholder="Tel" /> </div> <br> <div> <label for="searchTitle">TiTle:</label> <input id="searchTitle" v-model="searchTitle" placeholder="Title" /> </div> <br> <ul> <li v-for="item in filteredData" :key="item.id"> ID: {{ item.id }}, 名称: {{ item.nickname }}, 手机号: {{ item.tel }}, Title: {{ item.title }} </li> </ul> </div> </template> <script setup> import { ref, computed } from 'vue'; const data = ref([ { "id": 89, "shopid": 13, "userid": 21, "total": "99.00", "num": "1", "ord_num": "2023092410299525", "create_time": "2023-09-24 19:52:47", "status": 1, "nickname": "昵称", "tel": "12372272611", "title": "11苹果11双卡全面屏苹果手机", "price": "99.00", "info": "推荐购买" }, { "id": 88, "shopid": 13, "userid": 21, "total": "99.00", "num": "1", "ord_num": "2023092499519710", "create_time": "2023-09-24 08:48:44", "status": 1, "nickname": "昵称", "tel": "12372272611", "title": "11苹果11双卡全面屏苹果手机", "price": "99.00", "info": "推荐购买" }, { "id": 87, "shopid": 13, "userid": 21, "total": "99.00", "num": "1", "ord_num": "2023092497515653", "create_time": "2023-09-24 08:44:42", "status": 1, "nickname": "昵称", "tel": "12372272611", "title": "11苹果11双卡全面屏苹果手机", "price": "99.00", "info": "推荐购买" }, { "id": 86, "shopid": 13, "userid": 21, "total": "99.00", "num": "1", "ord_num": "2023092457100101", "create_time": "2023-09-24 08:44:41", "status": 1, "nickname": "昵称", "tel": "12372272611", "title": "11苹果11双卡全面屏苹果手机", "price": "99.00", "info": "推荐购买" }, { "id": 85, "shopid": 13, "userid": 21, "total": "99.00", "num": "1", "ord_num": "2023092448101101", "create_time": "2023-09-24 08:40:32", "status": 1, "nickname": "昵称", "tel": "12372272611", "title": "11苹果11双卡全面屏苹果手机", "price": "99.00", "info": "推荐购买" }, { "id": 84, "shopid": 9, "userid": 21, "total": "1", "num": "1", "ord_num": "2023092456545351", "create_time": "2023-09-24 07:53:12", "status": 1, "nickname": "昵称", "tel": "12372272611", "title": "魅鹰视力机德国技术a波光谱眼部按摩仪护眼仪儿童近散眼轴学生", "price": "1", "info": "儿童养眼" }, { "id": 83, "shopid": 9, "userid": 21, "total": "1", "num": "1", "ord_num": "2023092448101545", "create_time": "2023-09-24 07:44:16", "status": 1, "nickname": "昵称", "tel": "12372272611", "title": "魅鹰视力机德国技术a波光谱眼部按摩仪护眼仪儿童近散眼轴学生", "price": "1", "info": "儿童养眼" }, { "id": 82, "shopid": 3, "userid": 2, "total": "1", "num": "1", "ord_num": "2023091456535451", "create_time": "2023-09-14 14:46:16", "status": 1, "nickname": "冰海恋雨", "tel": "15225928729", "title": "顺丰包邮10斤混合组合混搭新鲜水果进口车厘子礼盒装中秋送礼高端", "price": "999", "info": "非常热爆" }, { "id": 81, "shopid": 1, "userid": 4, "total": "10", "num": "1", "ord_num": "2023091310156515", "create_time": "2023-09-13 07:46:06", "status": 1, "nickname": "李四", "tel": "15225928720", "title": "Jordan官方耐克乔丹AJ38男子实战篮球鞋秋新款透气缓震抗扭FN7482", "price": "10", "info": "AJ" }, { "id": 80, "shopid": 1, "userid": 9, "total": "10", "num": "1", "ord_num": "2023091251571024", "create_time": "2023-09-12 23:36:03", "status": 1, "nickname": "志昂张", "tel": "17839859856", "title": "Jordan官方耐克乔丹AJ38男子实战篮球鞋秋新款透气缓震抗扭FN7482", "price": "10", "info": "AJ" }, { "id": 79, "shopid": 1, "userid": 4, "total": "10", "num": "1", "ord_num": "2023091210297569", "create_time": "2023-09-12 18:55:59", "status": 1, "nickname": "李四", "tel": "15225928789", "title": "Jordan官方耐克乔丹AJ38男子实战篮球鞋秋新款透气缓震抗扭FN7482", "price": "10", "info": "AJ" }, { "id": 78, "shopid": 1, "userid": 4, "total": "10", "num": "1", "ord_num": "2023091249101575", "create_time": "2023-09-12 18:38:09", "status": 1, "nickname": "李四", "tel": "15223245720", "title": "Jordan官方耐克乔丹AJ38男子实战篮球鞋秋新款透气缓震抗扭FN7482", "price": "10", "info": "AJ" }, { "id": 77, "shopid": 1, "userid": 4, "total": "10", "num": "1", "ord_num": "2023091253575549", "create_time": "2023-09-12 18:37:41", "status": 1, "nickname": "李四", "tel": "15225943230", "title": "Jordan官方耐克乔丹AJ38男子实战篮球鞋秋新款透气缓震抗扭FN7482", "price": "10", "info": "AJ" }, { "id": 76, "shopid": 1, "userid": 4, "total": "10", "num": "1", "ord_num": "2023091297971021", "create_time": "2023-09-12 18:16:58", "status": 1, "nickname": "李四", "tel": "152123420", "title": "Jordan官方耐克乔丹AJ38男子实战篮球鞋秋新款透气缓震抗扭FN7482", "price": "10", "info": "AJ" }, { "id": 75, "shopid": 10, "userid": 4, "total": "13.8", "num": "1", "ord_num": "2023091210255505", "create_time": "2023-09-12 18:14:55", "status": 1, "nickname": "李四", "tel": "1524567720", "title": "紫薯新鲜9斤农家蜜薯板栗香红沙地薯地瓜糖心蔬菜山芋小番薯包邮", "price": "13.8", "info": "紫薯新鲜9斤农家蜜薯板栗香红沙地薯地瓜糖心蔬菜山芋小番薯包邮" }, { "id": 74, "shopid": 4, "userid": 4, "total": "1", "num": "1", "ord_num": "2023091210048559", "create_time": "2023-09-12 18:14:37", "status": 1, "nickname": "李四", "tel": "15267898720", "title": "正版 华晨宇同款李宁防泼水外套 | 2023秋季新款开衫防风运动服男女款", "price": "1", "info": "好穿不贵" }, { "id": 73, "shopid": 1, "userid": 4, "total": "10", "num": "1", "ord_num": "2023091250501011", "create_time": "2023-09-12 17:44:18", "status": 1, "nickname": "李四", "tel": "15225456720", "title": "Jordan官方耐克乔丹AJ38男子实战篮球鞋秋新款透气缓震抗扭FN7482", "price": "10", "info": "AJ" }, { "id": 72, "shopid": 1, "userid": 4, "total": "10", "num": "1", "ord_num": "2023091210048491", "create_time": "2023-09-12 17:42:53", "status": 1, "nickname": "李四", "tel": "15225928720", "title": "Jordan官方耐克乔丹AJ38男子实战篮球鞋秋新款透气缓震抗扭FN7482", "price": "10", "info": "AJ" } ]); const searchId = ref(''); const searchNickname = ref(''); const searchTel = ref(''); const searchTitle = ref(''); const filteredData = computed(() => { return data.value.filter(item => { return ( (!searchId.value || item.id.toString().includes(searchId.value)) && (!searchNickname.value || item.nickname.toLowerCase().includes(searchNickname.value.toLowerCase())) && (!searchTel.value || item.tel.includes(searchTel.value)) && (!searchTitle.value || item.title.toLowerCase().includes(searchTitle.value.toLowerCase())) ); }); }); </script>