最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Vue 不定高展開動(dòng)效原理詳解

 更新時(shí)間:2022年06月20日 10:33:05   作者:kzkz  
本文主要介紹了Vue不定高展開動(dòng)效原理詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

使用場(chǎng)景

在大多數(shù) APP 中,都有問(wèn)答模塊,類似于下面這種(bilibili 為例):

問(wèn)答模塊的靜態(tài)頁(yè)面開發(fā)并不復(fù)雜,也沒(méi)有特殊的交互。唯一有一點(diǎn)難度應(yīng)該是回答部分的展開特效。

  • 展開時(shí),需要從上往下將回答部分的 div 慢慢撐開,上面的箭頭也要有旋轉(zhuǎn)的特效。
  • 收回時(shí),需要從下往上將回答部分的 div 慢慢縮小,上面的箭頭也要有旋轉(zhuǎn)的特效。

對(duì)于一般的展開、隱藏特效,只需要在對(duì)應(yīng)元素的 height 上面增加過(guò)渡效果即可。但問(wèn)題是: 不知道對(duì)應(yīng)的 div 的高度,其高度是內(nèi)部的元素自動(dòng)撐開的,此時(shí)直接在 height 屬性上面添加過(guò)渡效果會(huì)失效(后面會(huì)說(shuō)明原因)。

對(duì)于箭頭的旋轉(zhuǎn),則只需要在箭頭元素的 transform 上面增加過(guò)渡效果,然后讓其旋轉(zhuǎn) 180 度(rotateZ(180deg))即可,這個(gè)比較好實(shí)現(xiàn)。

背景

今天做需求時(shí),正好需要做這種特效。也就是上面的第一張圖。先介紹一下列表的數(shù)據(jù)結(jié)構(gòu)和其 DOM 結(jié)構(gòu)。

列表數(shù)據(jù)結(jié)構(gòu)如下:

// Item 表示問(wèn)答的每一項(xiàng)
interface Item {
  Q: string;  // 問(wèn)題
  A: string;  // 回答
  show: boolean;  // 是否展示
}

// List 表示問(wèn)答列表
type List = Item[];

項(xiàng)目中并未使用 TypeScript,這里用 interface 是為了方便理解。

DOM 結(jié)構(gòu)(Vue 版本)如下:

<div class="qa panel">
  <div class="qa__title">
    常見(jiàn)問(wèn)題
  </div>
  <div class="list-qa">
    <div
      v-for="(item, ind) in qaList"
      :key="ind"
      class="list-qa__item"
    >
      <div class="list-qa__question">
        <span>{{ item.Q }}</span>
        <span class="list-qa__question__arrow" />
      </div>
      <span class="list-qa__answer">
        {{ item.A }}
      </span>
    </div>
  </div>
</div>

上面的結(jié)構(gòu)簡(jiǎn)化了一些交互邏輯和展示邏輯,默認(rèn)問(wèn)答列表的每一項(xiàng)都會(huì)展示。最外層包裹了一層 div,上面是標(biāo)題,下面是問(wèn)答列表,問(wèn)答列表的每一項(xiàng)包括問(wèn)題、箭頭 icon 和答案。

實(shí)現(xiàn)

因?yàn)轫?xiàng)目使用的框架是 Vue,所以以 Vue 為例,來(lái)分析一下如何實(shí)現(xiàn)它,以及其實(shí)現(xiàn)的原理。

回答是否展示,可以用一個(gè)變量控制,這里是 item 的 show 屬性。使用 v-show 實(shí)現(xiàn),因?yàn)橛脩艨赡軙?huì)多次點(diǎn)擊箭頭,導(dǎo)致回答頻繁地展示或隱藏。

<div
  v-for="(item, ind) in list"
  :key="ind"
  class="list-item"
>
  <!-- 。。。省略不相關(guān)元素。。。 -->
  <span
    v-show="item.show"
    class="list-answer"
  >
    {{ item.A }}
  </span>
</div>

transition 組件

在 Vue 中,可以使用 transition 組件來(lái)為元素添加動(dòng)態(tài)效果。transition 組件讓我們可以為使用條件渲染(v-if、v-show)的元素添加進(jìn)入、離開時(shí)的過(guò)渡效果。

<div id="demo">
  <button v-on:click="show = !show">
    Toggle
  </button>
  <transition name="fade">
    <p v-if="show">hello</p>
  </transition>
