我们一起来学习vue3
这是我学习vue3做的一个demo,功能实现了增删查改。是演示效果,没有真正与数据库打交道。
做这个demo的过程中,我遇到了几个问题。还好一一解决了。所以我觉得必要分享出来。
给各位像我一样的新手。少浪费一些时间,多学习一些新知识。
我也是参考博客园一些人的文章,开始学的。
先看看效果。
整体效果,上面两个导航按钮,
中间搜索框,操作按钮。
下面是内容,有修改,有删除。
看看查询的
还可以吧
再看看修改的。
修改成功了
在来看看删除的。
只有一条了
再看看新增的
现在看看项目结构
现在开始看代码
product页面
<template> <div> <!-- 我是产品页面内容 <br/> {{name}} <button @click="changeData">改变数据</button> --> <div class="search-form"> <div class="search-form-key"><input v-model="keywords" placeholder="请输入型号名称" /></div> <div class="search-btn"><button @click="search">搜索</button> </div> <div class="search-btn"><button @click="add">添加</button> </div> </div> <div> <!-- {{productData}} --> <list :list="tempData.length>0?tempData:productData"></list> <!-- {{tempData}} --> <br> <!-- {{tempData.length}} --> <br> <!-- <list :list="tempData"></list> --> </div> </div> <teleport to="body"> <div v-if="modalOpen" class="modal"> <div class="model-header"> <button @click="modalOpen = false"> Close </button> </div> <div class="model-body"> <div class="form-item">型号编码<input v-model="productModel.productModelCode"></div> <div class="form-item">型号名称<input v-model="productModel.productModelName"></div> <div class="form-item">产品编码<input v-model="productModel.productCode"></div> <div class="form-item">产品名称<input v-model="productModel.productName"></div> </div> <div class="model-footer"> <button class="btn" @click="modalOpen = false">取消</button> <button class="btn" @click="saveData">确定</button> </div> </div> </teleport> </template> <script> import list from '../../components/List.vue' import dogData from '../../tempdata/productModel.js' import { useStore } from 'vuex' import { ref, reactive, toRefs, onMounted, onBeforeUpdate, watchEffect, toRef } from 'vue' export default { name: 'product', components: { list }, setup() { let keywords = ref('') const store = useStore(); //console.log('store', store.state.name); let name = ref('原始数据'); store.commit('changeName', '改变后的数据'); function changeData() { store.dispatch('changeVal') name.value = store.state.name; }; let productData = reactive(dogData.data.rows); let tempData = ref([]) //console.log((productData[1]),'reactive') function search() { setTimeout(() => { console.log(keywords.value, "keywords") let x = productData.filter((item) => { if (item.productModelName.includes(keywords.value.trim())) { return item } }); console.log(...toRefs(x), "ddddd") tempData.value = (x); }, 1000) } let modalOpen = ref(false); let productModel = ref({}) function add(){ modalOpen.value=true; } function saveData(){ productData.push(productModel.value); modalOpen.value=false; } return { name, keywords, productData, changeData, tempData, search, add, modalOpen, productModel, saveData } }, } </script> <style> .search-form { width: 100%; margin: 20px; padding: 10px; display: flex; justify-content: center; } .search-form-key, .search-btn { height: 30px; margin-right: 10px; } .search-form-key input { width: 200px; height: 30px; border-radius: 10px; } .search-btn button { height: 37px; width: 100px; border-radius: 10px; } </style>
自定义组件页面
<template> <div class="list"> <div class="table-header"> <div class="item-title">型号编码</div> <div class="item-title">型号名称</div> <div class="item-title">产品编码</div> <div class="item-title">产品名称</div> <div class="item-title">创建时间</div> <div class="item-title-btnlist">操作</div> </div> <div v-for="(item,index) in items"> <ListItem :listItem="item" :selected="changeChecked" :numIndex="index" :deleteItem="deleteRow"></ListItem> </div> </div> </template> <script> import { ref, reactive } from 'vue' import ListItem from './ListItem.vue' export default { name: "list", components: { ListItem }, props: { list: { type: Array, default: [] } }, watch: { list: function(newValue, oldValue) { // console.log(newValue,"newValuenewValue") this.items = newValue; // console.log(this.items,"thisitems") } }, setup(props) { const items = ref(props.list); //获取从父级传来的值 function changeChecked(num, newData) { let item = items.value[num] //获得选中的项 item.productModelCode = newData.productModelCode //修改选中状态 item.productModelName = newData.productModelName //修改选中状态 item.productCode = newData.productCode //修改选中状态 item.productName = newData.productName //修改选中状态 //console.log(item,"item") } function deleteRow(num) { //alert(num) //console.log(items.value,"items.value") items.value.splice(num, 1) } return { items, changeChecked, deleteRow } } } </script> <style> .table-header { display: flex; justify-content: space-between; margin: 10px 0; text-align: left; } .item-title { flex: 1; font-size: 18px; font-weight: bold; } .item-title-btnlist { flex: 1.5; font-size: 18px; font-weight: bold; display: flex; justify-content: flex-start } </style>
最小组件
<template> <div class="box-item"> <div class="item">{{listItem.productModelCode}}</div> <div class="item">{{listItem.productModelName}}</div> <div class="item">{{listItem.productCode}}</div> <div class="item">{{listItem.productName}}</div> <div class="item">{{listItem.createTime}}</div> <div class="item-btnlist"> <div class="btn"><button @click="updateData(listItem)">修改</button></div> <div class="btn"><button @click="deleteItemData(numIndex)">删除</button></div> </div> </div> <teleport to="body"> <div v-if="modalOpen" class="modal"> <div class="model-header"> <button @click="modalOpen = false"> Close </button> </div> <div class="model-body"> <div class="form-item">型号编码<input v-model="productModel.productModelCode"></div> <div class="form-item">型号名称<input v-model="productModel.productModelName"></div> <div class="form-item">产品编码<input v-model="productModel.productCode"></div> <div class="form-item">产品名称<input v-model="productModel.productName"></div> </div> <div class="model-footer"> <button class="btn" @click="modalOpen = false">取消</button> <button class="btn" @click="saveData">确定</button> </div> </div> </teleport> </template> <script> import { ref, reactive, toRefs, readonly } from 'vue' export default { name: "listitem", props: { listItem: { type: Object, default: {} }, numIndex: { type: Number //索引ID号属性 }, selected: { type: Function //方法作为属性传过去 }, deleteItem: { type: Function //方法作为属性传过去 } }, setup(props) { const listItem = (props.listItem) //接受父级传来的参数 let modalOpen = ref(false); let productModel = ref({}) function saveData() { props.selected(props.numIndex, productModel.value) modalOpen.value = false; } function deleteItemData(index) { props.deleteItem(index) } return { modalOpen, productModel, saveData, deleteItemData } }, methods:{ updateData(data) { let tempData={...data} this.modalOpen = true; this.productModel =tempData } } } </script> <style> .box-item { display: flex; justify-content: space-between; margin: 10px 0; text-align: left; } .item { text-align: left; flex: 1; /**设置每项宽度**/ } .item-btnlist { text-align: left; flex: 1.5; /**设置每项宽度**/ display: flex; justify-content: flex-start } .btn { margin: 0 10px; } .modal { background: red; z-index: 99999; width: 40%; height: 50%; position: absolute; left: 25%; top: 25%; border-radius: 10px; } .model-header { height: 30px; text-align: right; margin: 0 20px; padding: 10px; } .model-body { display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; } .form-item { flex: 20; margin: 10px 20px; } .form-item input { height: 30px; border-radius: 10px; } .model-footer { margin-top: 20px; display: flex; justify-content: space-around; align-items: center; text-align: center; height: 45px; } .btn { height: 40px; width: 120px; border-radius: 10px; } </style>
数据
let data={ "version": 0, "timestamp": 1640827793378, "sign": null, "total": 12, "size": 10, "current": 1, "pages": 2, "resultStateVo": { "code": 200, "msg": "操作成功" }, "rows": [{ "productModelCode": "xm_cp_bm_001", "productModelName": "小明产品型号001", "productCode": "xm_bm_001", "productName": "小明产品001", "description": null, "createTime": "2021-12-13 18:05:39", "creatorId": "104", "updateTime": null, "updateId": null }, { "productModelCode": "hao", "productModelName": "车海洋洗车中心", "productCode": "bm001", "productName": "编码001", "description": "test888", "createTime": "2021-12-09 16:23:48", "creatorId": "1", "updateTime": "2021-12-10 17:38:51", "updateId": "1" }, { "productModelCode": "chy_001", "productModelName": "车海洋001号", "productCode": "bm001", "productName": "编码001", "description": "666sss", "createTime": "2021-12-03 09:26:48", "creatorId": "1", "updateTime": "2021-12-10 17:37:21", "updateId": "1" }, { "productModelCode": "chy_five_wash", "productModelName": "五代+", "productCode": "hello", "productName": "测试111", "description": "一直想做一款后台管理系统,看了很多优秀的开源项目但是发现没有合适自己的。", "createTime": "2021-10-22 15:54:06", "creatorId": "1", "updateTime": "2021-12-02 16:43:50", "updateId": "1" }, { "productModelCode": "chy_one_tow_three", "productModelName": "一拖三", "productCode": "chy_product", "productName": "车海洋产品666", "description": "测试", "createTime": "2021-10-22 15:53:44", "creatorId": "1", "updateTime": "2021-12-07 14:41:58", "updateId": "1" }, { "productModelCode": "chy_water", "productModelName": "加水机", "productCode": "chy_product", "productName": "车海洋产品666", "description": "测试", "createTime": "2021-10-22 15:53:26", "creatorId": "1", "updateTime": null, "updateId": null }, { "productModelCode": "chy_digital", "productModelName": "数码洗车机", "productCode": "chy_product", "productName": "车海洋产品666", "description": "测试", "createTime": "2021-10-22 15:52:42", "creatorId": "1", "updateTime": null, "updateId": null }, { "productModelCode": "chy_automatic", "productModelName": "全自动", "productCode": "chy_product", "productName": "车海洋产品666", "description": "测试", "createTime": "2021-10-22 15:52:16", "creatorId": "1", "updateTime": null, "updateId": null }, { "productModelCode": "chy_android", "productModelName": "安卓机", "productCode": "chy_product", "productName": "车海洋产品666", "description": "测试", "createTime": "2021-10-22 15:50:06", "creatorId": "1", "updateTime": null, "updateId": null }, { "productModelCode": "S3", "productModelName": "S3电动自行车", "productCode": "S1-01", "productName": "小白系列电动自行车S101", "description": null, "createTime": "2021-10-22 14:26:49", "creatorId": "1", "updateTime": null, "updateId": null } ] } // 定义数据出口 export default {data}
明天再把一些关键点列一下,今天先发布了。
参考文章
https://www.cnblogs.com/web-learn/p/15722923.html
https://www.cnblogs.com/xiaohuasan/p/15720539.html