Vue 增刪改查

此demo選用的vue2.x版本
看完你將收獲以下幾點(diǎn)技能:

  1. 快速創(chuàng)建vue項(xiàng)目
  2. 理解vue常用指令的使用場(chǎng)景
  3. 網(wǎng)站快速成型工具Element-ui使用
  4. 項(xiàng)目中增刪改查的具體應(yīng)用

效果圖

image.png

技術(shù)棧

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

構(gòu)建工具選擇

如你遇到包下載慢、依賴(lài)不同導(dǎo)致各種bug等等(因?yàn)閚pm鏡像地址在國(guó)外所以訪問(wèn)會(huì)慢有的時(shí)候還訪問(wèn)不到),可選用淘寶鏡像地址(淘寶鏡像同步頻率目前為10分鐘一次以保證盡量與官方服務(wù)同步)或者pnpm
pnpm是高性能的npm,pnpm節(jié)省磁盤(pán)空間,安裝速度快;通過(guò)內(nèi)容可尋址存儲(chǔ)(CAS)、符號(hào)鏈接(Symbolic Link)、硬鏈接(Hard Link)等管理依賴(lài)包。

設(shè)置淘寶鏡像地址

// 淘寶鏡像新地址舊地址
https://registry.npm.taobao.org // 舊
https://registry.npmmirror.com  // 新
// 永久使用
npm config set registry https://registry.npmmirror.com
// 使用淘寶鏡像并把npm設(shè)置為cnpm
npm install -g cnpm --registry=https://registry.npm.npmmirror.org
// 查看是否設(shè)置成功
npm get registry 

換回npm官網(wǎng)地址

如果淘寶鏡像影響你發(fā)布模塊可這樣換回去

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

安裝pnpm

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

一.安裝vue

在安裝之前先確保安裝了node環(huán)境, 如果沒(méi)有安裝,去官網(wǎng)最新穩(wěn)定版下載nodejs

全局安裝vue-cli

一鍵生成工程化的vue項(xiàng)目

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

查看vue-cli版本

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

創(chuàng)建vue項(xiàng)目

vue create vue2-demo
// 或者
 mkdir vue2-demo && cd vue2-demo // 創(chuàng)建vue2-demo文件夾并進(jìn)入目錄
vue create .  // 在當(dāng)前創(chuàng)建vue項(xiàng)目

接下來(lái)會(huì)出現(xiàn)選擇以前的配置項(xiàng)還是vue默認(rèn)創(chuàng)建的項(xiàng)目,還是手動(dòng)選擇,
選擇Manually select features(手動(dòng)安裝),會(huì)進(jìn)入下一步操作

用空格和上下箭頭選擇配置項(xiàng)

CSS Pre-processors  // CSS 預(yù)處理器
Linter / Formatter  // 代碼風(fēng)格檢查和格式化(選擇保存和提交時(shí)校驗(yàn))
選擇standard編碼規(guī)范
Sass/SCSS (with dart-sass)  // 如果不想安裝node-sass選擇dart-sass

查看standardjs編碼規(guī)范

二.安裝Element-ui

cnpm i element-ui -S

三.使用element-ui布局頁(yè)面

第一步先在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)
});

兩種引入方式: 完整引入和按需引入,建議選用按需引入,具體操作見(jiàn)官網(wǎng)
流程:官網(wǎng)-> 組件 -> 快速上手
element官網(wǎng)

第二步:布局頁(yè)面

找到Container 布局容器模塊,選擇第一個(gè)模版 由header和main組成的模塊,也就是分為標(biāo)題和主內(nèi)容部分

<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="請(qǐng)輸入用戶(hù)名" v-model="formInline.username" clearable>
          </el-input>
          </el-form-item>
          <el-form-item>
            <el-button type="primary" icon="el-icon-search">查詢(xún)</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="市區(qū)" 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>無(wú)數(shù)據(jù)...</div>
      </el-main>
    </el-container>
  </el-container>

彈出框模版代碼

<!-- dialog start -->
    <el-dialog
      title="默認(rèn)彈層標(biāo)題"
      :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="用戶(hù)名">
          <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! -->

頁(yè)面js初始數(shù)據(jù)

