簡體   English   中英

Vue.js 轉換從列表中更改選定元素

[英]Vue.js transition on changing selected element from a list

我有一個打開“編輯配置文件”屏幕的配置文件列表。 該屏幕從左側滑入。 當我選擇一個配置文件時,如果已經選擇了一個屏幕,我希望它先滑出,更改選定的配置文件數據,然后再滑入。

現在發生的情況是:當我第一次選擇一個元素時,屏幕會滑入。當我更改所選元素時,屏幕會停留並且不會滑出和滑入。

這是一個 gif,顯示它現在的行為:

在此處輸入圖像描述

我的代碼是:

Vue方法:

editProfile: function (index){
    // this.editingProfile = false;
    this.setProfile(index);
    this.editingProfile = true;

}

html視圖:

        <transition name="fade" mode="out-in">
            <div v-if="editingProfile" id="edit-profile">
                <input placeholder="Profile Name" v-model="synced.profiles[synced.selectedProfile].name">
            </div>
        </transition>

CSS:

.fade-enter-active, .fade-leave-active {
   transition: all .2s;
   /* transform:translateX(0); */
  }
  .fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {
    opacity: 0;
    transform:translateX(-100%);
  }

更改配置文件時,如何使其正確滑出然后重新滑入?

我認為我的評論不正確。 你可以做到這一點的一種方法是利用:keyv-if ,這樣如果你選擇了一個面板,你就可以告訴 Vue 渲染一個面板,然后以這種方式在面板之間進行轉換。 那時你不需要有一個transition-group

問題是:key告訴 Vue 一切都變了。 如果您不使用它,Vue 會嘗試盡可能多地回收。 請參閱文檔: 元素之間的轉換

在具有相同標簽名稱的元素之間切換時,您必須通過賦予它們唯一的key屬性來告訴 Vue 它們是不同的元素。 否則,Vue 的編譯器為了效率只會替換元素的內容。 即使在技術上沒有必要,<transition>組件中始終鍵入多個項目也被認為是一種好的做法

考慮下面的最小示例:

 const panels = [{ title: "Hello" }, { title: "World" }, { title: "Foo" }, { title: "Bar" } ]; const app = new Vue({ el: "#app", data() { return { panels, activePanel: null }; }, computed: { titles() { return this.panels.map(panel => panel.title); } }, methods: { handleTitleClick(idx) { if (this.activePanel === idx) { this.activePanel = null; return; } this.activePanel = idx; } } });
 body { margin: 0; padding: 0; } #app { display: flex; align-items: stretch; height: 100vh; } #panel-set { flex: 1 0 70%; display: flex; } #side-panel { flex: 1 0 30%; } .panel { padding: 1em; flex: 1 0; background-color: rgba(0, 0, 0, 0.2); } .slide-fade-enter-active, .slide-fade-leave-active { transition: transform 500ms ease-in-out; } .slide-fade-enter, .slide-fade-leave-to { transform: translateX(-100%); }
 <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.min.js"></script> <div id="app"> <div id="panel-set"> <transition name="slide-fade" mode="out-in"> <div class="panel" v-if="activePanel !== null" :key="activePanel"> <h2>{{panels[activePanel].title}}</h2> <p>Lorem ipsum</p> </div> </transition> </div> <div id="side-panel"> <ul> <li v-for="(title, idx) in titles" @click="handleTitleClick(idx)">{{title}}</li> </ul> </div> </div>

根本原因是v-if="editingProfile"在您的代碼中顯示一個配置文件后始終為真。

一種解決方案是先將其設置為 false,然后在this.$nextTick中再次將其設置為 true。 但是您必須將this.editingProfile = true放在一個setTimeout和延遲時間 = 轉換時間中。 否則, slide out效果將被覆蓋。

就像下面的演示:

 new Vue({ el: '#emit-example-simple', data() { return { editingProfile: false, synced : { profiles: [{'name':'A'}, {'name':'B'}, {'name':'C'}], selectedProfile: 0 }, } }, methods: { editProfile: function (index){ this.editingProfile = !this.editingProfile this.$nextTick(() => { setTimeout(()=> { this.synced.selectedProfile = index this.editingProfile = true }, 1200) }) } } })
 .fade-enter-active, .fade-leave-active { transition: all 1.2s; /* transform:translateX(0); */ } .fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ { opacity: 0; transform:translateX(-100%); border: 1px solid white; }
 <script src="https://unpkg.com/vue/dist/vue.js"></script> <div id="emit-example-simple"> <button @click="editProfile(0)">Profile 1</button> <button @click="editProfile(1)">Profile 2</button> <button @click="editProfile(2)">Profile 3</button> <transition name="fade" mode="out-in"> <div v-if="editingProfile" id="edit-profile"> <input style="border: 5px solid red;" placeholder="Profile Name" v-model="synced.profiles[synced.selectedProfile].name"> </div> </transition> </div>

或者您可以考慮使用如下簡單演示的Group transition

 new Vue({ el: '#emit-example-simple', data() { return { editingProfile: false, profileContainers: [true, false], synced : { profiles: [{'name':'A'}, {'name':'B'}, {'name':'C'}], selectedProfile: 0 }, } }, methods: { editProfile: function (index){ this.synced.selectedProfile = index this.profileContainers = this.profileContainers.map((x)=>!x) } } })
 .list-items-enter-active { transition: all 1.2s; } .list-items-leave-active { transition: all 1.2s; } .list-items-enter, .list-items-leave-to /* .fade-leave-active below version 2.1.8 */ { opacity: 0; transform:translateX(-100%); border: 1px solid white; } .list-item { display: inline-block; border: 6px solid red; }
 <script src="https://unpkg.com/vue/dist/vue.js"></script> <div id="emit-example-simple"> <button @click="editProfile(0)">Profile 1</button> <button @click="editProfile(1)">Profile 2</button> <button @click="editProfile(2)">Profile 3</button> <transition-group name="list-items" tag="p"> <div v-for="(item, index) in profileContainers" :key="index" v-if="item"> <input style="border: 5px solid red;" placeholder="Profile Name" v-model="synced.profiles[synced.selectedProfile].name"> </div> </transition-group> </div>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM