1. 程式人生 > 其它 >Vue深入-8【元件註冊、父子元件通訊】

Vue深入-8【元件註冊、父子元件通訊】

技術標籤:Vuevue

(1).註冊元件的兩種方式

1.全域性註冊元件

<script>
    Vue.component('my-cmp',{
        template:'<div>我的全域性註冊元件</div>'
    })
</script>

2.區域性註冊元件

let myLocalCmp={
    template:'<div>我的區域性註冊元件</div>'
}
new Vue({
    el:'#app',
    components:{
        myLocalCmp
    }
})

3.元件解析

元件就是個物件

通過vue-loder解析的物件

<template>
    <div>Test</div>
</template>
<script>
import App from './App';
console.log(App)
</script>

(2).jsx配合render註冊元件中的html

1.render

也可以在render中直接輸出html,下面這麼寫會報錯

Vue.component('my-cmp',{
    render(h){
        renturn(
            <h1>hello</h1>
        )
    }
})

這裡必須要寫到元件中經過babel編譯(下方就用cli了),且要禁用規則或者呼叫一下h才不會報錯

<script>
    export default{
        render(h){
            console.log(h);
            return(
                <h1>App</h1>
            )
        }
    }
</script

(3).render的h函式註冊元件中的html

h函式中有三個引數,第一個為標籤名,第二個為類名/id等,第三個為巢狀

1.第三個引數

基礎用法

h的第三個引數就是為巢狀關係(兒子)

如果有多個會將多個拼接在一起

<script>
    export default{
        render(h){
            return h('h1',{},['Test1','Test2'])
        }
    }
</script>


巢狀標籤

<script>
    export default{
        render(h){
            return h('h1',{},[
                h('span',{},'這是一個span')
            ])
        }
    }
</script>

迴圈建立

<scipt>
    export default{
        data(){
            return{
                items:['span1','span2']
            }
        },
        render(h){
            return h('h1',{},this.items.map((item)=>{
                return h('span',{},item)
            }))
        }
    }
</script>

2.第二個引數

可以寫類名/id/樣式等等

記得駝峰或者橫槓

<script>
    export default{
        render(h){
            return h('h1',{
                //類名
                class:{
                    test:true,
                    'another-class':true
                },
                //樣式
                style:{
                    color:'red',
                    fontSize:'100px'
                },
                //id
                attrs:{
                    id:'test'
                },
                //事件響應
                on:{
                    click:this.xx
                }
            })
        }
    }
</script>

(4).父子元件通訊

1.引入標籤傳值通訊

<template>
    <div>
        <h1>父親</h1>
        <Child :message="message"/>
    </div>
</template>
<script>
    import Child from './Child';
    export default{
        components:{
            Child
        },
        data(){
            return{
                message:'Hello Parent'
            }
        }
    }
</script>

<template>
    <div>
        <h1>孩子</h1>
        <p>{{message}}</p>
    </div>
</template>
<script>
    export default{
        props:['message']
    }
</script> 

2.$emit通訊

<template>
    <div>
        <h1>父親</h1>
        <Child :message="message" @changeMessage="message=$event"/>
    </div>
</template>
<script>
    import Child from './Child';
    export default{
        components:{
            Child
        },
        data(){
            return{
                message:'Hello Parent'
            }
        }
    }
</script>

<template>
    <div>
        <h1>孩子</h1>
        <p>{{message}}</p>
        <button @click="handleClick">按鈕</button>
    </div>
</template>
<script>
    export default{
        props:['message'],
        methods:{
            handleClick(){
                this.$emit('changeMessage','Bye')
            }
        }
    }
</script>

3.直接將函式傳遞下去

這裡vue會將this傳遞下去

<template>
    <div>
        <h1>父親</h1>
        <Child :message="message" :changeMessageFn="changeMessage"/>
    </div>
</template>
<script>
    import Child from './Child';
    export default{
        components:{
            Child
        },
        data(){
            return{
                message:'Hello Parent'
            }
        },
        methods:{
            changeMessage(value){
                this.message = value
            }
        }
    }
</script>

<template>
    <div>
        <h1>孩子</h1>
        <p>{{message}}</p>
        <button @click="changeMessageFn('回撥函式')">按鈕</button>
    </div>
</template>
<script>
    export default{
        props:['message','changeMessageFn'],
        methods:{
            handleClick(){
                this.$emit('changeMessage','Bye')
            }
        }
    }
</script>   

需要注意

data和props在初始化的時候會做合併,如果重名會報錯

<script>
    export default{
        data(){
            return {
                message:'data裡的message'
            }
        },
        props:['message','changeMessageFn'],
        methods:{
            handleClick(){
                this.$emit('changeMessage','Bye')
            }
        }
    }
