6

我一直都相信,决定未来的是自信与成长速度,成长的过程中,整理是一个非常重要的环节,接下来是我整理的系统组件开发常用的部分。

本文的主要内容有:

1.table内编辑 
2.高度不固定,显示隐藏过渡动画
3.解决vue父组件传递props异步数据到子组件的问题

一、vue table内编辑

  • 需求:

    1.table点击编辑按钮时,显示input(此input可修改table里某一行某一列的内容)、取消按钮、保存按钮。
    2.点击保存按钮,则保存编辑后的内容,点击取消则不保存。

  • 思路:
    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;
     }

二、高度不固定,上下滑动动画

不管是vue的过渡动画,还是element的过渡动画,都是需要高度固定,无法满足需求。接下来是一个大神封装的一个函数式组件,这个组件只适用于单个内容,如果内容是v-for循环,且高度不固定,我做了一下改装,使用的是vue 的transition-group。Vue.JS实现垂直方向展开、收缩不定高度模块的JS组件

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)
        }
    }

组件中可这样使用

 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:

     .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;
        }
      },

三、解决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>



以上是整理的内容。


你你
43 声望9 粉丝

自信,成长,一枚前端媛。