vue項目筆記-封裝組件篇

我一直都相信,決定將來的是自信與成長速度,成長的過程當中,整理是一個很是重要的環節,接下來是我整理的系統組件開發經常使用的部分。css

本文的主要內容有:html

1.table內編輯 
2.高度不固定,顯示隱藏過渡動畫
3.解決vue父組件傳遞props異步數據到子組件的問題

1、vue table內編輯

  • 需求:

    1.table點擊編輯按鈕時,顯示input(此input可修改table裏某一行某一列的內容)、取消按鈕、保存按鈕。
    2.點擊保存按鈕,則保存編輯後的內容,點擊取消則不保存。vue

  • 思路:
    1.點擊編輯時編輯按鈕隱藏,保存和取消顯示。可以使用$set,在每一行數據裏增長一個屬性edit,this.$set(v, 'edit', false);,組件標籤裏用v-show=「scope.row.edit 進行顯示隱藏。$set官方解釋(向響應式對象中添加一個屬性,並確保這個新屬性一樣是響應式的,且觸發視圖更新。它必須用於向響應式對象上添加新屬性)。

    2.編輯因爲input是雙向綁定,輸入的時候就改變了數據,點擊取消時,需恢復原來的數據。需 「拷貝」 一份原來的數據,如取消則使用這個數據。代碼有兩部分,一部分是隻針對一列,名字寫實,理解思路。另外一部分是實際項目開發能用到的,每一列均可編輯,而且名字可變。代碼以下:異步

    (1)理解思路,title列進行可編輯函數

請求table數據
        this.$http.get(this.tableUrl).then(response => {
        let commTable1 =response.data.tableData;
        this.list = commTable1 .map(v => {
             this.$set(v, 'edit', false); 
              v.oldTitle = v.title ; 
              return v
            })
        })
        點擊保存
        save(row) {
          row.edit = false
          row.oldTitle = row.title
        }
       點擊取消
       cancel(row) {
          row.title = row.oldTitle
          row.edit = false
       }

(2)table每一列進行編輯動畫

table請求數據
        this.$http.get(this.tableUrl).then(response => {
         response = response.data;
         let commTable1 =response.tableData;
         this.commTable= commTable1.map(v => {
              for(var obj in v){
                   v[`old${obj}`]=v[obj]
               }
              this.$set(v, 'edit', false);
                   return v
              })
           });
         點擊保存
         save(row) {
              for(var obj in row){
              let str = '';
              if(obj.indexOf('old')>-1){
                  str = obj.replace('old','');
                  row[obj]=row[str];
                }
              }
              row.edit = false
            }
         }
       點擊取消
       cancel(row) {
           let str = '';
            if(obj.indexOf('old')>-1){
               str = obj.replace('old','');
                row[str]=row[obj];
             }
           }
       row.edit = false;
     }

2、高度不固定,上下滑動動畫

無論是vue的過渡動畫,仍是element的過渡動畫,都是須要高度固定,沒法知足需求。接下來是一個大神封裝的一個函數式組件,這個組件只適用於單個內容,若是內容是v-for循環,且高度不固定,我作了一下改裝,使用的是vue 的transition-group。Vue.JS實現垂直方向展開、收縮不定高度模塊的JS組件this

const elTransition = '0.3s height ease-in-out, 0.3s padding-top ease-in-out, 0.3s padding-bottom ease-in-out'
    const Transition = {
     'before-enter' (el) {
            el.style.transition = elTransition
            if (!el.dataset) el.dataset = {}
    
            el.dataset.oldPaddingTop = el.style.paddingTop
            el.dataset.oldPaddingBottom = el.style.paddingBottom
    
            el.style.height = 0
            el.style.paddingTop = 0
            el.style.paddingBottom = 0
    },
    
     'enter' (el) {
            el.dataset.oldOverflow = el.style.overflow
            if (el.scrollHeight !== 0) {
            el.style.height = el.scrollHeight + 'px'
            el.style.paddingTop = el.dataset.oldPaddingTop
            el.style.paddingBottom = el.dataset.oldPaddingBottom
            } else {
            el.style.height = ''
            el.style.paddingTop = el.dataset.oldPaddingTop
            el.style.paddingBottom = el.dataset.oldPaddingBottom
            }
    
            el.style.overflow = 'hidden'
    },
    
     'after-enter' (el) {
            el.style.transition = ''
            el.style.height = ''
            el.style.overflow = el.dataset.oldOverflow
        },
    
     'before-leave' (el) {
            if (!el.dataset) el.dataset = {}
            el.dataset.oldPaddingTop = el.style.paddingTop
            el.dataset.oldPaddingBottom = el.style.paddingBottom
            el.dataset.oldOverflow = el.style.overflow
    
            el.style.height = el.scrollHeight + 'px'
            el.style.overflow = 'hidden'
        },
    
     'leave' (el) {
            if (el.scrollHeight !== 0) {
            el.style.transition = elTransition
            el.style.height = 0
            el.style.paddingTop = 0
            el.style.paddingBottom = 0
        }
      },
    
     'after-leave' (el) {
            el.style.transition = ''
            el.style.height = ''
            el.style.overflow = el.dataset.oldOverflow
            el.style.paddingTop = el.dataset.oldPaddingTop
            el.style.paddingBottom = el.dataset.oldPaddingBottom
        }
    }
    
    export default {
     name: 'VerticalToggle',
     functional: true,
        render (h, { children }) {
            const data = {
                 on: Transition
            }
            return h('transition', data, children)
        }
    }

