Vue.js組件

  • 組件用于封裝頁(yè)面的部分功能举庶,將功能的結(jié)構(gòu)会钝,樣式,邏輯代碼封裝為整體
  • 提高功能的復(fù)用性和可維護(hù)性笼踩,更好的專注于業(yè)務(wù)邏輯
  • 組件使用時(shí)為自定義HTML標(biāo)簽形式,通過(guò)組件名作為自定義標(biāo)簽名
  <div id="app">
    <!-- 普通HTML標(biāo)簽 -->
    <p>p標(biāo)簽內(nèi)容</p>
    <!-- Vue.js組件 -->
    <my-com></my-com>
  </div>

組件注冊(cè)

全局注冊(cè)

  • 全局注冊(cè)的組件在注冊(cè)之后可以用于任意實(shí)例或者組件中
Vue.component('組件名',{/*選項(xiàng)對(duì)象*/});
  • 注意:全局注冊(cè)必須設(shè)置在根Vue實(shí)例創(chuàng)建之前
    例子:
<body>
  <div id="app">
    <p>這是p標(biāo)簽</p>
    <my-component></my-component>
  </div>
  <script src="lib/vue.js"></script>
  <script>
    Vue.component('my-component',{
      template : '<div>這是我們?nèi)肿?cè)的組件</div>'
    });

    // 根實(shí)例
    new Vue({
      el: '#app',
      data: {

      }
    })
  </script>
</body>

組件基礎(chǔ)

  • 本質(zhì)上谷市,組件是可以復(fù)用的Vue實(shí)例蛔垢,可以與new Vue接收相同的選項(xiàng), 比如data迫悠,methods鹏漆,生命周期鉤子等等
  • 僅有的例外是像el這樣根實(shí)例特有的選項(xiàng)

組件命名規(guī)則

  • 組件具有兩種命名規(guī)則:
    • kebab-case:'my-component'(烤串命名法,短橫線鏈接多個(gè)單詞的命名方式)
    • PascalCase:'MyComponent'(傳統(tǒng)命名法创泄,帕斯卡命名法艺玲,每部分內(nèi)容的首字母大寫)


      示例
  • 注意:無(wú)論采用什么類型的命名方式,在DOM中都只有kebab-case可以使用

template 選項(xiàng)

  • template 選項(xiàng)用于設(shè)置組建的結(jié)構(gòu)鞠抑,最終被引入根實(shí)例或者其他組件中


    模板字符串
  • 注意:組件必須只有一個(gè)根元素(一個(gè)根元素饭聚,比如最外層的div就一對(duì))


    設(shè)置了兩個(gè)根元素就會(huì)報(bào)錯(cuò)

data 選項(xiàng)

  • data 選項(xiàng)用于存儲(chǔ)組件的數(shù)據(jù),與根實(shí)例不同搁拙,組件的data 選項(xiàng)必須為函數(shù)秒梳,數(shù)據(jù)設(shè)置在返回值對(duì)象中
  • 這種實(shí)現(xiàn)方式是為了確保每個(gè)組件實(shí)例可以維護(hù)一份被返回對(duì)象的獨(dú)立的拷貝,不會(huì)相互影響箕速。
    Vue devtools可以看到清晰的結(jié)構(gòu)

局部注冊(cè)

  • 局部注冊(cè)的組件只能用在當(dāng)前實(shí)例或組件中


    使用烤串命令法的時(shí)候需要加引號(hào)
  • 單獨(dú)配置組件的選項(xiàng)對(duì)象:


  • ES6的對(duì)象屬性簡(jiǎn)寫:


    使用ES6簡(jiǎn)寫的方式的兼容性沒(méi)有上面的好

組件通信

  • 父組件向子組件傳值
  • 子組件向父組件傳值
  • 非父子組件傳值
  • 其他通信方式

父組件向子組件傳值

  • 通過(guò)子組件的props選項(xiàng)接收父組件的傳值

    注意:props不要和data存在同名的屬性酪碘,否則會(huì)覆蓋
  • 父組件設(shè)置方式如下:


    第一行是靜態(tài)屬性設(shè)置,第二行是動(dòng)態(tài)設(shè)置盐茎,第三行是動(dòng)態(tài)設(shè)置常用操作