</div>
.fade-enter-active, .fade-leave-active {
  transition: opacity .5s;
}
.fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {
  opacity: 0;
}

這樣在 name 為 fade 的 transition 組件包裹的 p 標(biāo)簽展示和隱藏時(shí),會(huì)有一個(gè) 0.5s 的淡入淡出效果。

過(guò)渡效果原理

在展示時(shí),p 標(biāo)簽的 opacity(透明度)會(huì)從 0(.fade-enter 類選擇器中設(shè)定的值)開始增加,經(jīng)過(guò) 0.5s 之后,增加至 opacity: 1(元素默認(rèn)的透明度 opacity 為 1)。

在隱藏時(shí),p 標(biāo)簽的 opacity(透明度)會(huì)從 1 開始減少,經(jīng)過(guò) 0.5s 之后,減少至 opacity: 0.fade-leave-to 類選擇器中設(shè)定的值)。

這樣就實(shí)現(xiàn)了淡入淡出效果。

同樣的,如果我們想讓一個(gè)元素展示時(shí)高度從 0 開始增加,經(jīng)過(guò)某一個(gè)時(shí)間,達(dá)到具體的值;隱藏時(shí)高度從該具體值開始減少,經(jīng)過(guò)某一個(gè)時(shí)間,達(dá)到 0。這樣就能實(shí)現(xiàn)我們前面需要的效果。

我們可以用 css transition 為某一個(gè)元素設(shè)置過(guò)渡效果,過(guò)渡效果作用在這個(gè)元素的某個(gè)屬性上、過(guò)渡效果的時(shí)長(zhǎng)等。

.box {
  transition: height 1s;
}

上面代表為 class 為 box 的元素設(shè)置了過(guò)渡效果,作用在它的 height 屬性上面,過(guò)渡效果的時(shí)長(zhǎng)為 1s。當(dāng)該元素的高度從某一個(gè)值變化到另一個(gè)值時(shí),就會(huì)有一個(gè)長(zhǎng)為 1s 的過(guò)渡效果。

過(guò)渡效果的本質(zhì)是: 當(dāng)作用的屬性的值變化時(shí),并不會(huì)立即從一個(gè)值變?yōu)榱硪粋€(gè)值,而是在變化的過(guò)程中,將中間狀態(tài)呈現(xiàn)出來(lái)。

例如:設(shè)置了過(guò)渡效果的元素的高度(height)從 0 變化到 100px 時(shí),并不是直接從 0 變化到 100px 的,其變化過(guò)程是一個(gè)連續(xù)的狀態(tài),從 0 到 1px,從 1px 到 2px······直到 100px。把中間的高度展現(xiàn)出來(lái),就可以讓用戶看到過(guò)渡效果。

再例如:設(shè)置了過(guò)渡效果的元素的透明度(opacity)從 0 變化到 1 時(shí),并不是直接從 0 變化到 1 的,其變化過(guò)程也是一個(gè)連續(xù)的狀態(tài),從 0 到 0.1,從 0.1 到 0.2······直到 opacity 為1。這樣用戶就可以看到一個(gè)元素從透明狀態(tài)逐漸變得清晰。當(dāng)然,并不一定就是從 0 變化到 0.1,然后從 0.1 變化到 0.2,這個(gè)過(guò)程是一個(gè)連續(xù)的過(guò)程,它的值在慢慢增加,增量是多少并不重要。

需要實(shí)現(xiàn)過(guò)渡效果,就需要一個(gè)起始態(tài)和一個(gè)終止態(tài),瀏覽器能夠從起始態(tài)逐步過(guò)渡到終止態(tài)。也就是從起始態(tài)到終止態(tài)之間的部分是連續(xù)的,是可以計(jì)算的,這樣瀏覽器才能把中間的狀態(tài)給我們呈現(xiàn)出來(lái)。

再回到之前的問(wèn)題:不知道 div 的高度,其高度是內(nèi)部的元素自動(dòng)撐開的,此時(shí)直接在 height 屬性上面添加過(guò)渡效果會(huì)失效。

為什么會(huì)失效?為什么會(huì)失效?為什么會(huì)失效?

對(duì)于一個(gè) div,如果它的高度是由子元素?fù)伍_的,那么它的 css 樣式 height 屬性的值為 auto。從 0 變到 auto,或者從 auto 變到 0,其中間狀態(tài)都是不可計(jì)算的,瀏覽器沒(méi)發(fā)給我們展示出中間狀態(tài),所以我們看不到過(guò)渡效果。