data () {
    return {
      idx: 1, // 初始化id 為了使用本地?cái)?shù)據(jù) 
      editId: 0, // 要編輯的id
      showDialog: false, // 彈出層開(kāi)關(guān)
      addQuery: { // 添加字段
        username: '',
        date: ''
      },
      formInline: { // 查詢(xún)字段
        username: ''
      },
      tableData: [
        {
          id: 1,
          date: '2016-05-02',
          name: '王小虎1',
          province: '上海',
          city: '普陀區(qū)',
          address: '上海市普陀區(qū)金沙江路 1518 弄',
          zip: 200333
        },
        {
          id: 2,
          date: '2016-05-04',
          name: '王小虎2',
          province: '上海',
          city: '普陀區(qū)',
          address: '上海市普陀區(qū)金沙江路 1517 弄',
          zip: 200333
        },
        {
          id: 3,
          date: '2016-05-01',
          name: '王小虎3',
          province: '上海',
          city: '普陀區(qū)',
          address: '上海市普陀區(qū)金沙江路 1519 弄',
          zip: 200333
        },
        {
          id: 4,
          date: '2016-05-03',
          name: '王小虎4',
          province: '上海',
          city: '普陀區(qū)',
          address: '上海市普陀區(qū)金沙江路 1516 弄',
          zip: 200333
        }
      ]
    }
  },
methods: {
    handleClick (row) {
      console.log(row) // 查看 暫時(shí)不做什么功能
    }
}

備注:如果table出不來(lái),一片空白,原因是element-ui版本過(guò)高,在package里修改版本后 element-ui版本,cnpm install即可

四.添加-增/刪/改/查 邏輯

查詢(xún)

<el-input placeholder="請(qǐng)輸入用戶(hù)名" v-model.trim="formInline.username" clearable></el-input>
<el-button type="primary" icon="el-icon-search" @click="search">查詢(xún)</el-button>
// js-code
search () {
     /*
     第一步:先拿到input輸入的內(nèi)容
     第二步: 遍歷數(shù)組找到元素filter
     第三步:原數(shù)組賦值-更新視圖
      */
     const userName = this.formInline.username
     if (userName === '') {
       alert('請(qǐng)輸入查詢(xún)內(nèi)容哦') // 暫時(shí)用alert 哦~,可以用element自帶的漂亮框
       return
     }
     const tableData = JSON.parse(localStorage.getItem('tableData'))
     this.tableData = tableData.filter(item => item.name === userName)
}

注意:因?yàn)槭潜镜財(cái)?shù)據(jù),當(dāng)查詢(xún)條件有一個(gè)成立,不刷新頁(yè)面的情況,再次查詢(xún)會(huì)出現(xiàn)無(wú)數(shù)據(jù),原因是:
假如:第一次查詢(xún)name為王小虎1,把過(guò)濾的結(jié)果賦值給tableData,那么,
此時(shí)tableData里就只有name為王小虎1的這條數(shù)據(jù);
再次查詢(xún),即從最新的tableData里查詢(xún),查詢(xún)name為王小虎2的,顯
然找不到,所以也就會(huì)出現(xiàn)無(wú)數(shù)據(jù)情況。
解決辦法:因?yàn)槭潜镜財(cái)?shù)據(jù)庫(kù),那么我們可以在頁(yè)面掛載成功后,把tableData放到本地緩存一份,增加或者刪除的時(shí)候更新本地緩存,查詢(xún)的時(shí)候從本地緩存里查詢(xún),即可解決這個(gè)問(wèn)題。

新增localStoreSetItem函數(shù)

localStoreSetItem () {
      localStorage.setItem('tableData', JSON.stringify(this.tableData))
    }
mounted () {
    this.idx = this.tableData.length // 本地?cái)?shù)據(jù)生成id,用接口方式不需要這行代碼哦
    this.localStoreSetItem()
  },

添加邏輯

<el-button type="primary" @click="add">確 定</el-button>
add () {
      /*
      第一步:拿到彈出層輸入框內(nèi)容
            定義日期格式化函數(shù):formatDate 轉(zhuǎn)換格式
      第二步:追加到tableData數(shù)組中
            定義插入對(duì)象格式
      第三步:給tableData賦值 ->更新視圖
      第四步:彈出層數(shù)據(jù)數(shù)據(jù)恢復(fù)默認(rèn),關(guān)閉彈出層后把屬性設(shè)置為空 新增close
      */
      const { username, date } = this.addQuery
      const newDate = this.formatDate(date)
      const obj = {
        date: newDate,
        name: username,
        province: '上海',
        city: '普陀區(qū)',
        address: '上海市普陀區(qū)金沙江路 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)
      // 先查找當(dāng)前要?jiǎng)h除的id在數(shù)組的位置
      const index = this.tableData.findIndex((item) => item.id === id)
      // 從當(dāng)前位置開(kāi)始刪除1條內(nèi)容
      this.tableData.splice(index, 1)
      // 更新緩存中的tableData數(shù)據(jù)
      this.localStoreSetItem()
    }

注意:刪除的兩種方法;注意更新本地緩存數(shù)據(jù),不然有bug哦,刪除后的元素還能被搜索到哦

批量刪除

需要在el-table組件上綁定事件函數(shù),@selection-change=“自定義函數(shù)”,可以拿到選中的元素集合數(shù)組展示

// 模版
<el-table
          v-if="tableData.length > 0"
          @selection-change="handleSelectionTable"
          :data="tableData"
          border
          style="width: 100%"
        >
// js
handleSelectionTable (val) {
      this.selectionTableArr = val
    },
delMore () {
      /* 一.如果是后臺(tái)接口只需要傳遞[id1,id],那我們直接把選中的id拿出來(lái)即可
      兩種方法: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)
      /* 二. 以上是給接口的,那么現(xiàn)在處理本地的批量刪除
        第一步:循環(huán)刪除 -> 遞歸 do-while; 遞歸條件已選擇的數(shù)組len小于0的時(shí)候停止
        第二步:需要遞歸處理的事情,也就是while放的代碼:先查找已選中的id在原數(shù)組的位置,然后splice刪除1項(xiàng)
        第三步:更新本地緩存
      */
      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)
    },

