vue+element 表單封成組件(1)


作為一名剛接觸vue不到一個月的菜鳥,思想還沒有從操作DOM轉變為數據驅動,看vue的代碼處處別扭。組里為了讓我熟悉vue交給了我一個將element 表單封裝成組件的練手任務。由於開發過程中遇到的表單需求千奇百怪,我們不能直接將表單封裝成一個組件。所以我嘗試把輸入框,下拉菜單,滑塊,時間選擇器,單選,多選等功能各封一個組件(感覺很蠢),但這畢竟是練手任務嘛,最后開發時也不會用我的這個。在封裝的過程中遇到了很多問題和疑惑,以下記錄我的收獲與尚未解決的問題。

 1 <template>
 2   <el-form :model="ruleForm" ref="ruleForm" label-width="100px"  class="demo-ruleForm">
 3       <commonformtext
 4       prop="biao"
 5       placeholder="這個是測試的"
 6       label="活動區域"
 7       v-model="ruleForm.biao"
 8       :rules="[{ required: true, message: '請輸入活動名稱', trigger: 'blur' }]"
 9       >
10       </commonformtext>
11       <commonformselect
12       prop="select"
13       placeholder="這個是測試的下拉框"
14       label="下拉框"
15       v-model="ruleForm.select"
16       :rules="{ required: true, message: '請選擇活動區域', trigger: 'change' }"
17       :selectdata='selectdata'
18       >
19       </commonformselect> 
20       <el-form-item>
21         <el-button type="primary" @click="submitForm('ruleForm')">立即創建</el-button>
22         <el-button @click="resetForm('ruleForm')">重置</el-button>
23       </el-form-item>
24 </el-form>
25 </template>
26 <script> 
27 import commonformtext from "@/components/common/formtext.vue";
28 import commonformselect from "@/components/common/formselect.vue";
29   export default {
30     data() {
31       return {
32         ruleForm: {
33           biao:"",
34           select:""
35         },
36         selectdata:[
37           {lable:"區域1",value:"1"},
38           {lable:"區域2",value:"2"},
39           {lable:"區域3",value:"3"},
40           {lable:"區域4",value:"4"},
41           {lable:"區域5",value:"5"}
42         ]
43       };
44     },
45     components:{
46         commonformtext,
47         commonformselect,
48     },
49     methods: {
50       submitForm(formName) {
51         this.$refs[formName].validate((valid) => {
52           if (valid) {
53             alert('submit!');
54           } else {
55             console.log('error submit!!');
56             return false;
57           }
58         });
59       },
60       resetForm(formName) {
61         this.$refs[formName].resetFields();
62       }
63     }
64   }
65 </script>

以上是父組件,本篇先傳輸入框,下拉菜單兩個子組件

/*
* @property { rules :  {String Object} 表單驗證 一種驗證傳對象 一種以上把對象組成數組 }
* @property { prop :  {String} input的name 傳回的字段名與html中input標簽name值一樣。 }
* @property { placeholder :  {String} 提示語,與html中input標簽placeholder值一樣。 }
* @property { label :  {String} 標簽文本。 }
* @property { v-model :  {String} 語法糖,利用value接值父子組件相互傳值 當前表單填寫的內容  }
* @version 1.0.0
* @edit: 2018/7/30
*/
<template>
  <el-form-item :label="label" :prop="prop" :rules="rules">
    <el-input v-model="myValue" :placeholder="placeholder" name="biao"></el-input>
  </el-form-item>
</template>
<script>
    export default {
        props: {
            prop: {
                type: String
            },
            placeholder:{
                type: String
            },
            label:{
                type: String
            },
            value:{
                type: String
            },
            rules:[Object,Array]
        },
    data() {
        return {
            activeIndex: '',
            menuIndex: 0,
            myValue:""
        };
    },
    mounted(){
        this.myValue = this.value;
    },
    watch:{
        myValue(val){
            this.$emit("input",val)
        }
    }
    }
</script>

上面的是輸入框子組件

/*
* @property { rules :  {String Object} 表單驗證 一種驗證傳對象 一種以上把對象組成數組 }
* @property { prop :  {String} input的name 傳回的字段名與html中input標簽name值一樣。 }
* @property { placeholder :  {String} 提示語,與html中input標簽placeholder值一樣。 }
* @property { label :  {String} 標簽文本。 }
* @property { v-model :  {String} 語法糖,利用value接值父子組件相互傳值 當前表單填寫的內容  }
* @property { selectdata:  {Array} option中的數據 }
* @version 1.0.0
* @edit: 2018/7/30
*/
<template>
    <el-form-item :label="label" :prop="prop" :rules="rules">
    <el-select v-model="myValue" :placeholder="placeholder" v-on:change="change">
       <el-option v-for="item in selectdata" :key="item.id" :label="item.lable" :value="item.value"></el-option>
    </el-select>
  </el-form-item>
</template>
<script>
    export default {
        props: {
            selectdata: {
                type: Array
            },
            prop: {
                type: String
            },
            placeholder:{
                type: String
            },
            label:{
                type: String
            },
            value:{
                type: String
            },
            rules:[Object,Array]
        },
    data() {
        return {
            myValue:""
        };
    },
    mounted(){
        this.myValue = this.value;
    },
    methods:{
        change(){
            this.$emit("input",this.myValue)
        }
    }
    }
</script>

這個是下拉框子組件

首先是一個語法糖的知識點,父組件屬性中加入v-model子組件需要在props中使用value來接值,然后子組件中用  this.$emit("input",val) 來把值返回父組件,這樣父組件中就可以獲得當前輸入框的內容了。

在輸入框子組件中我們采用的是監聽輸入框中的值的變化,每當輸入的值變化我們都會 this.$emit("input",val)  將值返回父組件,但是在下拉欄中我們同樣用此方法監聽的時候會出現bug

 

我們明明選擇了區域2表單檢測卻給我們報了錯,然后當我們再次選擇的時候就好使了

此時我們做一個假設,表單檢測值事件運行時我們還沒有將已改變的值發給父組件,所以在父組件進行檢測的時候沒有值,那我們不用watch改用methods來傳值會不會變快呢,我們給select綁上change事件?

接下來我們來驗證它

    methods:{
        change(){
            console.log(this.myValue,"aaa")
        }
    },
    watch:{
        myValue(val){
             console.log(this.myValue,"bbb")
            this.$emit("input",val)
        }
    }

我們在子組件中加入這兩句話,來比一比監聽值的變化快還是change事件快

先打印出aaa再打印出bbb,所以change事件比較快,那我們可以試試用change將值傳給父組件,看看表單檢測的時候 this.$emit("input",val) 有沒有運行過。

結果change事件確實在表單檢測之前將值塞了進去,bug解決了。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM