組件(5):雜項

組件引用 —— ref、$refs

給子組件或者原始DOM加上ref特性,就能夠爲其聲明引用標記,添加引用後,能夠在Javascript中使用vm|this.$refs.refname獲取子組件或原始DOM。如果原始DOM,則效果如document.querySelector(ele);如果子組件,則結果爲一個VueComponent實例對象javascript

Vue.component('component-1', {
    props: ['subProp'],
    data: function () {
        return {
            subData: "child\'s data"
        }
    },
    template: '<div>子組件內容</div>'
})
Vue.component('component-2', {
    template: '<li>sub component</li>'
})
var vm = new Vue({
    el: '#app-1',
    data: {
        message: "send child\'s props",
        subPropVal: "default",
        subDataVal: "default",
        commonDomVal: "default",
        items: [
            { id: '1', case: 'piece' },
            { id: '2', case: '處刑之塔' },
            { id: '3', case: '獵殺聯盟行動' }
        ]
    },
    methods: {
        setVal: function () {
            this.subDataVal = this.$refs.child.subData
            this.subPropVal = this.$refs.child.subProp
            this.commonDomVal = this.$refs.common.value
            console.log(this.$refs.child)
            console.log(this.$refs.item)
            console.log(this.$refs.item2)
            
        },
    }
});
<div id="app-1">
    <component-1 ref="child" :sub-prop="message"></component-1>
    <input type="text" ref="common" value="normal DOM element" />
    <button @click="setVal">取值</button>
    <br>
    <span>獲取子組件data屬性[{{subDataVal}}]</span>
    <br>
    <span>獲取子組件prop特性[{{subPropVal}}]</span>
    <br>
    <span>獲取普通DOM元素值[{{commonDomVal}}]</span>
    <br>

    <ul v-for="item in items">
        <li ref="item">{{item.case}}</li>
    </ul>

    <ul v-for="item in items">
        <component-2 ref="item2"></component-2>
    </ul>
</div>

clipboard.png

父組件數據定義:messagesubPropValsubDataValcommonDomVal和一個數組items
子組件一中定義有:propssubProp、datasubDatavue

咱們在一個組件<component-1>和一個原始input上添加了ref特性,並把父組件的message經過Prop傳遞給子組件的subProp
如今,就能夠在綁定的按鈕單擊事件的回調中,經過this.$refs獲取組件和原始DOM的信息了,這些信息包括子組件的propsdatainput元素的valuejava

clipboard.png

若是和v-for一塊兒使用,那麼this.$refs.refname返回的是一個數組,引用原始DOM爲一個原始DOM的數組,引用子組件爲一個VueComponent數組,如在上面的例子中使用v-for&ref把輸出打印在控制檯以下:react

clipboard.png

混入(Mixins)

在Vue中沒有通用的API來實現組件繼承的,但也有一些手段能夠重複利用那些多個組件中相同的功能,好比這裏的Mixin。當多個組件有相同屬性或方法時,能夠抽取相同部分放入一個Mixins對象中。數組

Vue.mixin({
    created: function () {
        console.log('全局混入對象')
    }
})
var superPowersMixin = {
    data: function () {
        return {
            superPowers: false,
            //不會覆蓋組件中的`img`
            img: require('./angular.png'),
        }
    },
    methods: {
        superMe: function () {
            this.$el.classList.add("super")
            this.superPowers = true
        },
        goback: function () {
            this.$el.firstChild.innerText = 'Forever Stay Here'
        }
    },
    created: function () {
        this.$options.template =
            '<button class="btn btn-sm btn-primary" @click="goback" v-show="superPowers">Go Back</button>' +
            '<button class="btn btn-sm btn-primary" @click="superMe" v-if="!superPowers">Add Filter</button>' +
            this.$options.template
    }
}
new Vue({
    el: '#app-1',
    components: {
        vueImage: {
            data: function () {
                return { img: require('./vue.png') }
            },
            template: "<div><img :src='img' width='80' height='80'></div>",
            methods: {
                goback: function () {
                    this.$el.classList.remove("super")
                    this.superPowers = false
                }
            },
            //同名鉤子函數將混合爲一個數組,所以都將被調用。混入對象的鉤子將在組件自身鉤子以前調用。
            created: function () {
                this.$options.template = '<div>' +
                    this.$options.template +
                    '</div>'
            },
            mixins: [superPowersMixin]
        },
        reactImage: {
            data: function () {
                return { img: require('./react.png') }
            },
            template: "<div><img :src='img' width='80' height='80'></div>",
            created: function () {
                this.$options.template = '<div>' +
                    this.$options.template +
                    '</div>'
            },
            mixins: [superPowersMixin]
        }
    }
})
<style>
    .super {
        filter: hue-rotate(120deg);
    }
</style>
<div id="app-1">
    <vue-image></vue-image>
    <react-image></react-img>
</div>

clipboard.png

在以上示例混入對象中,咱們使用了屬性、模板、方法和鉤子函數,對於不一樣的選項來講,咱們有不一樣的合併規則。
整體上來說,當選項是一個對象時,咱們就合併成一個大的對象,若是對象中有重名的屬性時,咱們就丟棄混入對象中的屬性。好比爲組件vueImage添加混入時,屬性img和方法goback()就被丟棄。而鉤子函數混入和組件中的不合並,而是都執行,先執行混入中的鉤子,再執行組件中的。app

模擬繼承

利用混入能夠模擬下繼承系統。ide

var SuperClass = {
    template: '<p><button class="btn btn-sm btn-primary" @click="superMethod">Super Method</button>{{message}}</p>',
    data() {
        return {
            message: 'super class data'
        }
    },
    methods: {
        superMethod() {
            this.message = 'run super class method to change data'
        }
    }
}
var SubClass = {
    mixins: [SuperClass],
    template: '<p><button class="btn btn-sm btn-primary" @click="superMethod">Override Super Method</button>\
                  <button class="btn btn-sm btn-primary" @click="subMethod">Sub Method</button>{{message}}</p>',
    methods: {
        superMethod() {
            this.message = 'override super class method'
        },
        subMethod() {
            this.message = 'run sub class method to change data'
        }
    }
}
new Vue({
    el: '#app-2',
    components: { SuperClass, SubClass }
})
<div id="app-2">
    <super-class></super-class>
    <sub-class></sub-class>
</div>

clipboard.png

在這個例子中,爲組件subClass混入了superClass,並從superClass那裏繼承了屬性message,重寫了方法superMethod(),又添加了本身的方法subMethod()。感受能夠開發開發- -b。函數

相關文章
相關標籤/搜索