<body>
  <div id="app">
    <!-- 靜態(tài)屬性設(shè)置 -->
    <my-component-a 
      title="這是靜態(tài)的標(biāo)題"
      content="這是靜態(tài)的內(nèi)容"
    ></my-component-a>

    <!-- 動(dòng)態(tài)屬性綁定 -->
    <my-component-a
      v-bind:title="'這是靜態(tài)的標(biāo)題兴垦,這是演示'"
      :content="'這是靜態(tài)內(nèi)容'"
    ></my-component-a>

    <!-- 動(dòng)態(tài)屬性綁定:常用操作 -->
    <my-component-a
      :title="item.title"
      :content="item.content"
    ></my-component-a>
  </div>
  <script src="lib/vue.js"></script>
  <script>
    // 創(chuàng)建子組件
    Vue.component('my-component-a',{
      props : ['title','content'],
      template : `
      <div>
          <h3>{{ title }}</h3>
          <p>{{ content }}</p>
        </div>
      `
    });

    new Vue({
      el: '#app',
      data: {
        item: {
          title: '這是示例標(biāo)題',
          content: '這是示例內(nèi)容'
        }
      }
    });
  </script>
</body>

Props命名規(guī)則

  • 建議prop命名使用camelCase,父組件綁定時(shí)使用kebab-case


<body>
  <div id="app">
    <my-component
      :item-title="item.title"
      :item-content="item.content"
    ></my-component>
  </div>
  <script src="lib/vue.js"></script>
  <script>
    Vue.component('my-component', {
      props: ['itemTitle', 'itemContent'],
      template: `
        <div>
          <h3>{{ itemTitle }}</h3>
          <p>{{ itemContent }}</p>
        </div>
      `
    })
    new Vue({
      el: '#app',
      data: {
        item: {
          title: '這是示例標(biāo)題',
          content: '這是示例內(nèi)容'
        }
      }
    })
  </script>
</body> 

props練習(xí)

  • 通過(guò)v-for創(chuàng)建組件
<body>
  <div id="app">
    <!-- 通過(guò) v-for 遍歷數(shù)據(jù) items字柠,創(chuàng)建組件并生成內(nèi)容 -->
    <demo-item
      v-for="item in items"
      :item-title="item.title"
      :item-content="item.content"
      :key="item.id"

      :item="item"
    ></demo-item>
  </div>
  <script src="lib/vue.js"></script>
  <script>
    Vue.component('demoItem', {
      props: ['itemTitle', 'itemContent', 'item'],
      template: `
        <div>
          <h3>{{ itemTitle }}</h3>
          <p> {{ itemContent }} </p>
        </div>
      `
    })

    new Vue({
      el: '#app',
      data: {
        // 準(zhǔn)備給子組件使用的數(shù)據(jù)
        items: [
          {
            id : 1,
            title: '示例標(biāo)題1',
            content: '示例內(nèi)容1'
          },
          {
            id : 2,
            title: '示例標(biāo)題2',
            content: '示例內(nèi)容2'
          },
          {
            id : 3,
            title: '示例標(biāo)題3',
            content: '示例內(nèi)容3'
          },
        ]
      }
    })
  </script>
</body>

單向數(shù)據(jù)流

  • 父子組件間的所有prop都是單向下行綁定的探越,不能反向影響父組件
  • 如果子組件要處理prop數(shù)據(jù),應(yīng)當(dāng)存儲(chǔ)在data中再操作


  • 如果prop為數(shù)組或者對(duì)象的時(shí)候窑业,子組件操作將會(huì)影響到父組件的狀態(tài)
<body>
  <div id="app">
    <my-component
      :initial-title="title"
      :obj="obj"
      :arr = 'arr'
    ></my-component>
  </div>
  <script src="lib/vue.js"></script>
  <script>
    Vue.component('my-component', {
      props: ['initialTitle', 'obj','arr'],
      template: `
        <div>
          {{ title }}
          {{ obj }}
          {{ arr }}
          <button @click="fn">按鈕</button>
        </div>
      `,
      data () {
        return {
          title: this.initialTitle
        }
      },
      methods: {
        fn () {
          // title只是個(gè)字符串钦幔,不會(huì)反向影響到父組件的狀態(tài)
          this.title = '這是新的標(biāo)題';
          // this.initialTitle = '這是新的標(biāo)題'; // 不會(huì)影響父組件
          // obj是對(duì)象,會(huì)反向影響到父組件
          this.obj.name = 'jack';
          this.obj.age = '20';
          // arr是數(shù)組数冬,也會(huì)反向影響到父組件
          this.arr[0] = 4;
        }
      }
    });

    new Vue({
      el: '#app',
      data: {
        title: '這是示例標(biāo)題',
        obj: {
          name: 'william',
          age: 18
        },
        arr : [1,2,3]
      }
    });
  </script>