既然從 0 變到 auto,或者從 auto 變到 0,中間狀態(tài)無(wú)法計(jì)算,那我們可以顯式地告訴瀏覽器一個(gè)數(shù)值,應(yīng)該從 0 變到多少,或者從多少變到 0,讓瀏覽器可以計(jì)算出中間狀態(tài),這樣不就能看到過(guò)渡效果了嗎?

解決

當(dāng)展開時(shí),起始態(tài)為 0,我們通過(guò) getComputedStyle(element).height 得到元素的具體高度 x(終止態(tài))。給元素設(shè)置 transition 屬性,然后將元素的高度從 0 變到 x,這樣就能實(shí)現(xiàn)展開的動(dòng)效了。

<transition
  name="slide"
  @before-enter="beforeEnter"
  @enter="enter"
  @after-enter="afterEnter"
  @before-leave="beforeLeave"
  @leave="leave"
  @after-leave="afterLeave"
 >
  <span
    v-show="item.show"
    class="list-answer"
  >{{ item.A }}</span>
</transition>
beforeLeave(el) {
  // 給元素設(shè)置過(guò)渡效果
  el.style.transition = '0.3s height ease-in-out';
  // 高度變化時(shí),讓其內(nèi)容隱藏
  el.style.overflow = 'hidden';
},
leave(el) {
  el.style.height = 'auto';
  // 設(shè)置高度為具體的值
  el.style.height = window.getComputedStyle(el).height;
  // 強(qiáng)制瀏覽器回流,否則瀏覽器會(huì)合并兩次元素的高度更改(回流重繪的知識(shí))
  el.offsetHeight;
  el.style.height = '0px';
},
afterLeave(el) {
  // el.style.height = null;
  // 收尾工作,展示完過(guò)渡效果之后,設(shè)為原來(lái)的值
  el.style.transition = '';
  el.style.overflow = 'visible';
},

這里需要給元素設(shè)置 overflow: hidden,在元素高度小于內(nèi)部?jī)?nèi)容的高度時(shí),才會(huì)隱藏內(nèi)容。

同樣地,隱藏時(shí)先通過(guò) getComputedStyle(element).height 得到元素的具體高度 x(起始態(tài)),給元素設(shè)置 transition 屬性,然后將元素的高度從 x 變到 0,這樣就能實(shí)現(xiàn)隱藏的動(dòng)效了。

beforeEnter(el) {
  // 給元素設(shè)置過(guò)渡效果
  el.style.transition = '0.3s height ease-in-out';
  // 高度變化時(shí),讓其內(nèi)容隱藏
  el.style.overflow = 'hidden';
},
enter(el) {
  el.style.height = 'auto';
  // 保存元素原來(lái)的高度
  const endWidth = window.getComputedStyle(el).height;
  el.style.height = '0px';
  // 強(qiáng)制瀏覽器回流,否則瀏覽器會(huì)合并兩次元素的高度更改(回流重繪的知識(shí))
  el.offsetHeight;
  el.style.height = endWidth;
},
afterEnter(el) {
  // el.style.height = null;
  // 收尾工作,展示完過(guò)渡效果之后,設(shè)為原來(lái)的值
  el.style.transition = '';
  el.style.overflow = 'visible';
},

箭頭的旋轉(zhuǎn)動(dòng)效就比較簡(jiǎn)單了。先設(shè)置過(guò)渡效果,然后只需要在點(diǎn)擊箭頭的時(shí)候,動(dòng)態(tài)為這個(gè)元素添加一個(gè)類名,讓其旋轉(zhuǎn)屬性生效(rotateZ(180deg));當(dāng)再一次點(diǎn)擊的時(shí)候,去掉這個(gè)類名就好了。

<span
  class="list-question__arrow"
  :class="{'list-question__rotate-arrow': !item.show}"
  @click="onClickPromblem(ind)"
