vue从不会实现最简易table增删改查

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

二、搭建vue-cli脚手架
图形化方式创建vue项目了。
cmd:

vue ui
image.png

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

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

到这里基本就OK了。vue项目就创建在对应的文件夹中了。

三、逻辑功能
table的基本功能:增删改查。
增:点击添加按钮,生成一个表单弹窗,在弹窗中填写信息后提交,新提交的信息显示在视图中。
删:点击删除按钮,删除对应的信息。
改:点击编辑按钮,生成一个表单弹窗,更改信息提交后在视图中更新数据。
查:搜索关键字,在视图中返回包含关键字的数据。
待完善的功能:
增:没有对输入的数据进行限制(数据种类、格式、是否为空...)
删:...
改:修改功能大体上借用的增加的代码逻辑,每一次都要重新输入选择的数据的所有的值。
查:查询只是在逻辑和视图上完成了功能,但并不是理想中查询的逻辑。
基本界面:

image.png
image.png
image.png
image.png
四、代码实现
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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,236评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,867评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,715评论 0 340
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,899评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,895评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,733评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,085评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,722评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,025评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,696评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,816评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,447评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,057评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,009评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,254评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,204评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,561评论 2 343

推荐阅读更多精彩内容