</body>

props類型

  • Prop 可以設(shè)置類型檢查节槐,這時(shí)需要將 props 更改為一個(gè)帶有驗(yàn)證需求的對(duì)象搀庶,并指定對(duì)應(yīng)類型拐纱。
如果當(dāng)前傳入的值不滿足props類型設(shè)置的值,就會(huì)彈出警告
  • prop還可以同時(shí)指定多個(gè)類型哥倔,通過(guò)數(shù)組方式保存就可以了
    String或者Number都可以

    設(shè)置這個(gè)內(nèi)容檢測(cè)僅僅是檢測(cè)秸架,如果忽略這個(gè)錯(cuò)誤也是可以渲染內(nèi)容上去的,所以設(shè)置之后要看控制臺(tái)檢查錯(cuò)誤

props驗(yàn)證

  • 當(dāng) prop 需要設(shè)置多種規(guī)則時(shí)咆蒿,可以將 prop 的值設(shè)置為選項(xiàng)對(duì)象
  • 之前的類型檢測(cè)功能通過(guò) type 選項(xiàng)設(shè)置


  • required 用于設(shè)置數(shù)據(jù)為必填項(xiàng)


  • default 用于給可選項(xiàng)指定默認(rèn)值东抹,當(dāng)父組件未傳遞數(shù)據(jù)時(shí)生效


  • 當(dāng)默認(rèn)值是數(shù)組或者對(duì)象的時(shí)候蚂子,必須為工廠函數(shù)返回的形式,避免引用類型在多個(gè)組件中產(chǎn)生相互影響的情況


  • validator 用于給傳入的 prop 設(shè)置校驗(yàn)函數(shù)缭黔,return 值為false 時(shí) Vue.js 會(huì)發(fā)出警告

    驗(yàn)證函數(shù)中沒(méi)法使用實(shí)例的methods食茎,data等功能

非props屬性

  • 當(dāng)父組件給子組件設(shè)置了屬性,此屬性在props不存在馏谨,這時(shí)就會(huì)自動(dòng)綁定到子組件的根元素上


    image.png
  • 如果組件根元素已經(jīng)存在了對(duì)應(yīng)屬性别渔,則會(huì)替換組件內(nèi)部的值
  • class 與 style 是例外,當(dāng)內(nèi)外都設(shè)置時(shí)惧互,屬性會(huì)自動(dòng)合并


  • 如果不希望繼承父組件設(shè)置的屬性哎媚,可以設(shè)置inheritAttrs:false,但只適用于普通屬性喊儡,class 與 style 不受影響


子組件向父組件傳值

子組件傳向父組件需要通過(guò)自定義事件來(lái)實(shí)現(xiàn)

  • 舉個(gè)例子:商品為子組件拨与,購(gòu)物車為父組件,父組件需要統(tǒng)計(jì)商品個(gè)數(shù)艾猜,就需要在子組件個(gè)數(shù)變化時(shí)傳值給父組件



  • 子組件數(shù)據(jù)變化時(shí)买喧,通過(guò)$emit()觸發(fā)自定義事件


  • 事件的名稱建議使用kebab-case命名方式
  • 父組件監(jiān)聽(tīng)子組件的自定義事件,設(shè)置好處理程序


自定義事件傳值

  • 子組件觸發(fā)事件時(shí)可以向父組件傳值


    第一個(gè)參數(shù)就是事件名箩朴,第二個(gè)參數(shù)就是傳遞的數(shù)據(jù)信息
  • 父組件在監(jiān)聽(tīng)事件時(shí)需要接收子組件傳遞的數(shù)據(jù)


  • 也可以寫成自定義事件岗喉,對(duì)應(yīng)處理的程序


組件與v-model

  • v-model用于組件時(shí),需要通過(guò)props與自定義事件實(shí)現(xiàn)




    實(shí)踐案例:

<body>
  <div id="app">
    <p>輸入框內(nèi)容: {{ iptValue }}</p>
    <com-input v-model = 'iptValue'></com-input>
  </div>
  <script src="lib/vue.js"></script>
  <script>
    var comInput = {
      props : ['value'],
      template : `
        <input 
          type="text"
          :value="value"
          @input = "onInput"
          >
      `
      ,
      methods : {
        onInput(event){
          this.$emit('input',event.target.value)
        }
      }
    }

    new Vue({
      el: '#app',
      data: {
        iptValue : ''
      },
      components : {
        comInput
      }
    })
  </script>
</body>

非父子組件傳值

什么是非父子組件炸庞?兄弟組件或者完全無(wú)關(guān)的兩個(gè)組件

兄弟組件傳值

兄弟組件之間是可以通過(guò)父組件進(jìn)行數(shù)據(jù)中轉(zhuǎn)的

<body>
  <div id="app">
    <!-- 父組件接收子組件A的數(shù)據(jù) -->
    <com-a
      @value-change="value = $event"
    ></com-a>
    <!-- 父組件將數(shù)據(jù)傳遞給子組件B -->
    <com-b
      :value="value"
    ></com-b>
  </div>
  <script src="lib/vue.js"></script>
  <script>
    // 子組件A:發(fā)送數(shù)據(jù)
    Vue.component('ComA', {
      template: `
        <div>
          組件A的內(nèi)容: {{ value }}
          <button
            @click="$emit('value-change', value)"
          >發(fā)送</button>
        </div>
      `,
      data () {
        return {
          value: '這是組件A中的數(shù)據(jù)'
        }
      }
    });

    // 子組件B:接收數(shù)據(jù)
    Vue.component('ComB', {
      props: ['value'],
      template: `
        <div>
          組件B接收到: {{ value }}
        </div>  
      `
    });


    // 根實(shí)例(父組件)
    new Vue({
      el: '#app',
      data: {
        // 用于數(shù)據(jù)中轉(zhuǎn)
        value: ''
      }
    })
  </script>
</body>

EventBus

  • 當(dāng)組件嵌套關(guān)系復(fù)雜的時(shí)候钱床,根據(jù)組件關(guān)系傳值會(huì)比較繁瑣
  • 如果組件為了數(shù)據(jù)中轉(zhuǎn),data中會(huì)存在許多與當(dāng)前組件功能無(wú)關(guān)的數(shù)據(jù)
  • EventBus (事件總線)是一個(gè)獨(dú)立的事件中心埠居,用于管理不同組件間的傳值操作
  • EventBus 通過(guò)一個(gè)新的 Vue 實(shí)例來(lái)管理組件傳值操作查牌,組件通過(guò)給實(shí)例注冊(cè)事件、調(diào)用事件來(lái)實(shí)現(xiàn)數(shù)據(jù)傳遞
// 將新的Vue實(shí)例bus存放在一個(gè)叫做EventBus.js的文件中
var bus = new Vue();
  • 發(fā)送數(shù)據(jù)的組件觸發(fā)bus事件滥壕,接收的組件給bus注冊(cè)對(duì)應(yīng)的事件


  • 給 bus 注冊(cè)對(duì)應(yīng)事件通過(guò) $on() 操作


  • 最后創(chuàng)建根實(shí)例執(zhí)行代碼即可

<body>
  <div id="app">
    <h3>購(gòu)物車</h3>
    <product-item></product-item>
    <product-total></product-total>
  </div>
  <script src="lib/vue.js"></script>
  <!-- 引入EventBus.js要在vue.js引入之后 -->
  <script src="EventBus.js"></script>
  <script>
    // 商品組件
    Vue.component('ProductItem', {
      template: `
        <div>
          <span>商品名稱:蘋果纸颜,商品個(gè)數(shù):{{ count }}</span>
          <button
            @click="countIns"
          >+1</button>
        </div>
      `,
      data () {
        return {
          count: 0
        }
      },
      methods: {
        countIns () {
          // 給bus觸發(fā)自定義事件,傳遞數(shù)據(jù)
          bus.$emit('countChange', 1);
          this.count++;
        }
      }
    });

    // 計(jì)數(shù)組件
    Vue.component('ProductTotal', {
      template: `
        <p>總個(gè)數(shù)為: {{ totalCount }}</p>
      `,
      data () {
        return {
          totalCount: 0
        }
      },
      created () {
        // 給 bus 注冊(cè)事件绎橘,并接收數(shù)據(jù)
        bus.$on('countChange', (productCount) => {
          // 實(shí)例創(chuàng)建完畢胁孙,可以使用 data 等功能
          // 使用箭頭函數(shù),直接使用this
          this.totalCount += productCount;
        });

      }
    })

    // 根實(shí)例
    new Vue({
      el: '#app',
      data: {

      }
    });
  </script>
