2019年末史上最全Vue框架整理從基礎到實戰(一)

vue基礎

歷史介紹

  • angular 09年,年份較早,一開始你們是拒絕 star:javascript

  • react 2013年, 用戶體驗好,直接拉到一堆粉絲 star:css

  • vue 2014年, 用戶體驗好 做者:尤雨溪 江蘇無錫人 國人驕傲html

前端框架與庫的區別?

  • jquery 庫 => DOM(操做DOM) + 請求
  • 有可能學習了一些art-template 庫 -> 模板引擎
  • 框架
    • 全方位功能齊全
    • 簡易的DOM體驗 + 發請求 + 模板引擎 + 路由功能
  • KFC的世界裏,庫就是一個小套餐, 框架就是全家桶
  • 代碼上的不一樣
    • 通常使用庫的代碼,是調用某個函數,咱們本身把控庫的代碼
    • 通常使用框架,其框架在幫咱們運行咱們編寫好的代碼
      • 框架: 初始化自身的一些行爲
        • 執行你所編寫的代碼
        • 施放一些資源

vue起步

  • 1:引包前端

  • 2:啓動vue

    new Vue({
        el:'#app',//目的地
        data:{
          //保存數據的地方 
        },
        template:`模板內容`
    });
    複製代碼

插值表達式

  • {{ 表達式 }}
    • 對象 (不要連續3個{{ {name:'jack'} }})
    • 字符串 {{ 'xxx' }}
    • 判斷後的布爾值 {{ true }}
    • 三元表達式 {{ true?'是正確':'錯誤' }}
  • 能夠用於頁面中簡單粗暴的調試
  • 要用插值表達式 必需要data中聲明該屬性

什麼是指令

  • 在vue中提供了一些對於頁面 + 數據的更爲方便的輸出,這些操做就叫作指令, 以v-xxx表示java

    • 好比html頁面中的屬性 <div v-xxx ></div>
  • 好比在angular中 以ng-xxx開頭的就叫作指令react

  • 在vue中 以v-xxx開頭的就叫作指令jquery

  • 指令中封裝了一些DOM行爲, 結合屬性做爲一個暗號, 暗號有對應的值,根據不一樣的值,框架會進行相關DOM操做的綁定ajax

vue中經常使用的v-指令演示

  • v-text:元素的textContent屬性,必須是雙標籤 跟{{ }}效果是同樣的 使用較少
  • v-html: 元素的innerHTML
  • v-if : 判斷是否插入這個元素,至關於對元素的銷燬和建立
  • v-else-if
  • v-else
  • v-show 隱藏元素 若是肯定要隱藏, 會給元素的style加上display:none。是基於css樣式的切換

v-if和v-show的區別 (官網解釋)

v-if 是「真正」的條件渲染,由於它會確保在切換過程當中條件塊內的事件監聽器和子組件適當地被銷燬和重建。編程

v-if 也是惰性的:若是在初始渲染時條件爲假,則什麼也不作——直到條件第一次變爲真時,纔會開始渲染條件塊。

相比之下,v-show 就簡單得多——無論初始條件是什麼,元素老是會被渲染,而且只是簡單地基於 CSS 進行切換。

通常來講,v-if 有更高的切換開銷,而 v-show 有更高的初始渲染開銷。所以,若是須要很是頻繁地切換,則使用 v-show 較好;若是在運行時條件不多改變,則使用 v-if 較好。

v-bind使用

  • 給元素的屬性賦值

    • 能夠給已經存在的屬性賦值 input value
    • 也能夠給自定義屬性賦值 mydata
  • 語法 在元素上 v-bind:屬性名="常量||變量名"

  • 簡寫形式 :屬性名="變量名"

  • <div v-bind:原屬性名="變量"></div>
    <div :屬性名="變量">
    </div>
    複製代碼

v-on的使用

  • 處理自定義原生事件的,給按鈕添加click並讓使用變量的樣式改變
  • 普通使用 v-on:事件名="表達式||函數名"
  • 簡寫方式 @事件名="表達式"

