代码之家  ›  专栏  ›  技术社区  ›  Svinjica

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

  •  2
  • Svinjica  · 技术社区  · 6 年前

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

    在我的boostrap模板中,我试图添加一个基于selected选项的下拉列表。所以,我在第一个select选项中添加了change事件。所以,如果我选择 '第一项' 然后更改类并在行中添加下拉列表,否则将其隐藏。

    像这样的:

    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 在这里,您可以看到第三个选择下拉列表的平滑幻灯片过渡,但如果我更改了“选择自” “学习Vue” 对于其他内容,第三个下拉列表将其隐藏,但也没有任何动画。

    你也可以在下面的片段中看到它!

    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>

    您可以看到前两个下拉列表的change类,但没有任何转换。所以,可以为前两个下拉列表添加一些过渡吗?

    编辑:


    如您所见,我正在将类从*form group col-md-6*更改为*form group col-md-4*,我想知道从md-6到md-4的转换是否可能更平滑一些。

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

    2 回复  |  直到 6 年前
        1
  •  1
  •   Sphinx    6 年前

    在代码中,直接从 col-md-4 col-md-6 在里面 selectTodo . 会导致前两个 <div> 全宽 在第三个div完成动画之前的行。

    解决方案 ,使用 this.$nextTick setTimeout .

    当添加第三个div时,delay execute在前两个div之前显示第三个div <分区> 完成他们的动画。

    当移除第三个div时,延迟应用 列md-6 到前两个 <分区> 在第三个之前 <分区> 完成动画。

    下面是 一个样品 : ( 附言 :我在这里使用了转换组,因为它对于 Reusable Transitions )

    警告 :请整页测试下面的演示,否则引导程序会将其视为外部小屏幕(放置每个 <分区> 在每一行),虽然我认为小屏幕的效果仍然不错。

    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>
        2
  •  1
  •   Rawan Bekheet    6 年前

    我不知道在Vue中是否有一种特定的方法,但是使用CSS魔术可以很容易地实现您想要的。事实上很简单,你要做的就是在你不断变化的div中添加一个类,比如说类名是 transition 在CSS中定义 过渡 样式如下:

    .transition {
         transition: all 0.25s linear;
    }
    

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

    注意,您可以更改计时功能 linear 还有时间 0.25s 为了满足您的需要,您可以阅读更多关于CSS转换和效果的内容 here