# 插槽

# 匿名插槽(默认插槽)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <script src="js/vue.js"></script>
</head>
<body>

<style>
*{
    margin: 0;
    padding: 0;
}
.gx-container{
    display: flex;
    flex-direction: column;
    background-color: #96bff5;
}
.gx-header{
    min-height: 60px;
    background-color: rgb(111, 161, 218);
}
.gx-main{
    flex-grow: 1;
    background-color: rgb(214, 232, 248);
}
</style>

<div id="root">

    <gx-container height="100vh">
        <gx-header></gx-header>
        <gx-main></gx-main>
    </gx-container>

</div>

<script>
//容器组件
Vue.component('gx-container',{
    props: {
        width: String,
        height: String
    },
    template: `
    <div 
    class = "gx-container"
    :style = "{width,height}"
    >
        <slot>容器</slot>
    </div>
    `
})

//头部组件
Vue.component('gx-header',{
    template: `
    <div class="gx-header">
        <slot>头部</slot>
    </div>
    `
})

//主体组件
Vue.component('gx-main',{
    template: `
    <div class="gx-main">
        <slot>主体</slot>
    </div>
    `
})

//注册一个vue控制模块
var root =new Vue({
    el: '#root'
})
</script>

</body>
</html>

匿名插槽(默认插槽)通常一个。

# 命名插槽


<div id="root">

    <gx-main>

        <template slot="head">
            <h2>头部插槽</h2>
        </template>

        <template slot="foot">
            <h2>脚部插槽</h2>
        </template>

    </gx-main>

</div>

<script>
Vue.component('gx-main',{
    template: `
    <div class="gx-main">
        <slot name="head">头部插槽</slot>
        <slot name="foot">脚部插槽</slot>
        <slot>匿名插槽</slot>
    </div>
    `
})
</script>

# 作用域插槽

作用域插件基本的原理就是 把组件内部的数据 暴露给 组件外部插槽位置,方便定制组件内部模板

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <script src="js/vue.js"></script>
</head>
<body>
<style>
ul{
    display: flex;
    margin: 0;
    padding: 0;
    list-style: none;
}
</style>

<div id="root">

    <gx-nav :data="navs">
        <template slot-scope="item">
           <a :href="item.url">{{item.icon}} -- {{item.name}}</a>
        </template>
    </gx-nav>

</div>

<script>
Vue.component('gx-nav',{
    props:{
        data: Array,
        required: true
    },
    template:`
    <ul>
        <li v-for="item in data">
            <slot v-bind="item">
                {{item.name}}
            </slot>
        </li>
    </ul>  
    `
})

var root = new Vue({
    el:'#root',
    data: {
        navs: [
            {id:1,name:'首页',icon:'★',url:'index.html'},
            {id:2,name:'关于我们',icon:'♥',url:'about.html'},
            {id:3,name:'联系我们',icon:'◆',url:'contact.html'}
        ]
    }
})
</script>

</body>
</html>

# 深度监听

当我们在组件内部防止直接改变props中的属性值,于是在data中缓存props需要改变的值。但是这样会带来一个问题,如果props中该值发生了改变,那么组件内部的变量不会更新,这个需要深度监听,也就是watch中监听这个props中的变量,然后实时同步。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <script src="js/vue.js"></script>
</head>
<body>

<div id="root">

    <gx-nav :name.sync="name"></gx-nav>
    <h2>外部:{{name}}</h2>

</div>

<script>
Vue.component('gx-nav',{
    props: {
        name: String
    },
    data(){
        return {
            Name: this.name
        }
    },
    watch: {
        name( now){
            //深度监听 外面传过来name,一旦发送改变,则同步最新的name给data中的Name
            this.Name = now;
        },
        //深度监听
        Name( now ){
            this.$emit('update:name', now );
        }
    },
    template: `
    <div>
        <h2>内部:{{Name}}</h2>
        <button @click="Name='李四'">改变传值</button>
    </div>
    `

})

var root = new Vue({
    el:'#root',
    data: {
        name:'张三'
    }
})
</script>

</body>
</html>