</body>

其他通信方式

$root

  • $root 用于訪問(wèn)當(dāng)前組件樹(shù)根實(shí)例称鳞,設(shè)置簡(jiǎn)單的Vue應(yīng)用時(shí)可以通過(guò)此方式 進(jìn)行組件傳值


    注冊(cè)兩個(gè)局部組件comA和comB

    根據(jù)內(nèi)部的子組件直接訪問(wèn)到了根實(shí)例的數(shù)據(jù)

    進(jìn)一步證明是根實(shí)例的證據(jù):(組件B是子組件A的子組件)

<body>
  <div id="app">
    <com-a></com-a>
  </div>
  <script src="lib/vue.js"></script>
  <script>
    // 根實(shí)例的子組件A的子組件B
    var ComB = {
      template: `
        <div>
          組件B: {{ $root.count }}
          <button @click="clickFn">按鈕</button>
        </div>
      `,
      methods: {
        clickFn () {
          this.$root.count = 200;
        }
      }
    };

    // 子組件A
    var ComA = {
      template: `
        <div>
          組件A: {{ $root.count }}
          <button @click="clickFn">按鈕</button>
          <com-b></com-b>
        </div>
      `,
      methods: {
        clickFn () {
          this.$root.count = 100;
        }
      },
      components: {
        ComB
      }
    };


    // 根實(shí)例
    new Vue({
      el: '#app',
      data: {
        count: 0
      },
      components: {
        ComA
      }
    });
  </script>
</body>
  • 除了 $root , Vue.js 中還提供了 $parent$children 用于 便捷訪問(wèn)父子組件

$refs

  • $refs用于獲取設(shè)置了ref屬性的HTML標(biāo)簽或者子組件
  • 給普通HTML標(biāo)簽設(shè)置ref屬性涮较,$refs可以獲取DOM對(duì)象
  • 給子組件設(shè)置ref屬性,渲染后可以通過(guò)$refs獲取子組件實(shí)例
    mouted確認(rèn)組件已經(jīng)掛載完畢冈止,生命周期函數(shù)

組件插槽

便捷的設(shè)置組件內(nèi)容

單個(gè)插槽

  • 如果我們希望組件標(biāo)簽可以像 HTML 標(biāo)簽一樣設(shè)置內(nèi)容狂票,那么組件的使用靈活度會(huì)很高


  • 但平常我們書寫的組件,組件首尾標(biāo)簽中書寫的內(nèi)容會(huì)被拋棄


  • 這個(gè)時(shí)候我們需要通過(guò) <slot> 進(jìn)行插槽設(shè)置


    slot標(biāo)簽就代表了內(nèi)容區(qū)域
  • 需要注意模板內(nèi)容的渲染位置


    在父組件視圖模板中不能使用子組件的數(shù)據(jù)
  • 我們可以在 <slot> 中為插槽設(shè)置默認(rèn)值熙暴,也稱為后備內(nèi)容


具名插槽

  • 如果組件中有多個(gè)位置需要設(shè)置插槽闺属,據(jù)需要給 <slot> 設(shè)置name慌盯,稱為具名插槽



    default可以省略掉



    簡(jiǎn)寫模式:
<body>
  <div id="app">
    <com-a>
      <template v-slot:header>
        <h3>組件的頭部?jī)?nèi)容</h3>
      </template>

      <!-- <template v-slot:default>
        <p>組件的主體內(nèi)容1</p>
        <p>組件的主體內(nèi)容2</p>
      </template> -->

      <p>組件的主體內(nèi)容1</p>
      <p>組件的主體內(nèi)容2</p>

      <template #footer>
        <p>組件底部?jī)?nèi)容</p>
      </template>
    </com-a>
  </div>


  <script src="lib/vue.js"></script>
  <script>
    // 子組件 
    Vue.component('ComA', {
      template: `
        <div>
          <header>
            <slot name="header"></slot>
          </header>
          <main>
            <slot></slot>
          </main>
          <footer>
            <slot name="footer"></slot>
          </footer>
        </div>
      `
    });

    new Vue({
      el: '#app',
      data: {

      }
    });
  </script>