v-model 雙向的數據綁定

  • 雙向數據流(綁定)
    • 頁面改變影響內存(js)
    • 內存(js)改變影響頁面

v-bind 和 v-model 的區別

  • input v-model="name"

    • 雙向數據綁定 頁面對於input的value改變,能影響內存中name變量
    • 內存js改變name的值,會影響頁面從新渲染最新值
  • input :value="name"

    • 單向數據綁定 內存改變影響頁面改變
  • v-model: 其的改變影響其餘 v-bind: 其的改變不影響其餘

  • v-bind就是對屬性的簡單賦值,當內存中值改變,仍是會觸發從新渲染

v-for的使用

  • 基本語法 v-for="item in arr"
  • 對象的操做 v-for="item in obj"
  • 若是是數組沒有id
    • v-for="(item,index) in arr" :class="index" :key='index'
  • v-for的優先級最高

[TOC]

組件基礎

什麼是組件

其實忽然出來的這個名詞,會讓您不知因此然,若是你們使用過bootstrap的同窗必定會對這個名詞不陌生,咱們其實在很早的時候就接觸這個名詞

一般一個應用會以一顆嵌套的組件樹的形式來阻止:

局部組件

使用局部組件的打油詩: 建子 掛子 用子

注意:在組件中這個data必須是一個函數,返回一個對象

<div id="app">
      <!-- 3.使用子組件 -->
    <App></App>
</div>
<script> //1.建立子組件 const App = { //必須是一個函數 data() { return { msg: '我是App組件' } }, components: { Vcontent }, template: ` <div> <Vheader></Vheader> <div> <Vaside /> <Vcontent /> </div> </div> ` } new Vue({ el: '#app', data: { }, components: { // 2.掛載子組件 App } }) </script>
複製代碼

全局組件

經過Vue.component(組件名,{})建立全局組件,此時該全局組件能夠在任意模板(template)中使用

Vue.component('Child',{
    template:` <div> <h3>我是一個子組件</h3> </div> `
})
複製代碼

組件通訊

父傳子

若是一個網頁有一個博文組件,可是若是你不能向這個組件傳遞某一篇博文的標題和內容之類想展現的數據的話,它是沒有辦法使用的.這也正是prop的由來

父組件往子組件通訊:經過Prop向子組件傳遞數據

Vue.component('Child',{
    template:` <div> <h3>我是一個子組件</h3> <h4>{{childData}}</h4> </div> `,
    props:['childData']
})
const App = {
    data() {
        return {
            msg: '我是父組件傳進來的值'
        }
    },
    template: ` <div> <Child :childData = 'msg'></Child> </div> `,
    computed: {

    }
}
複製代碼
  1. 在子組件中聲明props接收在父組件掛載的屬性
  2. 能夠在子組件的template中任意使用
  3. 在父組件綁定自定義的屬性
子傳父

網頁上有一些功能可能要求咱們和父組件組件進行溝通

子組件往父組件通訊: 監聽子組件事件,使用事件拋出一個值

Vue.component('Child', {
    template: ` <div> <h3>我是一個子組件</h3> <h4>{{childData}}</h4> <input type="text" @input = 'handleInput'/> </div> `,
    props: ['childData'],
    methods:{
        handleInput(e){
            const val = e.target.value;
            //使用$emit觸發子組件的事件
            this.$emit('inputHandler',val);
        }
    },
})

const App = {
    data() {
        return {
            msg: '我是父組件傳進來的值',
            newVal:''
        }
    },
    methods:{
        input(newVal){
            // console.log(newVal);
            this.newVal = newVal;
        }
    },
    template: ` <div> <div class='father'> 數據:{{newVal}} </div> <!--子組件監聽事件--> <Child :childData = 'msg' @inputHandler = 'input'></Child> </div> `,
    computed: {

    }
}
複製代碼
  1. 在父組件中 子組件上綁定自定義事件

  2. 在子組件中 觸發原生的事件 在事件函數經過this.$emit觸發自定義的事件

平行組件

在開發中,可能會存在沒有關係的組件通訊,好比有個博客內容顯示組件,還有一個表單提交組件,咱們如今提交數據到博客內容組件顯示,這顯示有點費勁.

爲了解決這種問題,在vue中咱們可使用bus,建立中央事件總線

const bus = new Vue();
// 中央事件總線 bus
Vue.component('B', {
    data() {
        return {
            count: 0
        }
    },
    template: ` <div>{{count}}</div> `,
    created(){
        // $on 綁定事件
        bus.$on('add',(n)=>{
            this.count+=n;
        })
    }
})

Vue.component('A', {
    data() {
        return {

        }
    },
    template: ` <div> <button @click='handleClick'>加入購物車</button> </div> `,
    methods:{
        handleClick(){
            // 觸發綁定的函數 // $emit 觸發事件
            bus.$emit('add',1);
        }
    }
})
複製代碼
其它組件通訊方式

父組件 provide來提供變量,而後再子組件中經過inject來注入變量.不管組件嵌套多深

Vue.component('B', {
    data() {
        return {
            count: 0
        }
    },
    inject:['msg'],
    created(){
        console.log(this.msg);

    },
    template: ` <div> {{msg}} </div> `,
})

Vue.component('A', {
    data() {
        return {

        }
    },
    created(){
        // console.log(this.$parent.$parent);
        // console.log(this.$children);
        console.log(this);


    },
    template: ` <div> <B></B> </div> `
})
new Vue({
    el: '#app',
    data: {

    },
    components: {
        // 2.掛載子組件
        App
    }

})
複製代碼

插槽

匿名插槽

子組件定義 slot 插槽,但並未具名,所以也能夠說是默認插槽。只要在父元素中插入的內容,默認加入到這個插槽中去

Vue.component('MBtn', {
    template: ` <button> <slot></slot> </button> `,
    props: {
        type: {
            type: String,
            defaultValue: 'default'
        }
    },
})

const App = {
    data() {
        return {

        }
    },
    template: ` <div> <m-btn>登陸</m-btn> <m-btn>註冊</m-btn> <m-btn>提交</m-btn> </div> `,
}
new Vue({
    el: '#app',
    data: {

    },
    components: {
        // 2.掛載子組件
        App
    }

})
複製代碼
具名插槽

具名插槽能夠出如今不一樣的地方,不限制出現的次數。只要匹配了 name 那麼這些內容就會被插入到這個 name 的插槽中去

Vue.component('MBtn',{
    template:` <button :class='type' @click='clickHandle'> <slot name='register'></slot> <slot name='login'></slot> <slot name='submit'></slot> </button> `,
    props:{
        type:{
            type: String,
            defaultValue: 'default'
        }
    },
    methods:{
        clickHandle(){
            this.$emit('click');
        }
    }
})

const App = {
    data() {
        return {

        }
    },
    methods:{
        handleClick(){
            alert(1);
        },
        handleClick2(){
            alert(2);
        }
    },
    template: ` <div> <MBtn type='default' @click='handleClick'> <template slot='register'> 註冊 </template> </MBtn> <MBtn type='success' @click='handleClick2'> <template slot='login'> 登陸 </template> </MBtn> <MBtn type='danger'> <template slot='submit'> 提交 </template> </MBtn> </div> `,
}
new Vue({
    el: '#app',
    data: {

    },
    components: {
        App
    }

})
複製代碼
做用域插槽

一般狀況下普通的插槽是父組件使用插槽過程當中傳入東西決定了插槽的內容。但有時咱們須要獲取到子組件提供的一些數據,那麼做用域插槽就排上用場了

Vue.component('MyComp', {
    data(){
        return {
            data:{
                username:'小馬哥'
            }
        }
    },
    template: ` <div> <slot :data = 'data'></slot> <slot :data = 'data' name='one'></slot> </div> `
})

const App = {
    data() {
        return {

        }
    },
    template: ` <div> <MyComp> <!--默認的插槽 default能夠省略--> <template v-slot:default='user'> {{user.data.username}} </template> </MyComp> <MyComp> <!--與具名插槽配合使用--> <template v-slot:one='user'> {{user.data.username}} </template> </MyComp> </div> `,
}
new Vue({
    el: '#app',
    data: {

    },
    components: {
        App
    }

})
複製代碼
做用域插槽應用

