前端最基础的就是 HTML+CSS+Javascript
。掌握了这三门技术就算入门,但也仅仅是入门,现在前端开发的定义已经远远不止这些。前端小课堂(HTML/CSS/JS
),本着提升技术水平,打牢基础知识的中心思想,我们开课啦(每周四)。
前面我们基本学会了 Vue 的基本使用,那么今天我们来尝试实现一个库存管理系统,因为没有学服务端(放后面 express 里面做接口),我们暂时就不考虑服务端的实现了,直接存本地。
demo地址:https://www.lilnong.top/static/html/vue-erp-test.html。
demo地址,修改为 vue@2.6.11,支持新的插槽语法:https://www.lilnong.top/static/html/vue-erp-test-vue@2.6.11.html
需求
- 部门管理
- 人员管理,人员需要和部门关联。
库存管理,需要关联人员
- 可以补货
- 可以被领用,需要有领用人和数量
- 需要有操作记录
需求大概就是这样,下面说一下我们的实现方案:
- 因为没有服务端,所以数据存放在 localStroage 中。
基本上就是 table + dialog
- table 负责展示数据
- dialog 负责新增修改数据
- 初始化从 localStroage 读取数据,每次操作完保存 localStroage。
实现
table 列表
代码如下,我们来看一下里面都用到了那些东西
v-if 用来判断当前应该显示那个标签的内容
- 来个面试题 v-if 和 v-show 区别是什么?前端培训-中级阶段(35)- Vue 语法 之 Vue 自带的指令
v-bind,缩写为
:
size="mini"
用来传入了一个字符串,其实等价于:size="'mini'"
v-on,缩写为
@
@click="insertGroup"
用来实现单击时触发函数。
插槽,用于父组件给子组件传递 DOM
<el-button>新增部门</el-button>
,el-button
是一个组件,内部接收到了一个<slot name="default">
的内容。<template slot-scope="scope">
这里是一个作用域插槽,DOM 使用父级的,但是作用域使用子级的。当然slot-scope
被废弃了,应该用 2.6.0 增加的v-slot
<div v-if="navIdx == 1">
<div class="header">部门管理</div>
<div class="search-box">
<el-button
size="mini"
type="primary"
@click="insertGroup">新增部门</el-button>
</div>
<el-table
:data="list1"
style="width: 100%;padding-left: 10px;">
<el-table-column
prop="id"
label="编号"
width="180">
</el-table-column>
<el-table-column
prop="name"
label="名称"
width="auto">
</el-table-column>
<el-table-column
label="操作"
width="200">
<template slot-scope="scope">
<el-button
size="mini"
type="warning"
@click="updateGroup(scope.row)">修改部门信息</el-button>
</template>
</el-table-column>
</el-table>
</div>
dialog
代码如下,我们来看一下里面都用到了那些东西
- 首先我们把一个
dialog
的状态,全部集成到一个memberInfo
变量中。
这样其实是方便我们开发的,如果是多个 dialog 的场景,我们就可以很方便的分辨出作用域。 .sync
(vue 2.3.0+ 新增) 可以理解是对组件间数据双向绑定的一个扩展。之前只能用v-model
来做(:value
和@input
)。:visible.sync="memberInfo.dialogVisible"
子组件可以通过this.$emit('update:visible', newVisible)
来修改父组件的memberInfo.dialogVisible
的值。
插槽
- 具名插槽
<span slot="footer" class="dialog-footer">
,当然slot
被废弃了,应该用 2.6.0 增加的v-slot
- 具名插槽
<el-dialog
:title="memberInfo.id?'修改':'新增'"
:visible.sync="memberInfo.dialogVisible"
width="30%">
<div>
<div>
<el-input v-model="memberInfo.name" placeholder="人员名称"></el-input>
</div>
<div>
<el-select v-model="memberInfo.groupid" placeholder="请选择所属部门">
<el-option
v-for="item in list1"
:key="item.id"
:label="item.name"
:value="item.id">
</el-option>
</el-select>
</div>
</div>
<span slot="footer" class="dialog-footer">
<el-button size="mini" @click="memberInfoHandler(0)">取 消</el-button>
<el-button size="mini" type="primary" @click="memberInfoHandler(1)">确 定</el-button>
</span>
</el-dialog>
初始化数据&操作之后保存数据
初始化数据
created
时从 localStorage
读取数据。因为 Storage 只能保存字符串,所以还需要 JSON.parse
一下。
created(){
this.list1 = JSON.parse(localStorage.getItem('list1')) || []
this.list2 = JSON.parse(localStorage.getItem('list2')) || []
this.list3 = JSON.parse(localStorage.getItem('list3')) || []
this.list4 = JSON.parse(localStorage.getItem('list4')) || []
},
操作&保存数据
groupInfoHandler(type){
// 0取消 1确认
console.log('groupInfoHandler', arguments)
if(!type){
}else{
if(this.groupInfo.id){
var item = this.groupHash[this.groupInfo.id];
this.saveLog(2, `更新部门:${item.name} => ${this.groupInfo.name}`)
item.name = this.groupInfo.name
}else{
if(this.groupInfo.name.trim().length == ''){
return this.$message.error("请输入名称")
}
this.list1.push({
id: (this.list1.length+1),
name: this.groupInfo.name
})
this.saveLog(2, `新增部门:${this.groupInfo.name}`)
}
localStorage.setItem('list1',JSON.stringify(this.list1))
}
this.groupInfo.dialogVisible = false;
},
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。