天天看點

Vue的元件系統

1.元件
  • Vue有兩大核心内容
    • 指令
    • 元件
  • 什麼是元件化【為什麼要用元件?】
    • 為了避免多人開發造成的沖突
    • 為了加快開發效率
    • 為了便利更新和維護
    • 元件化:就是使用具有獨立公共的一個整體(元件)來進行項目開發的趨勢(流行)
  • 什麼是元件?
    • 元件是一個html css js img 等的一個聚合體
    • 在Vue中使用了一個叫做單檔案元件的技術來實作元件
      • 它是一個 xxx.vue 檔案
      • 這個檔案在浏覽器中不能運作,必須經過編譯(gulp webpack )才能運作
  • Vue裡面是如何實作元件的?

    Vue.extend()

    1. 通過執行個體化Vue構造器函數得到一個Vue執行個體,這個執行個體我們稱之為‘根執行個體’,它是最大的父級
    2. 這個根執行個體是以标簽的形式存在的,那麼我們也稱之為‘根元件’
    3. 根執行個體也是一個元件,但是我們得到的隻是根元件
    4. Vue.extend() 它就是對Vue功能的擴充,這個擴充就是元件
    5. Vue是通過Vue.extend() 來實作【擴充】Vue的功能的,這個功能就是元件
    6. 思考:Vue.extend() 如何使用?
      • 通過new Vue.extend() 發現和 new Vue 一樣 —排除
      • 元件就是一個以标簽化呈現的東西,是以應該像标簽一樣使用
      • 但是無論是 HTML3 還是 HTML5 肯定不會同意它随意使用标簽的
      • Vue會将元件編譯成 HTML 結構
      • Vue這個處理過程,我們就稱之為‘元件注冊’
      • 總結:
        • Vue是通過Vue.extend() 來實作元件的
        • Vue的元件使用時需要注冊
  • Vue中是如何使用元件的?
    • 組建注冊
      • 全局注冊
        //Vue.component(元件的名稱,元件的配置)
        const Hello = Vue.extend({
            template:'<div>Hello 元件</div>'
        })
        Vue.component('Hello',Hello)
        
        //簡寫
        Vue.componen('Hello',{
            template:'<div>Hello 元件</div>'
        })
                   
      • 局部注冊

        局部注冊使用 components 選項來完成

        局部注冊隻在目前注冊的執行個體範圍内有效

        new Vue({
            el:'#app',
            components:{//局部注冊元件的選項
                //元件的名稱:元件的選項
                'Hello':{
                   template:'<div>Hello 這裡是局部注冊</div>' 
                }   
            }
        })
                   
    • 元件的命名:一定要避免和原生标簽沖突 ,如:Header header 就不可以
      • 大駝峰 HeadTitle

        使用

      • 小寫+橫杠 head-title

        使用

      • 一個單詞 Hello
      ​ 使用
      <hello></hello>   
      //或者
      <Hello></Hello>//推薦     
                 
    • 元件的使用規則
      • 元件在父子級是有直接關系的标簽中是不能直接解析的,會出問題
      • 直接父子級關系的标簽
        ul li
        ol li
        table tr  td
        dl dd dt
        select option
                   
      • 如何解決這個問題

        使用 is 屬性 來解決

        <div id="app">
           <table border="1">
               <tr>
               <td>1</td>
               <td>1</td>
               <td>1</td>
               </tr>
               <tr is = "Hello"></tr>
            </table>
        </div>
                   
        Vue.component('Hello',{
            template:`
            <tr>
               <td>2</td>
               <td>2</td>
               <td>2</td>
             </tr>
        `
        })
        new Vue({
            el:"#app"
        })
                   
    • 動态元件
      • 業務: 點選開關切換兩個元件
      • template寫在執行個體範圍内,會被直接解析,并且将來不會在html結構中出現
      • template模闆内直接子元素有且僅有一個
      • Vue提供了一個 component 元件
      • 通過keep-alive元件實作動态元件的緩存,加快元件的切換速度
        <div id="app">
            <button @click="typeChange">
                點選
            </button>
            <keep-alive>
            <component :is="type"></component>
            </keep-alive>
        </div>
        <template id="hello-box">
            <div>
                <h3>
                    手機号登入
                </h3>
                <input type="text" placeholder="請輸入手機号"/>
            </div>
        </template>
                   
        new Vue({
            el:'#app',
            data:{
                type:'PhoneLogin'
            },
            methods:{
                typeChange(){
                    this.type=(this.type === 'PhoneLogin') && 'UserLogin' || 'PhoneLogin'
                }
            },
            components:{
                'PhoneLogin':{
                    template:'#hello-box'
                },
                'UserLogin':{
                    template:'<div>使用者名和密碼登入</div>'
                }
            }
        })
                   
