如何使用 Vue.js 在选择选项上使用转换

Posted

技术标签:

【中文标题】如何使用 Vue.js 在选择选项上使用转换【英文标题】:How to use transitions on select option using Vue.js 【发布时间】:2019-01-14 03:40:34 【问题描述】:

我有一个关于 Vue.js 转换的快速问题。

在我的 boostrap 模板中,我尝试根据所选选项再添加一个选择选项下拉菜单。所以,我在第一个选择选项上添加了更改事件。所以,如果我选择 'first item' 然后更改类并在行中添加下拉菜单,否则将其隐藏。

类似这样的:

selectTodo: function(e) 
  let selectValue = e.target.options[e.target.selectedIndex].text

  if (selectValue === 'Learn Vue') 
    this.styleObject.display = 'unset';
    this.col_md = 'form-group col-md-4';
    this.showCropStageList = true;
  
  else 
    this.showCropStageList = false;
    this.styleObject.display = 'none';
    this.col_md = 'form-group col-md-6';
    this.cropStageList = null;
  

我设法做到了,但我希望在前两个下拉菜单中更多平滑过渡。

我已经设法设置了一些 fiddle,您可以在其中看到第三个选择下拉列表的平滑滑动过渡,但是如果我将选择从 “Learn Vue” 更改为其他内容,则第三个下拉列表隐藏它,但也没有任何动画。

你也可以在下面的 sn-p 中看到它!

new Vue(
  el: "#app",
  data: 
    todos: [
       id:1 ,text: "Learn javascript", done: false ,
       id:2 ,text: "Learn Vue", done: false ,
       id:3 ,text: "Play around in JSFiddle", done: true ,
       id:4 ,text: "Build something awesome", done: true 
    ],
    col_md: 'form-group col-md-6',
    styleObject: 
          display: 'none'
        ,
    showCropStageList: false,
  ,
  methods: 
  	toggle: function(todo)
    	todo.done = !todo.done
    ,
    selectTodo: function(e) 
    let selectValue = e.target.options[e.target.selectedIndex].text
    
        if (selectValue === 'Learn JavaScript') 
          
          this.styleObject.display = 'unset';
          this.col_md = 'form-group col-md-4';
          this.showCropStageList = true;
        
        else 

          this.showCropStageList = false;
          this.styleObject.display = 'none';
          this.col_md = 'form-group col-md-6';
          this.cropStageList = null;
          
        
    
  
)
body 
  background: #20262E;
  padding: 20px;
  font-family: Helvetica;


.fade-enter 
  opacity: 0;


.fade-enter-active 
  transition: opacity 1s;


.fade-leave 

.fade-leave-active 
  transition: opacity 1s;
  opacity: 0;


#app 
  background: #fff;
  border-radius: 4px;
  padding: 20px;
  transition: all 0.2s;


li 
  margin: 8px 0;


h2 
  font-weight: bold;
  margin-bottom: 15px;


del 
  color: rgba(0, 0, 0, 0.3);
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div class="container">
  <!-- Content here -->
  <div id="app">
    <div class="form-row">
      <transition name="fade" appear>
        <div v-bind:class=col_md>
          <label for="cropType" class="col-form-label-sm font-weight-bold">Select Learn Javascript </label>
          <select class="form-control" v-on:change="selectTodo" id="cropType" v-model="pickedCropType" @change="getCropsByType()">
              <option v-for="(todo, index) in todos" :key="index" :value="todo.id" >
                todo.text
              </option>
            </select>
        </div>
      </transition>
      <div v-bind:class=col_md>
        <label for="cropCulture" class="col-form-label-sm font-weight-bold">2. Second</label>
        <select class="form-control" id="cropCulture">
     <option v-for="(todo, index) in todos" :key="index" :value="todo.id" >
                todo.text
              </option>
            </select>
      </div>
      <transition 
      enter-active-class="animated fadeInLeft"
      leave-active-class="animated fadeOutLeft"
      >
        <div class="form-group col-md-4" v-if="showCropStageList" v-bind:class="styleObject ">
          <label for="cropStage" class="col-form-label-sm font-weight-bold">3. Third</label>
          <select class="form-control" id="cropStage">
                <option v-for="(todo, index) in todos" :key="index" :value="todo.id" >
                todo.text
              </option>
              </select>
        </div>
      </transition>
    </div>
  </div>
</div>

您可以看到前两个下拉菜单的更改类别,但没有任何转换。那么,是否可以为前两个下拉菜单添加一些过渡?

编辑:


如您所见,我正在将课程从 *form-group col-md-6* 更改为 *form-group col-md-4*,我想知道是否有可能从 md 过渡-6 到 md-4 可以更平滑一些。

https://jsfiddle.net/Loque/akt0su98/

【问题讨论】:

this fiddle 呢? 关闭,我想是否可以在同一行中创建(根据要求的规范)。但绝对是小提琴的好工作 【参考方案1】:

在您的代码中,您直接将selectTodo 中的类从col-md-4 更新为col-md-6。这将导致前两个 &lt;div&gt; 在第三个 div 完成其动画之前占据行的 full width

解决方案,使用this.$nextTicksetTimeout

当添加第三个 div 时,延迟执行在前两个 &lt;div&gt; 完成动画之前显示第三个 div。

当删除第三个 div 时,延迟将 col-md-6 应用到前两个 &lt;div&gt;,然后第三个 &lt;div&gt; 完成其动画。