先說一下咱們假設的應用經常使用場景,咱們已經開發了一個代辦事項列表的組件,不少模塊在用,如今要求在不影響已測試經過的模塊功能和展現的狀況下,給已完成的代辦項增長一個對勾效果

也就是說,代辦事項列表組件要知足一下幾點

  1. 以前數據格式和引用接口不變,正常展現
  2. 新的功能模塊增長對勾
const todoList = {
   data(){
       return {

       }
   },
   props:{
       todos:Array,
       defaultValue:[]
   },
   template:` <ul> <li v-for='item in todos' :key='item.id'> <slot :itemValue='item'> {{item.title}} </slot> </li> </ul> `
}

const App = {
   data() {
       return {
           todoList: [
               {
                   title: '大哥你好麼',
                   isComplate:true,
                   id: 1
               },
               {
                   title: '小弟我還行',
                   isComplate:false,
                   id: 2
               },
               {
                   title: '你在幹什麼',
                   isComplate:false,
                   id: 3
               },
               {
                   title: '抽菸喝酒燙頭',
                   isComplate:true,
                   id: 4
               }
           ]
       }
   },
   components:{
       todoList
   },
   template: ` <todoList :todos='todoList'> <template v-slot='data'> <input type='checkbox' v-model='data.itemValue.isComplate'/> {{data.itemValue.title}} </template> </todoList> `,
}
new Vue({
   el: '#app',
   data: {

   },
   components: {
       App
   }

})
複製代碼

生命週期

「你不須要立馬弄明白全部的東西,不過隨着你的不斷學習和使用,它的參考價值會愈來愈高。

當你在作項目過程當中,遇到了這種問題的時候,再回過頭來看這張圖

什麼是生命週期

每一個 Vue 實例在被建立時都要通過一系列的初始化過程。 例如:從開始建立、初始化數據、編譯模板、掛載Dom、數據變化時更新DOM、卸載等一系列過程。 咱們稱 這一系列的過程 就是Vue的生命週期。 通俗說就是Vue實例從建立到銷燬的過程,就是生命週期。 同時在這個過程當中也會運行一些叫作生命週期鉤子的函數,這給了用戶在不一樣階段添加本身的代碼的機會,利用各個鉤子來完成咱們的業務代碼。

幹活滿滿

生命週期鉤子

beforCreate

實例初始化以後、建立實例以前的執行的鉤子事件

Vue.component('Test',{
   data(){
       return {
           msg:'小馬哥'
       }
   },
   template:` <div> <h3>{{msg}}</h3> </div> `,
   beforeCreate:function(){
       // 組件建立以前
       console.log(this.$data);//undefined

   }
})
複製代碼

效果:

建立實例以前,數據觀察和事件配置都沒好準備好。也就是數據也沒有、DOM也沒生成

created

實例建立完成後執行的鉤子

created() {
    console.log('組件建立', this.$data);
}
複製代碼

效果:

實例建立完成後,咱們能讀取到數據data的值,可是DOM還沒生成,能夠在此時發起ajax

beforeMount

將編譯完成的html掛載到對應的虛擬DOM時觸發的鉤子 此時頁面並無內容。 即此階段解讀爲: 即將掛載

beforeMount(){
    // 掛載數據到 DOM以前會調用
    console.log('DOM掛載以前',document.getElementById('app'));
}
複製代碼

效果:

mounted

編譯好的html掛載到頁面完成後所執行的事件鉤子函數

mounted() {
    console.log('DOM掛載完成',document.getElementById('app'));
}
複製代碼

效果:

beforeUpdate和updated
beforeUpdate() {
    // 在更新DOM以前 調用該鉤子,應用:能夠獲取原始的DOM
    console.log('DOM更新以前', document.getElementById('app').innerHTML);
},
updated() {
    // 在更新DOM以後調用該鉤子,應用:能夠獲取最新的DOM
  console.log('DOM更新完成', document.getElementById('app').innerHTML);
}
複製代碼

