Vue 增删改查

此demo选用的vue2.x版本
看完你将收获以下几点技能:

  1. 快速创建vue项目
  2. 理解vue常用指令的使用场景
  3. 网站快速成型工具Element-ui使用
  4. 项目中增删改查的具体应用

效果图

image.png

技术栈

vue2.x + Element-ui + sass + esLint + standard

构建工具选择

如你遇到包下载慢、依赖不同导致各种bug等等(因为npm镜像地址在国外所以访问会慢有的时候还访问不到),可选用淘宝镜像地址(淘宝镜像同步频率目前为10分钟一次以保证尽量与官方服务同步)或者pnpm
pnpm是高性能的npm,pnpm节省磁盘空间,安装速度快;通过内容可寻址存储(CAS)、符号链接(Symbolic Link)、硬链接(Hard Link)等管理依赖包。

设置淘宝镜像地址

// 淘宝镜像新地址旧地址
https://registry.npm.taobao.org // 旧
https://registry.npmmirror.com  // 新
// 永久使用
npm config set registry https://registry.npmmirror.com
// 使用淘宝镜像并把npm设置为cnpm
npm install -g cnpm --registry=https://registry.npm.npmmirror.org
// 查看是否设置成功
npm get registry 

换回npm官网地址

如果淘宝镜像影响你发布模块可这样换回去

npm config set registry https://registry.npmjs.org

安装pnpm

npm install -g pnpm
// 或
cnpm install -g pnpm

一.安装vue

在安装之前先确保安装了node环境, 如果没有安装,去官网最新稳定版下载nodejs

全局安装vue-cli

一键生成工程化的vue项目

cnpm install -g @vue/cli
# 或者
yarn global add @vue/cli

查看vue-cli版本

vue  -V  // @vue/cli 5.0.8 vue-^2.6.14

创建vue项目

vue create vue2-demo
// 或者
 mkdir vue2-demo && cd vue2-demo // 创建vue2-demo文件夹并进入目录
vue create .  // 在当前创建vue项目

接下来会出现选择以前的配置项还是vue默认创建的项目,还是手动选择,
选择Manually select features(手动安装),会进入下一步操作

用空格和上下箭头选择配置项

CSS Pre-processors  // CSS 预处理器
Linter / Formatter  // 代码风格检查和格式化(选择保存和提交时校验)
选择standard编码规范
Sass/SCSS (with dart-sass)  // 如果不想安装node-sass选择dart-sass

查看standardjs编码规范

二.安装Element-ui

cnpm i element-ui -S

三.使用element-ui布局页面

第一步先在main.js 引入ui

完整引入

import Vue from 'vue';
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import App from './App.vue';

Vue.use(ElementUI);

new Vue({
  el: '#app',
  render: h => h(App)
});

两种引入方式: 完整引入和按需引入,建议选用按需引入,具体操作见官网
流程:官网-> 组件 -> 快速上手
element官网

第二步:布局页面

找到Container 布局容器模块,选择第一个模版 由header和main组成的模块,也就是分为标题和主内容部分

<el-container>
  <el-header>Header</el-header>
  <el-main>Main</el-main>
</el-container>

按模块添加如下代码:

<el-container>
    <el-header>vue2.x增删改查part01</el-header>
    <el-container>
      <el-main>
        <el-form :inline="true" :model="formInline" class="demo-form-inline">
          <el-form-item>
            <el-input placeholder="请输入用户名" v-model="formInline.username" clearable>
          </el-input>
          </el-form-item>
          <el-form-item>
            <el-button type="primary" icon="el-icon-search">查询</el-button>
            <el-button type="success" @click="show">添加</el-button>
            <el-button type="danger">批量删除</el-button>
          </el-form-item>
        </el-form>
        <el-table v-if="tableData.length > 0" :data="tableData" border style="width: 100%">
          <el-table-column type="selection" width="40">
          </el-table-column>
          <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="操作">
            <template slot-scope="scope">
              <el-button
                @click="handleClick(scope.row)"
                type="primary"
                size="mini"
                >查看</el-button
              >
              <el-button type="success" size="mini">编辑</el-button>
              <el-button type="danger" size="mini">删除</el-button>
            </template>
          </el-table-column>
        </el-table>
        <div class="nodata" v-else>无数据...</div>
      </el-main>
    </el-container>
  </el-container>

弹出框模版代码