</body>

作用域插槽

用于讓插槽可以使用子組件的數(shù)據(jù)

  • 組件將需要被插槽使用的數(shù)據(jù)通過(guò) v-bind 綁定給 <slot>,這種用于給插槽傳遞數(shù)據(jù)的屬性稱為插槽 prop


  • 組件綁定數(shù)據(jù)后掂器,插槽中需要通過(guò) v-slot 接收數(shù)據(jù)


    dataObj指的是所有插槽prop的對(duì)象
  • 如果只存在默認(rèn)插槽亚皂,同時(shí)又需要接收數(shù)據(jù),可以進(jìn)行簡(jiǎn)寫



    default也是可以省略掉的

    還可以通過(guò) ES6 的解構(gòu)操作進(jìn)行數(shù)據(jù)接收
   <!-- 只具有默認(rèn)插槽的作用域插槽書寫方式 -->
    <!-- <com-b v-slot="dataObj"> -->
    <com-b #default="dataObj">
      {{ dataObj }}
    </com-b>

    <!-- 通過(guò) ES6 的解構(gòu)操作接收作用域插槽的數(shù)據(jù) -->
    <com-b v-slot="{ value, num }">
      {{ value }}
      {{ num }}
    </com-b>

內(nèi)置組件

動(dòng)態(tài)組件

動(dòng)態(tài)組件適用于多個(gè)組件頻繁切換的處理

  • <component> 用于將一個(gè)‘元組件’渲染為動(dòng)態(tài)組件国瓮,以 is 屬性值決定渲染哪個(gè)組件


    類似于v-if
  • 可以用來(lái)實(shí)現(xiàn)多個(gè)組件的快速切換孕讳,比如說(shuō)選項(xiàng)卡效果
<body>
  <div id="app">
    <!-- 按鈕代表選項(xiàng)卡的標(biāo)題功能 -->
    <button
      v-for="title in titles"
      :key="title"
      @click="currentCom = title"
    >
      {{ title }}
    </button>

    <!-- component 設(shè)置動(dòng)態(tài)組件 -->
    <component :is="currentCom"></component>
  </div>
  <script src="lib/vue.js"></script>
  <script>
    // 設(shè)置要切換的子組件選項(xiàng)對(duì)象
    var ComA = {
      template: `<p>這是組件A的內(nèi)容:<input type="text"></p>`
    };  
    var ComB = {
      template: `<p>這是組件B的內(nèi)容:<input type="text"></p>`
    };
    var ComC = {
      template: `<p>這是組件C的內(nèi)容:<input type="text"></p>`
    };

    new Vue({
      el: '#app',
      data: {
        // 所有組件名稱
        titles: ['ComA', 'ComB', 'ComC'],
        // 當(dāng)前組件名稱
        currentCom: 'ComA'
      },
      components: {
        ComA, ComB, ComC
      }
    });
  </script>
</body>

is 屬性會(huì)在每次切換組件時(shí),Vue 都會(huì)創(chuàng)建一個(gè)新的組件實(shí)例意思就是銷毀了再創(chuàng)建巍膘,無(wú)法進(jìn)行保留

keep-alive組件

主要用于保留組件狀態(tài)或避免組件重新渲染


  • include 屬性用于指定哪些組件會(huì)被緩存厂财,具有多種設(shè)置方式


    第一種方式,注意峡懈,每一個(gè)組件之間是不能有空格的

    第二種

    第三種璃饱,正則表達(dá)式
  • exclude 屬性用于指定哪些組件不會(huì)被緩存


  • max屬性用于設(shè)置最大的緩存數(shù)


    值得一提的是,不是選擇與否肪康,而是參與緩存就算一次

過(guò)渡組件

用于在Vue插入荚恶,更新,或者移除DOM的時(shí)候磷支,提供多種不同方式的應(yīng)用過(guò)渡谒撼,動(dòng)畫效果

transition組件
  • 用于給元素和組件添加進(jìn)入/離開(kāi)過(guò)渡
    • 條件渲染(v-if)
    • 條件展示(使用v-show)
    • 動(dòng)態(tài)組件
    • 組件根節(jié)點(diǎn)
  • 組件提供了6個(gè)class,用于設(shè)置過(guò)渡的具體效果
  • 進(jìn)入的類名:
    • v-enter
    • v-enter-to
    • v-enter-active
  • 離開(kāi)的類名
    • v-leave
    • v-leave-to
    • v-leave-active
