一、环境准备
编译器: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中能正常查询版本,说明安装就成功了

生成Vue3的element UI前端增删改查规范模板_搜索


二、搭建vue-cli脚手架

图形化方式创建vue项目了。

cmd:

vue ui

生成Vue3的element UI前端增删改查规范模板_搜索_02


选择合适的文件夹后,点击在此创建新项目

生成Vue3的element UI前端增删改查规范模板_vue_03


给项目起名

生成Vue3的element UI前端增删改查规范模板_ci_04


这里是选择项目的预设,如果之前创建过项目,且保存了预设,可以选择之前的预设,没有的话就进行手动配置项目。这里我选择了Babel、Router、Linter/Formatter、使用配置文件。

生成Vue3的element UI前端增删改查规范模板_数据_05


到这里基本就OK了。vue项目就创建在对应的文件夹中了。三、逻辑功能

table的基本功能:增删改查。

增:点击添加按钮,生成一个表单弹窗,在弹窗中填写信息后提交,新提交的信息显示在视图中。

删:点击删除按钮,删除对应的信息。

改:点击编辑按钮,生成一个表单弹窗,更改信息提交后在视图中更新数据。

查:搜索关键字,在视图中返回包含关键字的数据。

待完善的功能:

增:没有对输入的数据进行限制(数据种类、格式、是否为空…)

删:…

改:修改功能大体上借用的增加的代码逻辑,每一次都要重新输入选择的数据的所有的值。

查:查询只是在逻辑和视图上完成了功能,但并不是理想中查询的逻辑。

基本界面:

生成Vue3的element UI前端增删改查规范模板_搜索_06


生成Vue3的element UI前端增删改查规范模板_数据_07


生成Vue3的element UI前端增删改查规范模板_数据_08


生成Vue3的element UI前端增删改查规范模板_数据_09


四、代码实现

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