<!-- dialog start -->
    <el-dialog
      title="默认弹层标题"
      :visible.sync="showDialog"
      custom-class="mydialog"
    @close="close"
    >
      <div slot="title" align="left">添加信息</div>
      <el-form
        :model="addQuery"
        :inline="true"
        label-position="right"
        label-width="80px"
      >
        <el-form-item label="用户名">
          <el-input v-model="addQuery.username" autocomplete="off"></el-input>
        </el-form-item>
        <el-form-item label="选择日期">
          <el-date-picker
            v-model="addQuery.date"
            type="date"
            style="width:90%"
            placeholder="选择日期"
          >
          </el-date-picker>
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="close">取 消</el-button>
        <el-button type="primary" @click="add">确 定</el-button>
      </div>
    </el-dialog>
    <!-- dialog end! -->

页面js初始数据

data () {
    return {
      idx: 1, // 初始化id 为了使用本地数据 
      editId: 0, // 要编辑的id
      showDialog: false, // 弹出层开关
      addQuery: { // 添加字段
        username: '',
        date: ''
      },
      formInline: { // 查询字段
        username: ''
      },
      tableData: [
        {
          id: 1,
          date: '2016-05-02',
          name: '王小虎1',
          province: '上海',
          city: '普陀区',
          address: '上海市普陀区金沙江路 1518 弄',
          zip: 200333
        },
        {
          id: 2,
          date: '2016-05-04',
          name: '王小虎2',
          province: '上海',
          city: '普陀区',
          address: '上海市普陀区金沙江路 1517 弄',
          zip: 200333
        },
        {
          id: 3,
          date: '2016-05-01',
          name: '王小虎3',
          province: '上海',
          city: '普陀区',
          address: '上海市普陀区金沙江路 1519 弄',
          zip: 200333
        },
        {
          id: 4,
          date: '2016-05-03',
          name: '王小虎4',
          province: '上海',
          city: '普陀区',
          address: '上海市普陀区金沙江路 1516 弄',
          zip: 200333
        }
      ]
    }
  },
methods: {
    handleClick (row) {
      console.log(row) // 查看 暂时不做什么功能
    }
}

备注:如果table出不来,一片空白,原因是element-ui版本过高,在package里修改版本后 element-ui版本,cnpm install即可

四.添加-增/删/改/查 逻辑

查询

<el-input placeholder="请输入用户名" v-model.trim="formInline.username" clearable></el-input>
<el-button type="primary" icon="el-icon-search" @click="search">查询</el-button>
// js-code
search () {
     /*
     第一步:先拿到input输入的内容
     第二步: 遍历数组找到元素filter
     第三步:原数组赋值-更新视图
      */
     const userName = this.formInline.username
     if (userName === '') {
       alert('请输入查询内容哦') // 暂时用alert 哦~,可以用element自带的漂亮框
       return
     }
     const tableData = JSON.parse(localStorage.getItem('tableData'))
     this.tableData = tableData.filter(item => item.name === userName)
}

注意:因为是本地数据,当查询条件有一个成立,不刷新页面的情况,再次查询会出现无数据,原因是:
假如:第一次查询name为王小虎1,把过滤的结果赋值给tableData,那么,
此时tableData里就只有name为王小虎1的这条数据;
再次查询,即从最新的tableData里查询,查询name为王小虎2的,显
然找不到,所以也就会出现无数据情况。
解决办法:因为是本地数据库,那么我们可以在页面挂载成功后,把tableData放到本地缓存一份,增加或者删除的时候更新本地缓存,查询的时候从本地缓存里查询,即可解决这个问题。

新增localStoreSetItem函数

localStoreSetItem () {
      localStorage.setItem('tableData', JSON.stringify(this.tableData))
    }
mounted () {
    this.idx = this.tableData.length // 本地数据生成id,用接口方式不需要这行代码哦
    this.localStoreSetItem()
  },

添加逻辑

<el-button type="primary" @click="add">确 定</el-button>
add () {
      /*
      第一步:拿到弹出层输入框内容
            定义日期格式化函数:formatDate 转换格式
      第二步:追加到tableData数组中
            定义插入对象格式
      第三步:给tableData赋值 ->更新视图
      第四步:弹出层数据数据恢复默认,关闭弹出层后把属性设置为空 新增close
      */
      const { username, date } = this.addQuery
      const newDate = this.formatDate(date)
      const obj = {
        date: newDate,
        name: username,
        province: '上海',
        city: '普陀区',
        address: '上海市普陀区金沙江路 1518 弄',
        zip: 200333
      }
      this.tableData.unshift(obj)
      this.showDialog = false
    },
    close () {
      this.showDialog = false
      this.addQuery.name = ''
      this.addQuery.date = ''
    },
  }

删除逻辑

// 模版
<el-button type="danger" size="mini" @click="del(scope.row.id)">删除</el-button>