<style>
    /* 用于設(shè)置出場(chǎng)的最終狀態(tài) */
    .v-leave-to {
      opacity: 0;
    }

    /* 用于設(shè)置過(guò)渡的執(zhí)行過(guò)程 */
    .v-leave-active {
      transition: opacity 1s;
    }

    /* 用于設(shè)置入場(chǎng)的初始狀態(tài) */
    .v-enter {
      opacity: 0;
    }

    /* 用于設(shè)置入場(chǎng)的最終狀態(tài) */
    .v-enter-to {
      opacity: 0.5;
    }

    /* 用于設(shè)置入場(chǎng)的過(guò)程 */
    .v-enter-active {
      transition: all 1s;
    }
  </style>
<body>
  <div id="app">
    <button @click="show = !show">切換</button>

    <transition>
      <p v-if="show">hello world</p>
    </transition>
  </div>  
  <script src="./lib/vue.js"></script>
  <script>
    new Vue({
      el: '#app',
      data: {
        show: true
      }
    });
  </script>
</body>
transition組件
  • 給組件設(shè)置name屬性雾狈,可以給多個(gè)元素廓潜,組件設(shè)置不同的過(guò)渡效果,需要將v-更改為name-的形式
    比如:
    <transition name="demo"> 的對(duì)應(yīng)類名前綴為:

    • demo-enter
    • demo-leave....等等
  • 通過(guò) appear 屬性善榛,可以讓組件在初始渲染時(shí)實(shí)現(xiàn)過(guò)渡


自定義過(guò)渡類名

自定義類名比普通類名優(yōu)先級(jí)更高辩蛋,在使用第三方 CSS 動(dòng)畫庫(kù)時(shí)非常有用

  • 用于設(shè)置自定義過(guò)渡類名的屬性如下
    • enter-class
    • enter-active-class
    • enter-to-class
    • leave-class
    • leave-active-class
    • leave-to-class
  • 用于設(shè)置初始過(guò)渡類名的屬性如下
    • appear-class
    • appear-to-class
    • appear-active-class
  <style>
    .v-enter, .v-leave-to {
      opacity: 0;
    }

    .v-enter-active, .v-leave-active {
      transition: all .5s;
    }

/* 自定義過(guò)渡效果優(yōu)先級(jí)更高 */
    .test {
      transition: all 3s;
    }

  </style>
</head>
<body>
  <div id="app">
    <button @click="show = !show">切換</button>

    <transition
      enter-active-class="test"
      leave-active-class="test"
    >
      <p v-if="show">這是 p 標(biāo)簽</p>
    </transition>
  </div>  
  <script src="./lib/vue.js"></script>
  <script>
    new Vue({
      el: '#app',
      data: {
        show: true
      }
    });
  </script>
</body>

Animate.css 是一個(gè)第三方 CSS 動(dòng)畫庫(kù),通過(guò)設(shè)置類名來(lái)給元素添加各種動(dòng)畫效果
使用注意

  • animate_ 前綴與compat版本
  • 基礎(chǔ)類名animated
    使用animate.css的一個(gè)簡(jiǎn)單案例:
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <link
    rel="stylesheet"
    
  />

  <!-- 不需要添加 animate__ 的兼容版本移盆,但是官方建議使用完整版本 -->
  <!-- "https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.0.0/animate.compat.css" -->
</head>
<body>
  <div id="app">
    <button @click="show = !show">按鈕</button>

    <!-- 通過(guò)自定義過(guò)渡類名設(shè)置悼院,給組件添加第三方動(dòng)畫庫(kù)的類名效果 -->
    <transition
      enter-active-class="animate__bounceInDown"
      leave-active-class="animate__bounceOutDown"
    >
      <!-- 必須給要使用動(dòng)畫的元素設(shè)置基礎(chǔ)類名 animate__animated -->
      <p 
        v-if="show"
        class="animate__animated"  
      >hello world</p>
    </transition>
  </div>
  <script src="lib/vue.js"></script>
  <script>
    new Vue({
      el: '#app',
      data: {
        show: true
      }
    });
  </script>
</body>
</html>