/>
onClickPromblem(index) {
  const qaItem = this.qaList[index];
  this.$set(qaItem, 'show', !qaItem.show);
},
list-question__arrow {
  width: 12px;
  height: 12px;
  background: url(https://xxx.com/arrowup.png) center no-repeat;
  transition: transform .4s;
}
list-question__rotate-arrow {
  transform: rotateZ(180deg);
  transition: transform .4s;
}

到此這篇關(guān)于Vue 不定高展開動(dòng)效原理詳解的文章就介紹到這了,更多相關(guān)Vue 不定高展開 內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Vue3實(shí)現(xiàn)pdf預(yù)覽功能

    Vue3實(shí)現(xiàn)pdf預(yù)覽功能

    在開發(fā)中,PDF預(yù)覽和交互功能是一個(gè)常見(jiàn)的需求,無(wú)論是管理系統(tǒng)、在線教育平臺(tái),還是企業(yè)內(nèi)部的知識(shí)庫(kù),能夠高效地展示和操作PDF文件都能極大地提升用戶體驗(yàn),本文將詳細(xì)介紹如何在Vue項(xiàng)目中實(shí)現(xiàn)pdf預(yù)覽功能,需要的朋友可以參考下
    2025-03-03
  • 解決vue前端rsa加密遇到的問(wèn)題message too long for RSA

    解決vue前端rsa加密遇到的問(wèn)題message too long for RS

    這篇文章主要介紹了解決vue前端rsa加密遇到的問(wèn)題message too long for RSA,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-07-07
  • mint-ui 時(shí)間插件使用及獲取選擇值的方法

    mint-ui 時(shí)間插件使用及獲取選擇值的方法

    下面小編就為大家分享一篇mint-ui 時(shí)間插件使用及獲取選擇值的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-02-02
  • Vue自定義省市區(qū)三級(jí)聯(lián)動(dòng)

    Vue自定義省市區(qū)三級(jí)聯(lián)動(dòng)

    這篇文章主要為大家詳細(xì)介紹了Vue自定義省市區(qū)三級(jí)聯(lián)動(dòng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • vue template中slot-scope/scope的使用方法

    vue template中slot-scope/scope的使用方法

    今天小編就為大家分享一篇vue template中slot-scope/scope的使用方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-09-09
  • 詳解?Vue虛擬DOM如何提高前端開發(fā)效率

    詳解?Vue虛擬DOM如何提高前端開發(fā)效率

    這篇文章主要為大家介紹了詳解?Vue虛擬DOM如何提高前端開發(fā)效率,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-12-12
  • vue+swiper實(shí)現(xiàn)側(cè)滑菜單效果

    vue+swiper實(shí)現(xiàn)側(cè)滑菜單效果

    這篇文章主要為大家詳細(xì)介紹了vue+swiper實(shí)現(xiàn)側(cè)滑菜單效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-12-12
  • vue3配置代理實(shí)現(xiàn)axios請(qǐng)求本地接口返回PG庫(kù)數(shù)據(jù)

    vue3配置代理實(shí)現(xiàn)axios請(qǐng)求本地接口返回PG庫(kù)數(shù)據(jù)

    這篇文章主要為大家詳細(xì)介紹了vue3配置代理實(shí)現(xiàn)axios請(qǐng)求本地接口返回PG庫(kù)數(shù)據(jù)的相關(guān)知識(shí),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解下
    2025-03-03
  • vue3頁(yè)面組件中怎么獲取上一個(gè)頁(yè)面的路由地址

    vue3頁(yè)面組件中怎么獲取上一個(gè)頁(yè)面的路由地址

    這篇文章主要給大家介紹了關(guān)于vue3頁(yè)面組件中怎么獲取上一個(gè)頁(yè)面的路由地址的相關(guān)資料,文中通過(guò)代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2024-02-02
  • Vue3+Element+Ts實(shí)現(xiàn)表單的基礎(chǔ)搜索重置等功能

    Vue3+Element+Ts實(shí)現(xiàn)表單的基礎(chǔ)搜索重置等功能

    本文主要介紹了Vue3+Element+Ts實(shí)現(xiàn)表單的基礎(chǔ)搜索重置等功能,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-12-12

最新評(píng)論

榆社县| 辉南县| 山丹县| 乌拉特后旗| 富源县| 都江堰市| 方正县| 铁岭市| 县级市| 什邡市| 寿宁县| 岐山县| 来安县| 永顺县| 社旗县| 广西| 卫辉市| 闸北区| 阿勒泰市| 武强县| 麦盖提县| 鹿邑县| 商河县| 霍林郭勒市| 射洪县| 平定县| 新和县| 平舆县| 东至县| 布拖县| 沾益县| 宁津县| 巴林右旗| 杭锦旗| 贵定县| 上饶县| 扎囊县| 望奎县| 丹东市| 沈丘县| 英吉沙县|