1. 程式人生 > >VUE元件系列7:Table封裝3

VUE元件系列7:Table封裝3

前面寫的Table封裝,只是省了一部分事情,還是需要通過slot配置表結構,沒有達到一開始的想法:

只配置一個載入url和一個增刪改url 就完事了。

所以就再次優化。

問題1 修改與非修改間切換,通過這麼一個JSON陣列 {"name":"標籤名稱","val":"標籤值","flag":"是否顯示"}

     <div class="unit" v-for="(item, index) in userData" :key="index">
        <label>{{ item.name }}:</label>
        <input
          type="text"
          v-model="item.val"
          class="sys_input"
          v-bind:disabled="item.flag == '0' ? false : true"
        />
      </div>

實現效果如下,這樣就可以直接控制是否可以修改了。

測試原始碼如下:

<template>
  <div>
    <!-- table部分 -->
    <div class="carddata">
      <table class="pre_dataintable">
        <thead>
          <tr>
            <th v-for="(item, index) in tab_th" :key="index">
              {{ item.val }}
            </th>
            <th>操作</th>
          </tr>
        </thead>
        <tbody>
          <tr v-for="(item, index) in tab_tr" :key="index">
            <td v-for="(temp, index) in item" :key="index">
              <input
                type="text"
                v-model="temp.val"
                v-bind:disabled="temp.flag == '0' ? false : true"
              />
            </td>
            <td>
              <button @click="fun_upd(item)">修改</button>
              <button @click="fun_sav(item)">儲存</button>
              <button @click="fun_del(item)">刪除</button>
            </td>
          </tr>
        </tbody>
      </table>
    </div>
    <!-- 分頁部分 -->
    <div class="pre_page" v-show="show_page">
      <ul style="text-align: right; margin-right: 20px;">
        <li>
          當前頁:<label>{{ nowpage }}</label
          >&nbsp; 合計頁:<label>{{ maxpage }}</label
          >&nbsp;&nbsp; <a href="#" @click="firstpage">首頁</a>|
          <a href="#" @click="beforepage">上一頁</a>|
          <a href="#" @click="nextpage">下一頁</a>|
          <a href="#" @click="lastpage">尾頁</a>
          <input type="text" v-model="jumppage" value="" /><a
            href="#"
            @click="gopage"
            class="go"
            >Go</a
          >
        </li>
      </ul>
    </div>
    <!-- 彈出嚮導層 start-->
    <div id="pop" class="pop" v-show="pop_show">
      <div class="pop_head">
        <a class="close" href="javascript:void(0);" @click="hide()"></a>
      </div>
      <div id="pop_bodyup" class="pop_bodyup">
        <div class="input_data">
          <slot name="tab_addorupdate"></slot>
          <!-- <button
            @click="neworupdate"
            @keyup.enter="neworupdate"
            style="margin:30px 0 0 80px;background:#4f5f6f;width:56px;height:28px;border:none;outline:none;cursor: pointer;color:#fff;"
          >
            新增或修改
          </button> -->
        </div>
      </div>
    </div>
    <!-- 彈出嚮導層 end-->
    <!-- 新增到下面 start -->
    <div class="data_down">
      <slot name="tab_addorupdate_down"></slot>
    </div>
    <!-- 新增到下面 end -->
    <!-- 元件引入部分 彈窗元件和等待元件 -->
    <div>
      <per-message ref="msg_back" :message_data="msg_obj" />
      <pre-loading :pre_show_loading="fullloading" />
    </div>
  </div>
