一、环境准备
编译器:Webstorm
安装:Node.js -> npm -> cnpm -> vue
1.安装Node.js
菜鸟教程:https://www.runoob.com/nodejs/nodejs-install-setup.html
2.安装npm
Windows系统cmd:
npm install npm -g
使用淘宝镜像:
npm install -g cnpm --registry=https://registry.npm.taobao.org
3.安装cnpm
Windows系统cmd:
npm install -g cnpm --registry=https://registry.npm.taobao.org
4.安装vue
cnpm install npm -g
5.如果在cmd中能正常查询版本,说明安装就成功了
二、搭建vue-cli脚手架
图形化方式创建vue项目了。
cmd:
vue ui
选择合适的文件夹后,点击在此创建新项目
给项目起名
这里是选择项目的预设,如果之前创建过项目,且保存了预设,可以选择之前的预设,没有的话就进行手动配置项目。这里我选择了Babel、Router、Linter/Formatter、使用配置文件。
到这里基本就OK了。vue项目就创建在对应的文件夹中了。三、逻辑功能
table的基本功能:增删改查。
增:点击添加按钮,生成一个表单弹窗,在弹窗中填写信息后提交,新提交的信息显示在视图中。
删:点击删除按钮,删除对应的信息。
改:点击编辑按钮,生成一个表单弹窗,更改信息提交后在视图中更新数据。
查:搜索关键字,在视图中返回包含关键字的数据。
待完善的功能:
增:没有对输入的数据进行限制(数据种类、格式、是否为空…)
删:…
改:修改功能大体上借用的增加的代码逻辑,每一次都要重新输入选择的数据的所有的值。
查:查询只是在逻辑和视图上完成了功能,但并不是理想中查询的逻辑。
基本界面:
四、代码实现
1.Element-UI安装
使用Element-UI可以绕开很多麻烦,把更多精力放在逻辑实现上。
Terminal:
npm i element-ui -S
main.js中引入element-ui:
import Element from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
Vue.use(Element)
2.主界面App.vue
<template>
<div>
<div>
<el-row :gutter="20">
<el-col :span="16">
<el-input placeholder="请输入内容" v-model="searchdata" @clear="handleClear" clearable></el-input>
</el-col>
<el-col :span="8">
<el-button @click="handleSearch">搜索</el-button>
<!-- 点击"搜索"按钮,触发handleSearch事件 -->
<el-button @click="addClick">添加</el-button>
<!-- 点击"添加"按钮,触发addClick事件 -->
</el-col>
</el-row>
</div>
<!-- el-table :data绑定要总体上显示的数据,但是这样绑,当需要改变视图时(比如搜索结果) -->
<!-- 就需要改变tableData的值了 -->
<el-table
:data="tableData"
style="width: 100%"
max-height="550"
v-if = isShow>
<el-table-column
fixed
prop="date"
label="日期"
width="150">
</el-table-column>
<el-table-column
prop="name"
label="姓名"
width="120">
</el-table-column>
<el-table-column
prop="province"
label="省份"
width="120">
</el-table-column>
<el-table-column
prop="city"
label="市区"
width="120">
</el-table-column>
<el-table-column
prop="address"
label="地址"
width="300">
</el-table-column>
<el-table-column
prop="zip"
label="邮编"
width="120">
</el-table-column>
<el-table-column
fixed="right"
label="操作"
width="220">
<template slot-scope="scope">
<el-button
@click.native.prevent="handleDelete(scope.$index, tableData)"
type="button"
size="small">
移除
<!-- 点击"移除"按钮,触发handleDelete事件,同时传参 -->
</el-button>
<el-button
@click.native.prevent="modifyClick(scope.$index, tableData)"
type="button"
size="small"
>
修改
<!-- 点击"修改"按钮,触发modifyClick事件,同时传参 -->
</el-button>
</template>
</el-table-column>
</el-table>
<add-item :dialog-table-visible="isActive" @cActive="changeActive" @cAdd="handleAdd" ref="myaddchild"></add-item>
<!-- @cActive控制添加表单的显示,每当点击取消时,不再显示弹窗-->
<!-- @cAdd控制提交form表单的信息,点击确定时,子组件向父组件传递表单数据,同时isActive=false,不再显示弹窗-->
<modify-item :dialog-table-visiblemodify="isActive_modify" :index_from_parent="index_modify"
@cActive_modify="changeActive_modify" @cmodify="handleRewrite"></modify-item>
</div>
</template>
<script>
import additem from './components/additem'
import modifyitem from './components/modifyitem'
// 引入子组件
export default {
components: {
'add-item': additem,
'modify-item': modifyitem
},
data () {
return {
message: '', //这个好像没啥用
isActive: false, //控制additem子组件的显示 弹窗
isActive_modify: false, //控制modifyitem子组件的显示 弹窗
index_modify: 0, //记录修改的数据的下标
isShow: true, //没用的数据(应该是)
searchdata: '', //要搜索的值 关键字 字符串
tableData: [{ //假数据
date: '2016-05-01',
name: '刘小鹿',
province: '上海',
city: '普陀区',
address: '上海市普陀区金沙江路 1551 弄',
zip: '23333'
}, {
date: '2016-05-02',
name: '王小虎',
province: '上海',
city: '普陀区',
address: '上海市普陀区金沙江路 1518 弄',
zip: '200333'
}
],
searchList: [], //用于存储搜索结果的数组
tempList: [] //tempList用于存储tableData,因为在添加了搜索功能后,
//由于最顶层显示的是tableData的数据,我只能通过修改tableData的值来表现搜索结果的视图
//所以用tempList来存储每次修改tableData前的数据,当取消搜索时,视图变为搜索前,或搜索并删除后的数据
//所以在实现删除逻辑时,要兼顾对tempList进行操作
}
},
methods: {
addClick () { // 每次点击“添加”按钮时,首先将isActive激活,显示表单;再调用子组件的childaddClicj方法,清空之前子组件中的form表单
this.isActive = true // 显示弹窗
this.$refs.myaddchild.childaddClick() // 调用子组件中的childaddClick方法,清空表单
},
modifyClick (index, rows) {
this.isActive_modify = true // 显示修改弹窗
this.index_modify = index
},
handleDelete (index, rows) {
for (var i = 0; i < this.tempList.length; i++) { // 因为后来要实现一个搜索功能,但搜索出来的结果也要实现删除功能,所以tempList和tableData要实现同步删除
if (this.tempList[i].name === rows[index].name) {
this.tempList.splice(i, 1)
}
}
rows.splice(index, 1)
},
handleRewrite (form) {
this.isActive_modify = false // 显示修改弹窗
// eslint-disable-next-line no-unused-vars
this.tableData[this.index_modify].date = form.date
this.tableData[this.index_modify].name = form.name
this.tableData[this.index_modify].province = form.province
this.tableData[this.index_modify].city = form.city
this.tableData[this.index_modify].address = form.address
this.tableData[this.index_modify].zip = form.zip
this.isActive_modify = false
this.tempList = this.tableData
},
handleAdd (form) {
const obj = {
date: form.date,
name: form.name,
province: form.province,
city: form.city,
address: form.address,
zip: form.zip
} // 这里用临时变量存储子组件提交来的form表单的数据,而不能直接push子组件的form,因为那样做会导致是将form添加到了tableDate中,每次push都只是
// 增加了同一个form(个数有多个),修改一次form,其他的数据也会改变
this.tableData.push(obj)
this.tempList = this.tableData
this.isActive = false // 关闭显示弹窗
},
handleSearch () {
this.searchList = [] // 每次搜索,要将上次的搜索结果searchList清空
for (var i = 0; i < this.tableData.length; i++) {
if (this.tableData[i].date.includes(this.searchdata) ||
this.tableData[i].name.includes(this.searchdata) ||
this.tableData[i].province.includes(this.searchdata) ||
this.tableData[i].city.includes(this.searchdata) ||
this.tableData[i].address.includes(this.searchdata) ||
this.tableData[i].zip.includes(this.searchdata)) {
this.searchList.push(this.tableData[i])
} //不会js的搜索函数,用c的思路写一下了
}
this.tempList = this.tableData // 用tempList暂存tableDate,即搜索前的数据
this.tableData = this.searchList //更新视图
},
handleClear () {
this.tableData = this.tempList
},
changeActive () { // 用于只改变isActive的值来取消显示弹窗
this.isActive = false
},
changeActive_modify () {
this.isActive_modify = false
}
}
}
</script>
<style>
</style>
以上为App.vue的内容~
3.子组件
(1)增加功能组件additem:
additem子组件要实现的逻辑是,当点击"添加"按钮时,在当前页面生成弹窗,在弹窗内填写表单数据,将新的数据传到父组件中(emit)。那么就有几个主要需要实现功能:
①点击,显示弹窗:当点击添加时,触发事件,改变控制additem子组件的显示的值(变成true)。
②子组件数据传到父组件
使用$emit,父组件监听事件,子组件提交数据触发对应事件。
<template>
<div>
<el-dialog title="添加信息" :visible.sync="dialogTableVisible" :before-close="handleClose" width="50%">
<!-- dialogTableVisible控制additem子组件的显示 -->
<el-form ref="form" :model="form" label-width="80px">
<el-form-item label="日期">
<el-input v-model="form.date"></el-input>
</el-form-item>
<el-form-item label="姓名">
<el-input v-model="form.name" ></el-input>
</el-form-item>
<el-form-item label="省份">
<el-input v-model="form.province"></el-input>
</el-form-item>
<el-form-item label="城市">
<el-input v-model="form.city"></el-input>
</el-form-item>
<el-form-item label="地址">
<el-input v-model="form.address"></el-input>
</el-form-item>
<el-form-item label="邮编">
<el-input v-model="form.zip"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="handleCancel">取消</el-button>
<el-button @click="handleSubmit">确定</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
export default {
props: ['dialogTableVisible'],
data () {
return {
message: '来自子组件的消息', //想起来了,这个message是我用来测试父子传参时加的
form: {
date: '',
name: '',
province: '',
city: '',
address: '',
zip: ''
}
}
},
methods: {
handleCancel () {
this.$emit('cActive') // $emit应是用来子组件向父组件传参的,但是,这里我只是想改变父组件中isActive为false,
// 对应事件cActive
},
handleSubmit () {
this.$emit('cAdd', this.form)
// 对应事件cAdd
// &emit向父组件提交form表单
},
// 这里要将form的所有值清空,因为additem子组件的form仍保存着上次添加操作输入的值,
//但每次添加时,不能再让用户删除上次的值,对吧
childaddClick () {
this.form.date = ''
this.form.name = ''
this.form.province = ''
this.form.city = ''
this.form.address = ''
this.form.zip = ''
},
handleClose (done) {
//这里的confirm then catch说实话现阶段我还不是很明白,只是加了一个挺好玩的提示功能,糊上来的
this.$confirm('确认关闭?')
.then(_ => {
this.$emit('cActive') // 如果确认,就取消弹窗,
done()
})
.catch(_ => {})
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
</style>
(2)修改功能组件modifyitem:
我其实觉得如果就是简易的添加和修改,这两个功能的逻辑是差不多的。但修改是将点击修改的位置的数据更改,不是新push一段数据。所以在父组件额外需要注意的是,点击修改时要将对应的index传入对应的事件中。
<template>
<div>
<el-dialog title="添加信息" :visible.sync="dialogTableVisible" :before-close="handleClose" width="50%">
<el-form ref="form" :model="form" label-width="80px">
<el-form-item label="日期">
<el-input v-model="form.date"></el-input>
</el-form-item>
<el-form-item label="姓名">
<el-input v-model="form.name" ></el-input>
</el-form-item>
<el-form-item label="省份">
<el-input v-model="form.province"></el-input>
</el-form-item>
<el-form-item label="城市">
<el-input v-model="form.city"></el-input>
</el-form-item>
<el-form-item label="地址">
<el-input v-model="form.address"></el-input>
</el-form-item>
<el-form-item label="邮编">
<el-input v-model="form.zip"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="handleCancel">取消</el-button>
<el-button @click="handleSubmit">确定</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
export default {
props: ['dialogTableVisible'],
data () {
return {
message: '来自子组件的消息',
form: {
date: '',
name: '',
province: '',
city: '',
address: '',
zip: ''
}
}
},
methods: {
handleCancel () {
this.$emit('cActive') // $emit应是用来子组件向父组件传参的,但是,这里我只是想改变父组件中isActive为false,
// 对应事件cActive
},
handleSubmit () {
this.$emit('cAdd', this.form)
// 对应事件cAdd
// &emit向父组件提交form表单
},
childaddClick () {
this.form.date = ''
this.form.name = ''
this.form.province = ''
this.form.city = ''
this.form.address = ''
this.form.zip = ''
},
handleClose (done) {
this.$confirm('确认关闭?')
.then(_ => {
this.$emit('cActive') // 如果确认,就取消弹窗,
done()
})
.catch(_ => {})
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
</style>
五、总结
这个只能实现最基本的增删改查功能,并且也只是在前端完成的数据操作。而在实际应用中要和后端的接口连接起来搭建,以此完成对数据库中的数据的增删改查操作。下一步就是学习axios和用flask写api了。
还有最重要一点之一,变量名!我是按增-删-改-查的顺序做的,所以刚开始没有兼顾到后面变量名,有的变量是不同组件中,控制对应相同的功能(比如添加和修改子组件中的弹窗的显示控制:visible.sync=" ",当想最后再想统一给变量起名时,就怕改一个bug一堆,还是怠情阻止了我8-)。
github:https://github.com/anRank/table_adms