下面是一个示例:(PS:我在这里使用了transition-group,因为它更适合Reusable Transitions)

警告:请在完整页面下测试下面的演示,否则引导程序会将其视为超小屏幕(每行放置每个&lt;div&gt;),虽然我认为小屏幕的效果是还是不错的。

new Vue(
  el: "#app",
  data: 
    todos: [
       id:1 ,text: "Learn JavaScript", done: false ,
       id:2 ,text: "Learn Vue", done: false ,
       id:3 ,text: "Play around in JSFiddle", done: true ,
       id:4 ,text: "Build something awesome", done: true 
    ],
    col_md: 'form-group col-md-6',
    styleObject: 
          display: 'none'
        ,
    showCropStageList: false,
    pickedCropType: ''
  ,
  methods: 
  	getCropsByType: function () ,
  	toggle: function(todo)
    	todo.done = !todo.done
    ,
    selectTodo: function(e) 
    	let selectValue = e.target.options[e.target.selectedIndex].text
      if (selectValue === 'Learn Vue') 
        this.col_md = 'form-group col-md-4';
        this.$nextTick(() =>  //delay display the third div before first two div finish animation
        	setTimeout(()=>
            this.styleObject.display = 'unset';
            this.showCropStageList = true;
          , 500)

        )
        
      
      else 

        this.showCropStageList = false;
        this.styleObject.display = 'none';
        this.$nextTick(() =>  //delay apply `md-6` to first two div before 3rd div finish animation
        	setTimeout(()=>
          	this.col_md = 'form-group col-md-6';
          , 1000)
        	
        )
        
        this.cropStageList = null;

      
    
  
)
.sample 
  background: #fff;
  border-radius: 4px;
  padding: 20px;
  transition: all 0.2s;


.fade-item 
  transition: all 0.5s;
  display:inline-block;


.fade-enter 
  opacity: 0;
  transform: translateX(-130px);



.fade-enter-active 
  transition: all 1.5s;


.fade-leave-to 
  transform: translateX(130px);
  opacity: 0;
  flex: 0 0 20%;


.fade-leave-active 
  transition: all 1s;


#app 
  background: #20262E;
  padding: 20px;
  font-family: Helvetica;


li 
  margin: 8px 0;


h2 
  font-weight: bold;
  margin-bottom: 15px;


del 
  color: rgba(0, 0, 0, 0.3);
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>

<!-- Content here -->
<div id="app">
  <div class="container">
    <div class="sample">
      <transition-group name="fade" tag="div" class="form-row">
        <div v-bind:class="col_md" :key="1" class="fade-item">
          <label for="cropType" class="col-form-label-sm font-weight-bold">Select Learn Javascript </label>
          <select class="form-control" v-on:change="selectTodo" id="cropType" v-model="pickedCropType" @change="getCropsByType()">
              <option v-for="(todo, index) in todos" :key="index" :value="todo.id" >
                todo.text
              </option>
            </select>
        </div>
      <div v-bind:class="col_md" :key="2" class="fade-item">
        <label for="cropCulture" class="col-form-label-sm font-weight-bold">2. Second</label>
        <select class="form-control" id="cropCulture">
     <option v-for="(todo, index) in todos" :key="index" :value="todo.id" >
                todo.text
              </option>
            </select>
      </div>
        <div class="form-group col-md-4 fade-item" v-if="showCropStageList" v-bind:class="styleObject " :key="3">
          <label for="cropStage" class="col-form-label-sm font-weight-bold">3. Third</label>
          <select class="form-control" id="cropStage">
                <option v-for="(todo, index) in todos" :key="index" :value="todo.id" >
                todo.text
              </option>
              </select>
        </div>
      </transition-group>
    </div>
  </div>

</div>

【讨论】:

我想知道 :key 在 div 元素中,你能解释一下它的用途吗? @Svinjica,您可以查看Vue Guide: Key,Vue Guide: transition between elements,然后在&lt;transition-group&gt;(Vue Guide: List Transition)中需要密钥。 谢谢,我会调查的:) @Svinjica 有时我们会使用:key 像this demo 一样强制重新挂载,或者像评论中的这个demo fiddle 来实现强制进入/离开转换(类似于v-if =false,然后 v-if=true)。【参考方案2】:

我不知道在 Vue 中是否有特定的方法,但是你想要的可以使用一些 CSS 魔法轻松实现。事实上,这很简单,你要做的就是在你不断变化的 div 中添加一个类,例如类名是 transition 并且在你的 CSS 中定义 transition 样式如下:

.transition 
     transition: all 0.25s linear;

你可以找到更新的小提琴here

请注意,您可以更改计时功能linear 和时间0.25s 以满足您的需求,您可以阅读更多关于CSS 过渡和效果here

【讨论】:

你在正确的轨道上,但我仍然想知道是否可以在同一行中创建(之前的小提琴以某种方式接近最终解决方案)

以上是关于如何使用 Vue.js 在选择选项上使用转换的主要内容,如果未能解决你的问题,请参考以下文章

如何在值输入文本上显示选择选项的值? (vue.js 2)

如何在 Vue JS 中连接按钮并使用其选项进行选择

如何在 vue js 中使用 html 的选择选项仅显示该类别的服务?

Vue.js:如何使转换组只触发一次?

(Vue.js)如何使用数据中数值数组中的选项标记填充选择标记?

如何在选项/选择标签循环之外的按钮中使用 Vue.js 中下拉列表的选定 ID