</template>
<script >
/*
名稱:Table元件
日期:2019-03-21
作者:hj
目標:1、傳入一組資料,自動構建標題和內容=>兩個陣列  1個數組是標題  1個數組是內容  方便構造 
     2、所有的增、刪、改、查、均在元件內容完成。
     3、還可以分頁

分析:1、增、刪、改、查 呼叫api主動配置。=>容易
     2、標題主動配置。=>容易
     3、每一列的校驗方式 =>配置  
     4、不使用 solo 佔位符實現

*/
import '@/assets/css/pop.css';
import '@/assets/css/pre_table.css';
export default {  
  name: "pre_table_base",
  components: {    
    'per-message':()=>import("./pre_message.vue"),
    'pre-loading':()=>import("./pre_loading.vue")
  },  
  data() {
    return {
      tab_th: [],     //標題
      tab_tr: [],     //內容  
      show_page:true,
      maxpage:'',
      nowpage:'',
      jumppage:'',
      msg_obj:{},
      fullloading:false,      
      pop_show:false,
      show_btn_upd:true,
      show_btn_del:true,
      show_btn_sav:true,
    };
  },
  props: {
    api_url:String,
    pre_post:String, 
    page:String,   
    /* 需要 增 刪 改 就繫結這個 */
    pre_post_upd:{ type:String,default:'' },
    /* 按鈕顯示控制 */ 
    show_btn_upd:{type:Boolean,default:true},
    show_btn_del:{type:Boolean,default:true},
    show_btn_sav:{type:Boolean,default:true}

  },
  created:function(){
      if(Number(this.nowpage)==0) this.nowpage=1;
  },
  watch:{
    pre_post(val){
      //監測查詢條件 改變即重查
      this.loaddata();
    },
    pre_post_upd(val){
      // 監測修改條件 改變即修改
      if(String(val)!='')
        this.neworupdate();
    },
    page(val){
      // 監測翻頁
      if(Number(val)==0){
        this.nowpage=1;
      }else{
        this.nowpage=Number(val);
      }
    },
    nowpage(val){
      // 返回新頁數
      this.$emit("tab-event", this.nowpage);
    }
  },
  mounted() {
    this.initTable();
    this.loaddata();
  },
  methods: {
    initTable:function(){
      if(Number(this.maxpage)==0){
        this.show_page=false;
      }else{
        this.show_page=true;
      }
    },
    firstpage:function(){
        if(Number(this.nowpage)>1){
            this.nowpage=1;
            this.refresh_data();
        }else{
            this.msg_obj={'showtype':'warning','note':'已經是第一頁'};
        }
    },
    beforepage:function(){
        if(Number(this.nowpage)>1){
            this.nowpage--;
            this.refresh_data();
        }else{
            this.msg_obj={'showtype':'warning','note':'已經是第一頁'};
        }
    },
    nextpage:function(){
        if(Number(this.nowpage)<Number(this.maxpage)){
            this.nowpage++;
            this.refresh_data();
        }else{            
            this.msg_obj={'showtype':'warning','note':'已經是最後一頁'};
        }
    },
    lastpage:function(){
        if(Number(this.nowpage)<Number(this.maxpage)){
            this.nowpage=this.maxpage;
            this.refresh_data();
        }else{
            this.msg_obj={'showtype':'warning','note':'已經是最後一頁'};
        }
    },
    gopage:function(){
        console.log('跳轉到='+this.jumppage);
        if(Number(this.jumppage)>0 && Number(this.jumppage)<=Number(this.maxpage)){
            this.nowpage=this.jumppage;
            this.refresh_data();
        }else{
            this.msg_obj={'showtype':'warning','note':'跳轉頁數不在規定範圍內,請檢查'+this.jumppage};
        }
    },
    loaddata:function() {
      // console.log(this.api_url);
      // console.log(this.pre_post);      
      // this.fullloading=true;
      // this.$post(
      //   this.api_url,
      //   this.pre_post,
      // ).then(res => {
      //   this.fullloading=false;
      //   try {         
      //     res=JSON.parse(res); 
      //     console.log(res.data);         
      //     if (res.data.status == 1) {
      //       this.maxpage=res.data.allpage;
      //       this.data_tab=res.data.data;
      //     } else {
      //       this.msg_obj={'showtype':'warning','note':res.data.msg};
      //     }
      //     this.initTable();
      //   } catch (ex) {
      //     this.msg_obj={'showtype':'warning','note':"查詢失敗"+ex};
      //   }
      // });

      // 構建測試資料 二維陣列 模擬通過api取到如下資料
      var data=[];
      var tobj=[];
      tobj.push({"val":"序號"});
      tobj.push({"val":"列名1"});
      tobj.push({"val":"列名2"});
      tobj.push({"val":"列名3"});      
      data[0]=tobj;
      console.log(data);
      for(var i=1;i<5;i++){
        tobj=[];
        tobj.push({"val":""+i+"","flag":"1"});
        tobj.push({"val":""+i+"行資料1","flag":"1"});
        tobj.push({"val":""+i+"行資料2","flag":"1"});
        tobj.push({"val":""+i+"行資料3","flag":"1"});
        data[i]=tobj;
      }
      
      //  將表頭和內容分開
      this.tab_th=data[0];
      var tdata=[],num=0;
      for(var i=1;i<data.length;i++){        
        tdata[num]=data[i];
        num++;
      }
      this.tab_tr=tdata;
      console.log(this.tab_th);
      console.log(this.tab_tr);

    },
    refresh_data() {
      console.log('重新整理');
      this.$emit("tab-event", this.nowpage,this.key_word,'');
    },
    showpop:function(){
      this.pop_show=true;
    },
    hide:function(){
      this.pop_show=false;
    },
    fun_add:function(){

    },
    fun_del:function(item){
      console.log('刪除');
      var ts=JSON.stringify(item).toString();
      console.log(ts);
      
    },
    fun_upd:function(item){
      console.log('修改');
      // var ts=JSON.stringify(item).toString();
      // console.log(ts);
      // 釋放修改許可權
      console.log(item);
      var id=item[0].val;
      for(var i=0;i<this.tab_tr.length;i++){
        if(this.tab_tr[i][0].val==item[0].val){
          for(var j=1;j<this.tab_tr[i].length;j++){
            this.tab_tr[i][j].flag='0';
          }
        }else{
          for(var j=1;j<this.tab_tr[i].length;j++){
            this.tab_tr[i][j].flag='1';
          }
        }
      }

    },
    fun_sav:function(item){
      console.log('儲存');
      var ts=JSON.stringify(item).toString();
      console.log(ts);
    },
    fun_sel:function(){

    },
    neworupdate:function() {
      // console.log(this.api_url);
      // console.log(this.pre_post_upd);      
      this.fullloading=true;
      this.$post(
        this.api_url,
        this.pre_post_upd,
      ).then(res => {
        this.fullloading=false;
        this.pop_show=false;
        try {         
          res=JSON.parse(res); 
          console.log(res.data);         
          if (res.data.status == 1) {
            this.msg_obj={'showtype':'ok','note':res.data.msg};
            this.loaddata();
          } else {
            this.msg_obj={'showtype':'err','note':res.data.msg};
          }
          this.initTable();
        } catch (ex) {
          this.msg_obj={'showtype':'warning','note':"查詢失敗"+ex};
        }
      });
    },
  }
};
</script>
 