transition-group組件

  • <transition-group> 用于給列表統(tǒng)一設(shè)置過(guò)渡動(dòng)畫
    • tag屬性用于設(shè)置容器元素,默認(rèn)為<span>
    • 過(guò)渡會(huì)應(yīng)用于內(nèi)部元素咒循,而不是容器
    • 子節(jié)點(diǎn)必須要有獨(dú)立的key据途,動(dòng)畫才能正常工作
  • 當(dāng)列表元素變更導(dǎo)致元素位移,可以使用.v-move類名設(shè)置移動(dòng)時(shí)的效果
    列表移除添加小案例:
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    ul {
      position: relative;
    }

    .v-enter, .v-leave-to {
      opacity: 0;
      transform: translateX(100px);
    }

    .v-enter-active, .v-leave-active {
      transition: all .5s;
    }

    /* 讓元素在離場(chǎng)的過(guò)程中脫離標(biāo)準(zhǔn)流 */
    .v-leave-active {
      position: absolute;
    }

    .v-move {
      transition: all .5s;
    }

  </style>
</head>
<body>
  <div id="app">
    <input type="text"
      v-model="newTitle"
      @keyup.enter="addItem"
    >

    <transition-group
      tag="ul"
    >
      <li
        v-for="item in items"
        :key="item.id"
        @click="removeItem(item)"
      >
        {{ item.title }}
      </li>
    </transition-group>
  </div>  
  <script src="./lib/vue.js"></script>
  <script>
    new Vue({
      el: '#app',
      data: {
        items: [
          { id: 1, title: '示例內(nèi)容1'},
          { id: 2, title: '示例內(nèi)容2'},
          { id: 3, title: '示例內(nèi)容3'},
          { id: 4, title: '示例內(nèi)容4'},
          { id: 5, title: '示例內(nèi)容5'},
        ],
        newTitle: '',
        latestId: 5
      },
      methods: {
        addItem () {
          this.items.push({
            id: this.latestId + 1,
            title: this.newTitle
          });
          this.latestId++;
          this.newTitle = '';
        },
        removeItem (item) {
          var i = this.items.indexOf(item);
          this.items.splice(i, 1);
        }
      }
    });
  </script>
</body>
</html>
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末叙甸,一起剝皮案震驚了整個(gè)濱河市颖医,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌蚁署,老刑警劉巖便脊,帶你破解...
    沈念sama閱讀 218,858評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蚂四,死亡現(xiàn)場(chǎng)離奇詭異光戈,居然都是意外死亡哪痰,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門久妆,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)晌杰,“玉大人,你說(shuō)我怎么就攤上這事筷弦±哐荩” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 165,282評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵烂琴,是天一觀的道長(zhǎng)爹殊。 經(jīng)常有香客問(wèn)我,道長(zhǎng)奸绷,這世上最難降的妖魔是什么梗夸? 我笑而不...
    開(kāi)封第一講書人閱讀 58,842評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮号醉,結(jié)果婚禮上反症,老公的妹妹穿的比我還像新娘。我一直安慰自己畔派,他們只是感情好铅碍,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,857評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著线椰,像睡著了一般胞谈。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上憨愉,一...
    開(kāi)封第一講書人閱讀 51,679評(píng)論 1 305
  • 那天呜魄,我揣著相機(jī)與錄音,去河邊找鬼莱衩。 笑死爵嗅,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的笨蚁。 我是一名探鬼主播睹晒,決...
    沈念sama閱讀 40,406評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼括细!你這毒婦竟也來(lái)了伪很?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 39,311評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤奋单,失蹤者是張志新(化名)和其女友劉穎锉试,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體览濒,經(jīng)...
    沈念sama閱讀 45,767評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡呆盖,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年拖云,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片应又。...
    茶點(diǎn)故事閱讀 40,090評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡宙项,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出株扛,到底是詐尸還是另有隱情尤筐,我是刑警寧澤,帶...
    沈念sama閱讀 35,785評(píng)論 5 346
  • 正文 年R本政府宣布洞就,位于F島的核電站盆繁,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏旬蟋。R本人自食惡果不足惜改基,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,420評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望咖为。 院中可真熱鬧秕狰,春花似錦、人聲如沸躁染。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,988評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)吞彤。三九已至我衬,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間饰恕,已是汗流浹背挠羔。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,101評(píng)論 1 271
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留埋嵌,地道東北人破加。 一個(gè)月前我還...
    沈念sama閱讀 48,298評(píng)論 3 372
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像雹嗦,于是被迫代替她去往敵國(guó)和親范舀。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,033評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容