// js
del (id) {
      // 两种方法:filter,和splice 推荐splice
      // this.tableData = this.tableData.filter((e) => e.id !== id)
      // 先查找当前要删除的id在数组的位置
      const index = this.tableData.findIndex((item) => item.id === id)
      // 从当前位置开始删除1条内容
      this.tableData.splice(index, 1)
      // 更新缓存中的tableData数据
      this.localStoreSetItem()
    }

注意:删除的两种方法;注意更新本地缓存数据,不然有bug哦,删除后的元素还能被搜索到哦

批量删除

需要在el-table组件上绑定事件函数,@selection-change=“自定义函数”,可以拿到选中的元素集合数组展示

// 模版
<el-table
          v-if="tableData.length > 0"
          @selection-change="handleSelectionTable"
          :data="tableData"
          border
          style="width: 100%"
        >
// js
handleSelectionTable (val) {
      this.selectionTableArr = val
    },
delMore () {
      /* 一.如果是后台接口只需要传递[id1,id],那我们直接把选中的id拿出来即可
      两种方法:forEach,reduce
      */
      console.time('forEach')
      const ids = []
      this.selectionTableArr.forEach(item => {
        ids.push(item.id)
      })
      console.timeEnd('forEach') // forEach: 0.02099609375 ms
      // reduce效率最高
      console.time('reduce')
      const ids1 = this.selectionTableArr.reduce((arr, item) => {
        arr.push(item.id)
        return arr
      }, [])
      console.timeEnd('reduce') // reduce: 0.009033203125 ms
      console.log(ids1)
      /* 二. 以上是给接口的,那么现在处理本地的批量删除
        第一步:循环删除 -> 递归 do-while; 递归条件已选择的数组len小于0的时候停止
        第二步:需要递归处理的事情,也就是while放的代码:先查找已选中的id在原数组的位置,然后splice删除1项
        第三步:更新本地缓存
      */
      let len = this.selectionTableArr.length
      do {
        const index = this.tableData.findIndex(item => item.id === this.selectionTableArr[len - 1].id)
        this.tableData.splice(index, 1)
        len--
       // 刚更新本地缓存
        this.localStoreSetItem()
      } while (len > 0)
    },

修改逻辑

因为修改逻辑处理完数据回填后,走的还是添加的逻辑,所以添加代码修改为

 show () {
      this.showDialog = true
      this.editId = 0
    },
edit (row) {
      /*
        分析:把当前要编辑的row拿到;然后赋值给弹出层表单model的addQuery对象,addQuery对象更新input的v-model值更新
        第一步:拿到当前点击的row对象
        第二步:给addQuery对象的属性赋值 for in 或者 深拷贝
        第三步:点击保存后:1.如果是走的接口,那么会和添加是一样的逻辑
                         2.如果更新本地缓存,那么先找到当前id所在数组的位置
                           接着,用splice(index, 1, 新的内容对象) // 删除一条用新的内容替换
        第四步:更新最新缓存数据tableData

      */
      this.showDialog = true
      for (const k in row) {
        this.addQuery[k] = row[k]
      }
      this.editId = row.id
      this.showDialog = true
 },
add (id) {
      /*
      第一步:拿到弹出层输入框内容
            定义日期格式化函数:formatDate 转换格式
      第二步:追加到tableData数组中
            定义插入对象格式
      第三步:给tableData赋值  更新视图
      第四步:弹出层数据数据恢复默认,关闭弹出层,
      */
      !this.showDialog && (this.showDialog = true)
      const {  name, date } = this.addQuery
      if (name === '' && this.date === '') {
        alert('请填写内容')
        return
      }
      // 如果有要修改的数据,把之前的旧数据删除
      const index = this.tableData.findIndex(item => id === item.id)
      const newDate = this.formatDate(date)
      const obj = {
        id: ++this.idx,
        date: newDate,
        name,
        province: '上海',
        city: '普陀区',
        address: '上海市普陀区金沙江路 1518 弄',
        zip: 200333
      }
     if (this.editId > 0) {
        this.tableData.splice(index, 1, obj) // 如果是修改元素顺序不变
        this.editId = 0
      } else {
        this.tableData.unshift(obj) // 如果是新添加第一条出现最上面
      }
      this.localStoreSetItem() // 不管是添加还是修改都要更新本地缓存
      this.close()
    },

五. 总结

1.添加或者修改数据后再次打开弹出层记得清空上一次的记录状态
2.使用本地数据和真实项目中的接口操作数据有很多地方变化,一定要注意之间的关系。

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

推荐阅读更多精彩内容