<style scoped >
</style>

CSS樣式檔案

/* pre_search */
.pre_btn {
	text-align: left;
}
.pre_btn > label {
	position: relative;
	/* left: 2%; */
}
.pre_btn > input {
	position: relative;
	/* left: 2%; */
}
.pre_btn > input :focus {
	border: 1px solid #024aee;
	background-color: #aaa;
}

.pre_btn > button {
	position: relative;
	left: 2%;
	width: 120px;
	height: 32px;
	line-height: 32px;
	border-radius: 5px;
}

.pre_btn_ok {
	background-color: rgba(68, 70, 238, 0.986);
	color: white;
	font-optical-sizing: 16px;
}

.pre_btn_ok :focus {
	background-color: rgba(247, 61, 36, 0.986);
}

/* table 整體樣式 */
.pre_dataintable {
	margin-top: 15px;
	border-collapse: collapse;
	border: 1px solid #aaa;
	width: 95%;
	/* padding 沒有作用 */
	/* padding: 0px 5px 10px 5px; */
	position: relative;
	/* left: 2%; */
}
.pre_dataintable th {
	vertical-align: baseline;
	padding: 5px 15px 5px 6px;
	background-color: rgb(87, 201, 230);
	border: 1px solid #3f3f3f;
	text-align: center;
	color: #000000;
	font-size: 16px;
	font-weight: bolder;
}
.pre_dataintable td {
	/* vertical-align: text-top; */
	padding: 5px 8px 5px 8px;
	border: 1px solid #aaa;
	text-align: left;
}
/* 表格內按鈕 */
.pre_dataintable td button {
	width: 80px;
	padding: 6px 6px 6px 6px;
	border: 1px solid #aaa;
	text-align: center;
	display: inline-block;
}
/* 表格內輸入框 */
.pre_dataintable td input {
	width: 100%;
	height: 100%;
	border: 0px;
	text-align: left;
	padding: 2px 2px 2px 2px;
  /* font-size: 16px; */
  background-color: #babcbe00;
}

.pre_dataintable tr {
	cursor: pointer;
}
.pre_dataintable tr:nth-child(odd) {
	background-color: #f5f5f5;
}
.pre_dataintable tr:nth-child(even) {
	background-color: #fff;
}
.pre_dataintable tr:hover {
	background-color: #e2fde2;
}

.tab_add {
	width: 95%;
	display: flex;
	margin-top: 5px;
	margin-left: 2%;
	background-color: rgba(103, 233, 77, 0.644);
}
.tab_upd {
	width: 95%;
	display: flex;
	margin-left: 2%;
	background-color: rgba(209, 212, 36, 0.644);
}

/* 翻頁樣式 */
.pre_page {
	width: 100%;
	margin-top: 5px;
	margin-bottom: 5px;
}
.pre_page > ul {
	text-align: right;
	list-style: none;
}
.pre_page > ul > li > a {
	text-decoration: none;
}
.pre_page > ul > li > .go {
	display: inline-block;
	width: 40px;
	height: 20px;
	border: 1px solid #cccccc;
	background: #024aee;
	color: #fff;
	border-radius: 4px;
	text-align: center;
	margin-left: 5px;
}
.pre_page > ul > li > a:hover {
	color: #394656;
}
/* 下面樣式 */
.td_btn {
	text-align: center;
}
.td_btn > button {
	border-radius: 3px;
	height: 28px;
	padding: 1px 2px 2px 2px;
}
.td_btn > button:hover {
	background-color: rgba(155, 222, 231, 0.986);
	cursor: pointer;
}
.btn_upd {
	background-color: rgba(244, 247, 111, 0.986);
}
.btn_sub {
	background-color: rgba(44, 247, 61, 0.986);
}
.btn_can {
	background-color: rgba(234, 248, 246, 0.986);
}
.btn_del {
	background-color: rgba(236, 26, 26, 0.986);
}
/* 單選樣式 */
.radio_name {
}
.radio_val {
	width: 20px;
}

效果如下

呼叫方式

展示效果:

預設資料

點選修改後資料

剩下的慢慢補全,總算不用每次都寫好幾