</script>

4.$children訪問兒子data

<template>
    <div>
        <h1>父親</h1>
        <p>{{message}}</p>
        <button @click="changeChildNumber">按鈕</button>
        <Child/>
    </div>
</template>
<script>
    import Child from './Child';
    export default{
        components:{
            Child
        },
        data(){
            return{
                message:'Hello Parent'
            }
        },
        methods:{
            changeChildNumber(){
                this.$children[0].number = 50
            }
        }
    }
</script>

<template>
    <div>
        <h1>孩子</h1>
        <p>{{number}}</p>
    </div>
</template>
<script>
    export default{
        data(){
            return{
                nmber:30
            }
        }
      
    }
</script> 

$children的順序是不一定的,所以節制呼叫

5.通過$parent來訪問父例項

<template>
    <div>
        <h1>孩子</h1>
        <p>{{parentMessage}}</p>
    </div>
</template>
<script>
    export defalut{
        data(){
            return {
                number:10
            }
        },
        computed:{
            parentMessage(){
                return this.$parent.message
            }
        }
    }
</script>

同時也可以獲取到父元件的名稱

this.$parent.$options.name

$parent $children是沒什麼用的,通常用於元件庫去查詢到父元件的名稱

6.provide,inject

所有inject都可以獲取到provide宣告的值,無論是什麼層級的元件

<template>
    <div>
        <h1>父親</h1>
        <Child/>
    </div>
</template>
<script>
    import Child from './Child';
    export default{
        provide:{
            message:'Hello Parent'
        },
        components:{
            Child
        }
    }
</script>

<template>
    <div>
        <h1>孩子</h1>
        {{message}}
        <GrandChild/>
    </div>
</template>
<script>
    import GrandChild from './GrandChild'
    export default{
        inject:['message'],
        components:{
            GrandChild
        }
    }
</script>

<template>
    <div>
        <h1>孫子</h1>
        {{message}}
    </div>
</template>
<script>

    export default{
        inject:['message']
    }
</script>

7.$attrs $listeners

1.$attrs 和v-bind

$attrs可以不接收父親的data,儲存在attrs中傳遞給孫子

<template>
    <div>
        <h1>父親</h1>
        <p>姓名:{{name}}</p>
        <p>年齡:{{age}}</p>
        <Child :name="name" :age="age"/>
    </div>
</template>
<script>
    import Child from './Child';
    export default{
        components:{
            Child
        },
        data(){
            return {
                name:'zza',
                age:20
            }
        }
    }
</script>

<template>
    <div>
        <h1>孩子</h1>
        <GrandChild v-bind="$attrs"/> //這裡的v-bind就是簡化了引數的傳遞
    </div>
</template>
<script>
    import GrandChild from './GrandChild';
    export default{
        components:{
            GrandChild
        }
    }
</script>

<template>
    <div>
        <h1>孫子</h1>
        {{name}}
        {{age}}
    </div>
</template>
<script>

    export default{
        props:['name','age']
    }
</script>

$listeners監聽父親監聽器觸發的函式

觸發父級繫結的事件處理函

<template>
    <div>
        <h1>父親</h1>
        <p>姓名:{{name}}</p>
        <p>年齡:{{age}}</p>
        <Child :name="name" :age="age" @test="changeName"/>
    </div>
</template>
<script>
    import Child from './Child';
    export default{
        components:{
            Child
        },
        data(){
            return {
                name:'zza',
                age:20
            }
        },
        methods:{
            changeName(){
                this.name='小夏'
            }
        }
    }
</script>

<template>
    <div>
        <h1>孩子</h1>
        <button @click="$listeners.test">按鈕</button>
      
    </div>
</template>

8.$refs.childComp

引用元件事件

<template>
    <div>
        <h1>父親</h1>
         <button @click="changeAge">按鈕</button>
        <Child ref="childComp"/>
    </div>
</template>
<script>
    import Child from './Child';
    export default{
        components:{
            Child
        },
        methods:{
            changeAge(){
                console.log('before',this.$refs.childComp.age)//20
                this.$refs.childComp.changeAge();
                 console.log('before',this.$refs.childComp.age)//50
            }
        }
    }
</script>

<template>
    <div>
        <h1>孩子</h1>
        <button>按鈕</button>
      
    </div>
</template>
<script>
    export default{
        data(){
            return {
                age:20
            }
        },
        methods:{
            changeAge(){
                this.age=50
            }
        }
    }
</script>

$ref也可以獲取dom

<template>
    <div>
        
        <div ref="mydiv"></div>
    </div>
</template>
<script>
mounted(){
    console.log(this.$refs.myDiv)
    this.$refs.myDiv.innerHtml="Hello"
}
</script