我一直都相信,决定未来的是自信与成长速度,成长的过程中,整理是一个非常重要的环节,接下来是我整理的系统组件开发常用的部分。
本文的主要内容有:
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>
以上是整理的内容。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。