向上滑动动画后移除元素,反之,在Vue 3.X中向下滑动前安装元素

umuewwlo  于 2023-02-09  发布在  Vue.js
关注(0)|答案(2)|浏览(100)

bounty将在3天后过期。回答此问题可获得+50的声望奖励。Takeshi Tokugawa YD正在寻找规范答案

vue-slide-up-down库仅使用预安装的元素。

***向下滑动情况:**动画开始前不会挂载元素
***向上滑动情况:**动画结束后不会卸载元素

它只处理元素的height和hidden属性。
现在,如果我没有什么目标元素被挂载时,它不显示?

***向下滑动情况:**在动画开始之前,我希望安装元素
***向上滑动情况:**动画完成后,我希望元素被卸载,而不仅仅是隐藏

如果我们尝试

<slide-up-down 
  v-if="active"
  :active="active" 
>
  Only show this if "active” is true
</slide-up-down>

它将不是动画,因为:

***向下滑动情况:**动画在安装元素之前开始
***向上滑动情况:**元素将在动画开始前卸载

afdcj2ne

afdcj2ne1#

您需要一个单独的变量来控制组件是否呈现(我在下面将其命名为isRendered)。
计算setter + getter(以下命名为rendered),将activeisRendered设置为当前值,但顺序不同:

  • 当设置为true时:首先打开isRendered,然后在$nextTick中将active设置为true,这样动画就会播放
  • 当设置为false时:首先将active设置为false,等待动画完成,然后将isRendered设置为false
    • 版本2演示**:
Vue.component("slide-up-down", VueSlideUpDown)
new Vue({
  el: "#app",
  data: () => ({
    isRendered: false,
    active: false,
    duration: 500
  }),
  computed: {
    rendered: {
      get() {
        return this.isRendered
      },
      set(val) {
        if (val) {
          this.isRendered = val
          this.$nextTick(() => {
            this.active = val
          })
        } else {
          this.active = val
          setTimeout(() => {
            this.isRendered = val
          }, this.duration)
        }
      }
    }
  }
})
.wrap {
  padding: 1rem;
  border: 1px solid #ccc;
  background-color: #f5f5f5;
}

button {
  margin-bottom: 1rem;
}
<script src="https://unpkg.com/vue@2.7.14/dist/vue.min.js"></script>
<script src="https://unpkg.com/vue-slide-up-down@2.0.0/dist/vue-slide-up-down.umd.js"></script>
<div id="app">
  <button @click="rendered = !rendered">Toggle</button>
  <slide-up-down v-if="isRendered" v-bind="{ active, duration }">
    <div class="wrap">
      Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aut, consequatur
      ut magnam, quos possimus, velit quam mollitia voluptate adipisci
      reiciendis sapiente accusamus ullam ab voluptatem laborum non! Accusamus,
      ullam, voluptatum.
    </div>
  </slide-up-down>
</div>
    • 版本3演示**:

一个一个三个一个一个一个一个一个四个一个一个一个一个一个五个一个
如果您要多次执行此操作,您可能希望将其作为独立组件提取。

<conditional-slide :rendered="condition" :duration="1000">
  <div>content you want rendered based on `this.condition` (boolean)</div>
</conditional-slide>

由于现在的更改来自rendered属性,因此可以将计算出的setter代码移动到watch中:
Vue 2中:

<template>
  <div>
    <slide-up-down
      v-if="isRendered"
      v-bind="{ active, duration }"
    >
      <slot />
    </slide-up-down>
  </div>
</template>
<script>
import SlideUpDown from 'vue-slide-up-down'
export default {
  components: { SlideUpDown },
  props: {
    rendered: {
      type: Boolean,
      default: false
    },
    duration: {
      type: Number,
      default: 500
    }
  },
  data: () => ({
    active: false,
    isRendered: false
  }),
  watch: {
    rendered: {
      handler(val) {
        if (val) {
          this.isRendered = val
          this.$nextTick(() => {
            this.active = val
          })
        } else {
          this.active = val
          setTimeout(() => {
            this.isRendered = val
          }, this.duration)
        }
      },
      immediate: true
    }
  }
}
</script>

沙盒。

  • 请随意添加更多的 prop ,并将它们传递给内部的<slide-up-down />
  • 注意vue2和vue3版本使用相同插件的不同分支(注意导入)并且具有稍微不同的模板语法。
vngu2lb8

vngu2lb82#

如果我没猜错,就有解决办法。
使用v-show代替v-if
我使用了vue-slide-up-down站点中的原始示例来演示这种行为。
如果您使用"v-show"并同时切换v-slide-组件,那么当您隐藏的内容再次显示时,您将获得幻灯片效果。

Vue.component("slide-up-down", VueSlideUpDown);
var vm = new Vue({
  el: '#app',
  data: () => ({
      active: false,
      show: true,
      contentLength: 2,
      showOptions: false,
      useHidden: true,
      timing: "",
      duration: 500
   }),
   methods: {
      toggle() {
        this.active = !this.active;
      },
      toggleShow() {
        this.show = !this.show;
        this.active = this.show;
      }
    }
})
* {
  margin: 0;
  padding: 0;
  font-size: 1em;
  box-sizing: border-box;
}
body {
  font-family: sans-serif;
  padding: 20px;
  line-height: 1.5em;
}
#app {
  margin: 0 auto;
  max-width: 700px;
}
.Button {
  display: block;
  width: 100%;
  margin-top: 10px;
  margin-left: auto;
  margin-right: auto;
  padding: 1em;
  border: 0;
  background-color: gray;
  cursor: pointer;
}
.Button.small {
  width: auto;
  font-size: 0.8em;
  padding: 0.5em 1em;
  background-color: lightgray;
  margin: 0;
}
.AccordionWrapper {
  background-color: darkred;
}
.AccordionWrapper.easeInOutCirc {
  transition-timing-function: cubic-bezier(0.785, 0.135, 0.15, 0.86);
}
.AccordionWrapper.customTiming {
  transition-timing-function: cubic-bezier(0.195, 1.65, 0.435, -0.6);
}
.Accordion {
  display: block;
  width: 96%;
  margin-left: auto;
  margin-right: auto;
  padding: 1em;
  border: 0;
  background-color: lightgray;
}
.Accordion p,
.Accordion hr {
  margin-bottom: 10px;
}
.Accordion p:last-child {
  margin-bottom: 0;
}
<div id="app">  
  <div v-show="show">
    <button @click="toggle" class="Button">Toggle Content</button>
     <slide-up-down class="AccordionWrapper" :active="active" :use-hidden="this.useHidden" :class="this.timing" :duration="this.duration"> 
      <div class="Accordion">
        <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aut, consequatur ut magnam, quos possimus, velit quam mollitia voluptate adipisci reiciendis sapiente accusamus ullam ab voluptatem laborum non! Accusamus, ullam, voluptatum.</p>
      </div>
    </slide-up-down>
    </div>
   <button class="Button" @click="toggleShow">Toggle if elements exists</button>
</div>
<script src="https://unpkg.com/vue@2.7.14/dist/vue.js"></script>
<script src="https://unpkg.com/vue-slide-up-down@2.0.0/dist/vue-slide-up-down.umd.js"></script>

相关问题