2.元件通信
  • 元件的嵌套
    • 子元件以标簽的形式要在父元件的模闆中使用
  • 元件中資料的定義
    • 為什麼元件中的data選項是一個函數,而根執行個體中是對象【面試】

      原因:

      1. 元件是一個獨立的整體,那麼資料也應該是一個獨立的
      2. 多人開發,資料如果不是獨立的,那麼資料就會沖突
      3. javascript最大的特點:函數式程式設計,而函數本身就有一個獨立作用域
    • 為什麼元件中的data函數要有傳回值,并且傳回值是一個對象,不能是其他嗎?

      原因:因為data選項要經過ES5 Object.defineProperty 屬性進行getter和setter設定

    • 資料中資料的使用
      • 組建的資料,适用範圍隻能在元件的模闆中
  • 元件通信
    • 父子元件通信
      1. 父元件中定義一個資料
      2. 在父元件的模闆中,用v-bind将父元件的資料綁定在子元件身上
        <Son :aa="money"></Son> //aa屬性為自定義
                   
      3. 在子元件的選項中,通過props選項來接收這個屬性
      4. 這個屬性可以在子元件的模闆中以全局變量的形式使
        <div id="app">
          <Father/>  
        </div>
        <!-- father 元件 start-->
        <template id="father">
        <div>
            <h3>
                這裡是 父元件
            </h3>
            <hr/>
            <Son :aa="money"></Son>
        </div>
        </template>
        <!-- father 元件 end-->
        
        <!-- son 元件 start-->
        <template id="son">
        <div>
            <h4>
                這裡是子元件
            </h4>
            <p>
                老爸每月給我 {{ aa }} 生活費
            </p>
            </div>
        </template>
        <!-- son 元件 end-->
                   
        Vue.component('Father',{
            template:'#father',
            data(){
                return {
                    money:3000
                }
            }
        });
        Vue.component('Son',{
            template:'#son',
            props:['aa']
        })
                   
      • Props選項
        • props屬性驗證
          • props可以是一個對象
          • props中的 validator 函數
          • props 第三方屬性驗證 :vue-validator-help
    • 子父元件通信
      • 自定義事件
        this.$emit
                   
      • 子父通信流程
        //1.先在子元件中定義一個資料
        Vue.component('Son',{
            tempalte:'#son',
            data(){
                return {
                    money:1000
                }
            }
        });
        //2. 在父元件中也定義一個資料,這個資料用來接收子元件傳遞過來的資料
         Vue.component('Father',{
                    template: '#father',
                    data () {
                      return {
                        bank: 1000
                      }
                    }
                  })
        //3.在父元件中定義一個事件處理程式,用于改變父元件定義的資料,這個事件處理程式是有參數的,這個參數就是子元件傳遞過來的資料
        Vue.component('Father',{
            template:'#father',
            data(){
                return {
                    bank:1000
                }
            },
            methods:{
                bankAdd( val ){//val就是子元件給的資料
                    this.bank += val;
                }
            }
        });
        //4.将這事件處理程式用過事件綁定的形式綁定在子元件
        <Son @aa="bankapp></Son>
        //5.在子元件中定義一個事件處理程式,這事件處理程式中通過this.$emit觸發自電子定義事件,并傳遞以參數
        Vue.component('Son',{
            template:'#son',
            data(){
                return {
                    money:1000
                }
            },
            methods:{
                give(){
                    this.$emit('aa',this,mone y)
                }
            }
        })
        
        <tempolate id="son">
        <div>
        <h4>
        這裡是子元件
        </h4>
        <button @click="give" ></botton>
        </div>
        </template>
                   
    • 非父子元件通信
      • ref
      • bus事件總線
    • 多元件狀态共享
      • Vuex