效果:

beforeDestroy和destroyed

當子組件在v-if的條件切換時,該組價處於建立和銷燬的狀態

beforeDestroy() {
    console.log('beforeDestroy');
},
destroyed() {
    console.log('destroyed');
},
複製代碼
activated和deactivated

當配合vue的內置組件<keep-alive>一塊兒使用的時候,纔會調用下面此方法

<keep-alive>組件的做用它能夠緩存當前組件

activated() {
    console.log('組件被激活了');
},
deactivated() {
   console.log('組件被停用了');
},
複製代碼

組件進階

動態組件

有的時候,在不一樣組件之間進行動態切換是很是有用的,好比在一個多標籤的界面裏

const bus = new Vue();
Vue.component('TabLi', {
    data() {
        return {

        }
    },
    methods: {
        clickHandler(title) {
            bus.$emit('handleChange', title);
        }
    },
    props: ['tabTitles'],
    template: ` <ul> <li @click='clickHandler(title)' v-for='(title,i) in tabTitles' :key='i'>{{title}}</li> </ul> `
})
const Home = {
    data() {
        return {
            isActive:false
        }
    },
    methods: {
        handleClick(){
            this.isActive = true;
        }
    },
    template: `<div @click='handleClick' :class='{active:isActive}'>Home Component</div>`
}
const Posts = {
    data() {
        return {

        }
    },
    template: `<div>Posts Component</div>`
}
const Archive = {
    data() {
        return {

        }
    },
    template: `<div>Archive Component</div>`
}
Vue.component('TabComp', {
    data() {
        return {
            title: 'Home'
        }
    },
    created() {
        bus.$on('handleChange', (title) => {
            this.title = title
        })
    },
    template: ` <div class='content'> <componet :is='title'></componet> </div> `,
    components: {
        Home,
        Posts,
        Archive
    }
})

const App = {
    data() {
        return {
            tabTitles: ['Home', 'Posts', 'Archive']
        }
    },
    template: ` <div> <TabLi :tabTitles='tabTitles'></TabLi> <TabComp></TabComp> </div> `,

}
new Vue({
    el: '#app',
    data() {
        return {

        }
    },
    components: {
        App,

    }
})
複製代碼

使用is特性來切換不一樣的組件

當在這些組件之間切換的時候,有時候會想保持這些組件的狀態,以免反覆渲染致使的性能問題

在動態組件上使用keep-alive
<keep-alive>
    <componet :is='title'></componet>
</keep-alive>
複製代碼

異步組件

在大型應用中,咱們可能須要將應用分割成小一些的代碼塊,而且只在須要的時候才從服務器加載一個模塊。爲了簡化,Vue 容許你以一個工廠函數的方式定義你的組件,這個工廠函數會異步解析你的組件定義。Vue 只有在這個組件須要被渲染的時候纔會觸發該工廠函數,且會把結果緩存起來供將來重渲染。例如:

const App = {
    data() {
        return {
            isShow:false
        }
    },
    methods:{
        asyncLoadTest(){
            this.isShow = true;
        }
    },
    template:` <div> <button @click='asyncLoadTest'>異步加載</button> <test v-if='isShow'/> </div> `,
    components:{
        //異步加載組件
        test:()=>import('./Test.js')
    }
}
new Vue({
    el:'#app',
    data(){
        return {

        }
    },
    components:{
        App
    }
})
複製代碼

效果顯示:

獲取DOM和子組件對象

儘管存在 prop 和事件,有的時候你仍可能須要在 JavaScript 裏直接訪問一個子組件。爲了達到這個目的,你能夠經過 ref 特性爲這個子組件賦予一個 ID 引用。例如:

const Test = {
    template: `<div class='test'>我是測試組件</div>`
}
const App = {
    data() {
        return {

        }
    },
    created() {
        console.log(this.$refs.test); //undefined

    },
    mounted() {
        // 若是是組件掛載了ref 獲取是組件對象,若是是標籤掛載了ref,則獲取的是DOM元素
        console.log(this.$refs.test);
        console.log(this.$refs.btn);

        // 加載頁面 讓input自動獲取焦點
        this.$refs.input.focus();

    },
    components: {
        Test
    },
    template: ` <div> <button ref = 'btn'></button> <input type="text" ref='input'> <Test ref = 'test'></Test> </div> `
}
new Vue({
    el: '#app',
    data: {

    },
    components: {
        App
    }
})
複製代碼
nextTick的用法

將回調延遲到下次 DOM 更新循環以後執行。在修改數據以後當即使用它,而後等待 DOM 更新

有些事情你可能想不到,vue在更新DOM時是異步執行的.只要偵聽到數據變化,Vue將開啓一個隊列,並緩存在同一事件循環中發生的全部數據變動.若是同一個wather被屢次觸發,只會被推入到隊列中一次.這種在緩衝時去除重複數據對於避免沒必要要的計算和 DOM 操做是很是重要的。而後,在下一個的事件循環「tick」中,Vue 刷新隊列並執行實際 (已去重的) 工做

<div id="app">
    <h3>{{message}}</h3>
</div>
<script src="./vue.js"></script>
<script> const vm = new Vue({ el:'#app', data:{ message:'123' } }) vm.message = 'new Message';//更新數據 console.log(vm.$el.textContent); //123 Vue.nextTick(()=>{ console.log(vm.$el.textContent); //new Message }) </script>
複製代碼

當你設置vm.message = 'new Message',該組件不會當即從新渲染.當刷新隊列時,組件會在下一個事件循環'tick'中更新.多數狀況咱們不須要關心這個過程,可是若是你想基於更新後的 DOM 狀態來作點什麼,這就可能會有些棘手。雖然 Vue.js 一般鼓勵開發人員使用「數據驅動」的方式思考,避免直接接觸 DOM,可是有時咱們必需要這麼作。爲了在數據變化以後等待 Vue 完成更新 DOM,能夠在數據變化以後當即使用 Vue.nextTick(callback)。這樣回調函數將在 DOM 更新完成後被調用。

nextTick的應用

有個需求:

在頁面拉取一個接口,這個接口返回一些數據,這些數據是這個頁面的一個浮層組件要依賴的,而後我在接口一返回數據就展現了這個浮層組件,展現的同時,上報一些數據給後臺(這些數據就是父組件從接口拿的),這個時候,神奇的事情發生了,雖然我拿到數據了,可是浮層展示的時候,這些數據還未更新到組件上去,上報失敗

const Pop = {
    data() {
        return {
            isShow:false
        }
    },
    template:` <div v-show = 'isShow'> {{name}} </div> `,
    props:['name'],
    methods: {
        show(){
            this.isShow = true; 
            alert(this.name);
        }
    },
}
const App = {
    data() {
        return {
            name:''
        }
    },
    created() {
        // 模擬異步請求的數據
        setTimeout(() => {
            this.name = '小馬哥',
            this.$refs.pop.show();
        }, 2000);
    },
    components:{
        Pop
    },
    template: `<pop ref='pop' :name='name'></pop>`
}
const vm = new Vue({
    el: '#app',
    components: {
        App
    }
})
複製代碼

完美解決:

created() {
     // 模擬異步請求的數據
     setTimeout(() => {
         this.name = '小馬哥',
          this.$nextTick(()=>{
               this.$refs.pop.show();
         })
     }, 2000);
},
複製代碼
對象變動檢測注意事項

因爲JavaScript的限制,Vue不能檢測對象屬性的添加和刪除

對於已經建立的實例,Vue不容許動態添加根級別的響應式屬性.可是,能夠經過Vue.set(object,key,value)方法向嵌套獨享添加響應式屬性

<div id="app">
    <h3>
        {{user.name}}{{user.age}}
        <button @click='handleAdd'>添加年齡</button>
    </h3>
</div>
<script src="./vue.js"></script>
<script> new Vue({ el:'#app', data:{ user:{}, }, created() { setTimeout(() => { this.user = { name:'張三' } }, 1250); }, methods: { handleAdd(){ console.log(this); // 無響應式  // this.user.age = 20; // 響應式的 this.$set(this.user,'age',20); } }, }) </script>
複製代碼
this.$set(this.user,'age',20);//它只是全局Vue.set的別名
複製代碼

若是想爲已存在的對象賦值多個屬性,可使用Object.assign()

// 一次性響應式的添加多個屬性
this.user = Object.assign({}, this.user, {
    age: 20,
    phone: '113131313'
})
複製代碼

混入mixin偷懶

混入(mixin)提供了一種很是靈活的方式,來分發Vue組件中的可複用功能.一個混入對象能夠包含任意組件選項.

一個混入對象能夠包含任意組件選項。當組件使用混入對象時,全部混入對象的選項將被「混合」進入該組件自己的選項。

<div id="app">
    {{msg}}
</div>
<script src="./vue.js"></script>
<script> const myMixin = { data(){ return { msg:'123' } }, created() { this.sayHello() }, methods: { sayHello(){ console.log('hello mixin') } }, } new Vue({ el: '#app', data(){ return { msg:'小馬哥' } }, mixins: [myMixin] }) 複製代碼

mixin應用

有一種很難常見的狀況:有兩個很是類似的組件,他們共享一樣的基本函數,而且他們之間也有足夠的不一樣,這時你站在了一個十字路口:我是把它拆分紅兩個不一樣的組件?仍是隻使用一個組件,建立足夠的屬性來改變不一樣的狀況。

這些解決方案都不夠完美:若是你拆分紅兩個組件,你就不得不冒着若是功能變更你要在兩個文件中更新它的風險,這違背了 DRY 前提。另外一方面,太多的屬性會很快會變得混亂不堪,對維護者很不友好,甚至是你本身,爲了使用它,須要理解一大段上下文,這會讓你感到失望。

使用混合。Vue 中的混合對編寫函數式風格的代碼頗有用,由於函數式編程就是經過減小移動的部分讓代碼更好理解。混合容許你封裝一塊在應用的其餘組件中均可以使用的函數。若是被正確的使用,他們不會改變函數做用域外部的任何東西,因此屢次執行,只要是一樣的輸入你老是能獲得同樣的值。這真的很強大。

咱們有一對不一樣的組件,他們的做用是切換一個狀態布爾值,一個模態框和一個提示框.這些提示框和模態框除了在功能,沒有其它共同點:它們看起來不同,用法不同,可是邏輯同樣

<div id="app">
    <App></App>
</div>
<script src="./vue.js"></script>
<script> // 全局混入 要格外當心 每次實例建立 都會調用 Vue.mixin({ created(){ console.log('hello from mixin!!'); } }) // 抽離 const toggleShow = { data() { return { isShow: false } }, methods: { toggleShow() { this.isShow = !this.isShow } } } const Modal = { template: `<div v-if='isShow'><h3>模態框組件</h3></div>`, data() { return { } }, mixins:[toggleShow] } const ToolTip = { data() { return { } }, template: `<div v-if='isShow'><h3>提示組件</h3></div>`, mixins:[toggleShow] } const App = { data() { return { } }, template: ` <div> <button @click='handleModel'>模態框</button> <button @click='handleToolTip'>提示框</button> <Modal ref='modal'></Modal> <ToolTip ref="toolTip"></ToolTip> </div> `, components: { Modal, ToolTip }, methods: { handleModel() { this.$refs.modal.toggleShow() }, handleToolTip() { this.$refs.toolTip.toggleShow() } }, } new Vue({ el: '#app', data: {}, components: { App }, }) 複製代碼

往期文章

2019年末史上最全Vue框架整理從基礎到實戰(二)

2019年末史上最全Vue框架整理從基礎到實戰(三)

2019年末史上最全Vue框架整理從基礎到實戰(四)

2019年末史上最全Vue框架整理從基礎到實戰(五)

相關文章
相關標籤/搜索