組件中可這樣使用.net

import verticalToggle from './vertical-toggle.js';
 <vertical-toggle> 
    <div style="background-color:red;" v-show="dialogVisible1">123</div>
  </vertical-toggle>

以上適用於單個內容,若是內容是v-for循環,且高度不固定,使用的是vue 的transition-group
**vue組件:**
<transition-group name="fade2" v-on:enter="enter" v-on:before-leave="beforeLeave" v-on:leave="leave">
         <div v-for="(item2,i2) in item.children" :key="i2" class="fade2">
            {{item2.name}}
         </div>
    <transition-group>

方法:雙向綁定

enter(el){
        el.style.height = el.scrollHeight + 'px';
        el.style.paddingTop = el.dataset.oldPaddingTop
        el.style.paddingBottom = el.dataset.oldPaddingBottom
    },
    beforeLeave(el){
       el.dataset.oldPaddingTop = el.style.paddingTop
       el.dataset.oldPaddingBottom = el.style.paddingBottom
       el.dataset.oldOverflow = el.style.overflow
       el.style.height = el.scrollHeight + 'px'   
       el.style.overflow = 'hidden'
    },
    leave(el){
       el.style.height = 0
       el.style.paddingTop = 0
       el.style.paddingBottom = 0
      },

}
css:code

.fade2-enter-active,.fade2-leave-active {
         transition: all .5s;
    }
     .fade-enter,.fade2-enter,.fade-leave-to,.fade2-leave-to{
         height: 0px;
    }

若是有需求是還要在顯示的組件裏添加內容,則還需下面代碼,由於this.$refs不支持響應,因此就在updated生命週期裏寫了。

updated() {
         if(this.flog1){
         for(let obj of this.list){
             let index=this.list.indexOf(obj)
             this.$refs.fade[index].style.height="auto";
         }
         this.flog2=false;
        }
      },

3、解決vue父組件傳遞props異步數據到子組件的問題

data爲異步獲取的數據,想傳遞給子組件使用

<template>
    <div> 
        父組件
        <child :child-data="data"></child>
    </div>
</template>
<script>
    import child from './child'
    export default {
    data: () => ({
        data: ''
     }),
    components: {
        child 
    },
    mounted () {
        // setTimeout模擬異步數據
        setTimeout(() => {
            this.data= '異步的數據'
        }, 2000)
    }
    }
</script>

子組件child.vue

<template>
    <div>
        子組件{{childData}}
    </div>
</template>
<script>
export default {
props: {
    childData:{
        type:String
    }
},
created () {
    console.log(this.childData) // 空值
},
}
</script>

子組件的html中的{{childData}}的值會隨着父組件的值而改變,可是created裏面的卻不會發生改變(生命週期問題)
解決辦法:我這裏給出我常常用的兩種經常使用的解決方案,還有其餘的解決方案 https://www.jb51.net/article/...
1.在父組件使用v-if 方法

<template>
    <div> 
        父組件
        <child :child-data="data" v-if="flag"></child>
    </div>
</template>
<script>
    import child from './child'
    export default {
    data: () => ({
        data: '',
        flag: false
     }),
    components: {
        child 
    },
    mounted () {
        // setTimeout模擬異步數據
        setTimeout(() => {
            this.data= '異步的數據'
        }, 2000)
        this.flag = true
    }
    }
</script>

2.子組件使用watch來監聽父組件改變的prop,使用methods來代替created,既然created只會執行一次,可是又想監聽改變的值作其餘事情的話,可以使用這個方法。

<template>
    <div>
        子組件{{childData}}
    </div>
</template>
<script>
export default {
props: {
    childData:{
        type:String
    }
},
created () {
    console.log(this.childData) // 空值
},
watch: {
    childData: (val) {
        this.childData=val;
        this.updata();
    }
}
methods: {
    updata () { 
        console.log(this.childData);
    }
}
</script>

以上是整理的內容。

相關文章
相關標籤/搜索