3.擴充
  • 2.5 slot slot-scope
    • slot 具名插槽 (必須會)
    • slot-scope(了解)
  • 2.6 v-slot(必須會)
4.元件的生命周期【組建的鈎子有哪些?】
  • 為什麼要使用生命周期?
  • 我們想要使用元件,那麼就得在元件的特定階段完成特定的任務(特定時間點完成特定任務)
  • 名詞–鈎子:機遇
    • 特定時間點,觸發一個方法
  • 組建的而生命周期分為三個階段: 初始化 、運作中 、銷毀

    8個鈎子函數(熟練掌握)

    • 生命周期鈎子不允許寫成箭頭函數,因為箭頭函數會改變this指向
    • 初始化
      • beforeCreat () {}
        • 元件即将建立
        • 任務: 初始化事件,并且為整個生命周期的開始做準備 【舉例:相親–父母給你做準備和謀劃】
        • 意義:
          • 資料未擷取,真實DOM未拿到
          • 資料請求,資料修改
      • created () {}
        • 元件建立結束
        • 任務:進行資料的注入和資料的反應【舉例:父母告訴你了讓你相親】
        • 意義:
          • 資料拿到了,真實DOM未拿到
          • 資料請求,資料修改
      • beforeMount () {}
        • 元件即将挂載
        • 任務:判斷元件是否有el/template選項,如果有那麼使用

          render函數

          将template模闆中的jsx轉換成VDOM對象模型,如果沒有,需要我們使用

          $mount/outerHTML

          手動挂載 【舉例:男女雙方互加微信,聊天】
        • 意義:
          • 更多的是内部完成任務,我們外部就不幹預了
          • 資料請求,資料修改
      • mounted () {}
        • 元件挂在結束
        • 任務: 将VDOM渲染為真實DOM,然後挂載到頁面中,這個時候我們在頁面中可以看到内容了 【舉例:網絡約見面】
        • 意義:
          • 操作真實DOM【可以進行第三方庫執行個體化】
          • 資料請求,資料修改
      • 總結 :
        • 我們常将資料請求寫在created中,因為created鈎子是第一次獲得資料的地方
        • mounted鈎子函數可以進行DOM操作【第三方庫執行個體化(靜态資料)】
    • 運作中
      • beforUpdate 元件更新前
        • 觸發條件:元件的資料發生改變
        • 任務 :VDOM重新生成,然後通過diff算法和以前的VDOM對比,生成patch更新檔對象【内部進行】【舉例:見面的結果】
      • updated 元件更新結束
        • 觸發條件:元件的資料發生改變
        • 任務:将patch更新檔對象進行渲染生成真實DOM 【舉例:證明第一次相親失敗,換了一人】
        • 意義:
          • 可以操作DOM【第三方庫的執行個體化(動态資料)】
      • 總結:平時大家使用updated進行第三方庫執行個體化
    • 銷毀
      • 意義: 用來完成善後工作【計時器,第三方庫執行個體,window.onscroll】
      • 元件的銷毀有兩種形式
        • 内部銷毀【舉例: 你可以将這個資訊告訴父親 】

          $destroy

          • 元件會被銷毀掉,但是元件的DOM外殼還在
          • 外部銷毀 【舉例:你父母得知相親的結果是由别人告知的】
            • 通過開關銷毀【推薦】
      • 元件的銷毀會觸發兩個鈎子函數【 沒啥差别, 任意選擇一個使用 】
        • beforDestroy () {} 銷毀前
        • destroyed () {} 銷毀結束
5.自定義過濾器
  • 注意點:
    • 是對已有資料進行格式化
    • 過濾器也可以傳遞參數
    • 過濾器要使用管道符才能起作用
      • 管道符 --回調函數中的傳回值是什麼,格式化後的資料就是什麼
  • 分類
    • 全局過濾器
      Vue.filter(過濾器名稱,回調函數)
                 
    • 局部過濾器
    filters:{
        //過濾器名稱:回調函數
        'dateFilter':(val,type) =>{//val就是要過濾的資料
            var date = new Date(val)
            return date.getFullYear()+type+(date.getMonth()+1)+type+date.getDate()
        }
    }
               

繼續閱讀