修改邏輯

因?yàn)樾薷倪壿嬏幚硗陻?shù)據(jù)回填后,走的還是添加的邏輯,所以添加代碼修改為

 show () {
      this.showDialog = true
      this.editId = 0
    },
edit (row) {
      /*
        分析:把當(dāng)前要編輯的row拿到;然后賦值給彈出層表單model的addQuery對(duì)象,addQuery對(duì)象更新input的v-model值更新
        第一步:拿到當(dāng)前點(diǎn)擊的row對(duì)象
        第二步:給addQuery對(duì)象的屬性賦值 for in 或者 深拷貝
        第三步:點(diǎn)擊保存后:1.如果是走的接口,那么會(huì)和添加是一樣的邏輯
                         2.如果更新本地緩存,那么先找到當(dāng)前id所在數(shù)組的位置
                           接著,用splice(index, 1, 新的內(nèi)容對(duì)象) // 刪除一條用新的內(nèi)容替換
        第四步:更新最新緩存數(shù)據(jù)tableData

      */
      this.showDialog = true
      for (const k in row) {
        this.addQuery[k] = row[k]
      }
      this.editId = row.id
      this.showDialog = true
 },
add (id) {
      /*
      第一步:拿到彈出層輸入框內(nèi)容
            定義日期格式化函數(shù):formatDate 轉(zhuǎn)換格式
      第二步:追加到tableData數(shù)組中
            定義插入對(duì)象格式
      第三步:給tableData賦值  更新視圖
      第四步:彈出層數(shù)據(jù)數(shù)據(jù)恢復(fù)默認(rèn),關(guān)閉彈出層,
      */
      !this.showDialog && (this.showDialog = true)
      const {  name, date } = this.addQuery
      if (name === '' && this.date === '') {
        alert('請(qǐng)?zhí)顚?xiě)內(nèi)容')
        return
      }
      // 如果有要修改的數(shù)據(jù),把之前的舊數(shù)據(jù)刪除
      const index = this.tableData.findIndex(item => id === item.id)
      const newDate = this.formatDate(date)
      const obj = {
        id: ++this.idx,
        date: newDate,
        name,
        province: '上海',
        city: '普陀區(qū)',
        address: '上海市普陀區(qū)金沙江路 1518 弄',
        zip: 200333
      }
     if (this.editId > 0) {
        this.tableData.splice(index, 1, obj) // 如果是修改元素順序不變
        this.editId = 0
      } else {
        this.tableData.unshift(obj) // 如果是新添加第一條出現(xiàn)最上面
      }
      this.localStoreSetItem() // 不管是添加還是修改都要更新本地緩存
      this.close()
    },

五. 總結(jié)

1.添加或者修改數(shù)據(jù)后再次打開(kāi)彈出層記得清空上一次的記錄狀態(tài)
2.使用本地?cái)?shù)據(jù)和真實(shí)項(xiàng)目中的接口操作數(shù)據(jù)有很多地方變化,一定要注意之間的關(guān)系。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
禁止轉(zhuǎn)載,如需轉(zhuǎn)載請(qǐng)通過(guò)簡(jiǎn)信或評(píng)論聯(lián)系作者。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,702評(píng)論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,143評(píng)論 3 415
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 175,553評(píng)論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 62,620評(píng)論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,416評(píng)論 6 405
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 54,940評(píng)論 1 321
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,024評(píng)論 3 440
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 42,170評(píng)論 0 287
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,709評(píng)論 1 333
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,597評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,784評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,291評(píng)論 5 357
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,029評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 34,407評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 35,663評(píng)論 1 280
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,403評(píng)論 3 390
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,746評(píng)論 2 370

推薦閱讀更多精彩內(nèi)容