第7章-组件(二)

一、学习目标

  • 掌握props选项的用法
  • 掌握slot槽口的使用方法
  • 掌握自定义事件的使用方法
  • 能够灵活的掌握父子组件的定义与组合方法

二、props 选项的作用

2.1、props选项的作用

作用:props选项用来声明它期待获得的数据 。如图:

props本质: props为元素属性

 语法:

语法:
JS中需要在组件中定义:
    components:{
                'myHeader': {
                    template: "#head",
                    props: ['message1','message2',....] //props的定义
                }
            }
template中调用:
        <template id="head">
             <div class="headerWarp">
                <span>{{message1}}</span>  //1.与data一样,props可以用在版本中
            </div>                         //2.可以在vm实例中像 this.message 这样使用
       </template>

HTML中传入实际需要的val:
        <组件  message1='val'></组件>
    

实际例子使用:

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width,user-scalable=0,initial-scale=1.0"/>
    <title>Title</title>
    <style>
        * {margin: 0;padding: 0;}
        .headerWarp {width: 100%;height: 48px;background: #f7f7f7;
            border-bottom: 1px solid #999;}
    </style>
</head>
<body>
    <!--
        props: 定义希望接收到的值
        语法:props: ['希望接收的值',.....]
        使用:1)与data 一样,可以在模板中使用;
              2)可以在vm实例中,像 this.msg 这样去使用
        值得传入:
            HTML:<组件  希望接收的值='val'></组件>
      -->
    <div id="box">
        <my-header txt="上海" src1="img/blue.png" src2="img/chat_blue.png"></my-header>
        <my-header txt="北京"></my-header>
    </div>
    <template id="head">
        <div class="headerWarp">
            <span>{{txt}}</span>
            <!--v-bind指令缩写,也可以写成v-bind='{src:scr1}'-->
            <img :src="src1" class="headerWarp">
            <img :src="src2" class="headerWarp">
        </div>
    </template>
    <script src="js/vue.js"></script>
    <script>
        var vm = new Vue({
            el: "#box",
            data: {},
            components:{
                'myHeader': {
                    template: "#head",
                    props: ['txt','src1','src2'] //定义props,需要定义在组件内
                }
            }
        });
    </script>
</body>
props使用

小结:

  • props选项用来声明它期待获得的数据
  • 使用: 与data一样可用在模板中;可在vm实例中使用。

三、slot 槽口

slot(槽口)作用:用来混合父组件的内容与子组件的模板。是在子模板去留槽口,然后再父组件的模板中去使用槽口。

3.1、匿名槽口(slot)

说明:匿名槽口(slot),顾名思义就是不需要给这个槽口起具体的名字,直接使用slot槽口,而且名的槽口只能定义一个

语法:

//定义容器
<div id="box">
    <parent>
        <p>我是留下的不具名的槽口</p> //根据留下的不具名槽口插入内容。
    </parent>
</div>

//定义模板
<template id="p">
    <div>
        <h1>组件模板</h1>
        <slot></slot>   //定义slot不具名槽口
    </div>
</template>

具体使用:

<body>
    <div id="box">
        <parent>
            <p>我是留下的不具名的槽口</p>  <!--留下的槽口插入内容-->
        </parent>
    </div>
    <!--定义模板-->
    <template id="p">
        <div>
            <h1>组件模板</h1>
            <slot></slot> <!--定义一个不具名槽口-->
        </div>
    </template>
    <!--
        slot: 槽口,在组件封装的过程中,向外部留出的槽口,也就是可提供插入一些内容
        语法:<slot></slot>
        注意:不具名槽口只能允许插入一个
     -->
    <script src="js/vue.js"></script>
    <script>
        var vm = new Vue({
            el: "#box",
            data: {},
            components: {  //定义局部组件
                "parent": {
                    template: "#p"  //根据选择器找到模板
                }
            }
        });
    </script>
</body>
匿名槽口slot

3.2、具名槽口(slot)

  <slot>元素可以用一个特殊属性name来配置如何分发内容,多个slot槽口可以有不同的名字,具名slot槽口将匹配内容片断中有对应slot。

语法:

具名槽口:<slot name="slot_name"></slot>
匹配: <tag_name slot="slot_name"></tag_name>

 完整语法:

//定义容器
<div id="box">
    <test>
        <span slot="slot1">111111</span> //调用具名槽口
    </test>
</div>

//定义组件模板
<template id="t">
    <div>
        <h2>test</h2>
        <slot name="slot1"></slot> //定义具名槽口
    </div>
</template>

//创建vue对象
<script src="js/vue.js"></script>
<script>
    var vm = new Vue({
        el: "#box",
        data: {},
        components: { //定义局部组件
            "test": {
                template: "#t"  //调用模板
            }

        }
    });
</script>

 具体使用:

<body>
    <div id="box">
        <test>
            <img slot="leftImg" src="ic_actionbar_search_icon.png"/> //调用具名槽口
            <img slot="rightImg" src="ic_actionbar_button_icon"/>
            <span>111111</span>
        </test>
    </div>
    <!--
        slot: 槽口,在组件的封装的过程中,向外部留出槽口,也就是可供外部插入一些内容
        具名槽口:<slot name="slot_name"></slot>
        匹配: <tag_name slot="slot_name"></tag_name>
    -->
    <template id="t">
        <div>
            <h2>test</h2>
            <slot name="leftimg"></slot> //定义多个具名槽口
            <slot name="rightimg"></slot>
            <slot></slot>  //不具名槽口只能定义是一个
        </div>
    </template>
    <script src="js/vue.js"></script>
    <script>
        var vm = new Vue({
            el: "#box",
            data: {},
            components: {
                "test": {
                    template: "#t"
                }    
            }
        });
    </script>
</body>
具名槽口slot

注意:具名slot槽口可以定义多个,但是不具名slot槽口只能定义一个。

小结:

  1. slot作用:用来混合父组件的内容与子组件自己的模板
  2. 具名slot: 具名slot将匹配内容片断中有对应slot特性的元素
  3. 在使用指令时,是不是直接在slot槽口添加指令的,需要在slot外面包装一层使用指令:<span v-show="!bol"><slot name="nomalImg"></slot></span>

四、父子组件

4.1、父子组件定义

在一个实例中可以有多个局部组件,在局部组件中还可以定义它的子组件,在子组件还可以定义子组件,这个就是父子组件,定义如下:

components:{
     'parent':{  //父组件
           template: '<div></div>',
           components: {
                     'child': {  //子组件
                               template: '<div></div>'
                     }
           }
     }
}

4.2、父子组件的使用

说明:父子组件件作用域是相互独立的,子组件只能在父组件的模板中进行调用。

<body>
    <div id="box">
        <parent></parent>
    </div>
    <!--定义父组件模板-->
    <template id="p">
        <div class="tabbarWrap">
            <!--在父组件的模板中调用-->
            <child></child>
        </div>
    </template>
    <!--定义子组件模板-->
    <template id="c">
        <div class="itemWrap">
            <img src="1.png">
            <span>首页</span>
        </div>
    </template>
    <!--
        每一个组件相当于完整的vue实例,拥有绝大数的vm实例的配置项
        子组件调用:只能在父组件的模板中进行调用
    -->
    <script src="js/vue.js"></script>
    <script>
        var vm = new Vue({
            el: "#box",
            data: {},
            components: {
                //父组件
                "parent": {
                    template: "#p",
                    //定义子组件
                    components: {
                        "child": {
                            template: "#c"
                        }
                    }
                }
            }
        });
    </script>
</body>
父子组件的使用

注意事项:

  1. 父组件和子组件的作用域是相互独立的,是无法共享的。
  2. 子组件只能在父组件的模板中调用,不能直接在容器中去调用。

五、自定义事件

  之前我们都是绑定一个事件,这些事件都是我们事先定义好的,但是我们也可以自定义事件,我们通过自定义事件,可以实现父子组件之间传值。这边的步骤,首先我们子组件先抛出自定义监听事件,父组件接收自定义监听事件。

5.1、抛出自定义事件监听

语法:

this.$emit('event',val) //event事件名必须传入,val值可传可不传

 $emit: 代表着父组件的一个方法,实例方法,用来触发事件监听的。

参数:

  • event:自定义事件名陈
  • val:通过自定义事件传递的值。注:val为可选参数。
<body>
    <div id="box">
        <parent></parent>
    </div>
    <!--定义父模板-->
    <template id="p">
        <div>
            <h1>parent~~~~~~~~~~{{pMsg}}</h1>
            <child1></child1>
        </div>
    </template>
    <!--定义子模板-->
    <template id="c1">
        <!--一点击就让它传值-->
        <div @click="fn">
            <p>child1***********{{ cMsg }}</p>
        </div>
    </template>
    <!--
        子组件将值传递给父组件,叫做逆向传值,需要借助 自定义监听事件。
    -->
    <script src="js/vue.js"></script>
    <script>
        var vm = new Vue({
            el: "#box",
            data: {},
            components: {
                'parent': {
                    template: '#p',
                    data: function(){
                        return {
                            pMsg: "pppppp"
                        }
                    },
                    components: {
                        child1: {
                            template: "#c1",
                            data: function(){
                                return {
                                    cMsg: "cccc11111"
                                }
                            },
                            methods: {
                                fn: function(){
                                    //console.log(11);
                                    //自定义事件
                                    //$emit('自定义事件名称',传递的值)
                                    this.$emit('change',this.cMsg);
                                }
                            }
                        }
                    }
                }
            }
        });
    </script>
</body>
抛出自定义事件

注意:

  • 子组件将值传递给父组件,叫做你想传值,需要借助 自定义监听事件。

5.2、接收自定义事件监听

说明:子组件抛出自定义事件监听,父组件需要接收自定义事件监听,这样子组件的数据 才能传递给父组件。

语法:

<component  @event='fn'></component>
fn: function(val){
}

val: 自定义事件传递出的值

①逆向传值

说明:以上我们说的把 子组件 的 值 通过 自定义事件  传递给 父组件,这种传递方式叫  逆向传值。子组件传值 -> 父组件接收。

<body>
    <div id="box">
        <parent></parent>
    </div>
    <!--定义父模板-->
    <template id="p">
        <div>
            <h1>parent~~~~~~~~~~{{pMsg}}</h1>
            <!--父组件接收 监听事件 -->
            <child1 @change="getVal"></child1>
            <!-- 接收事件监听出,方法名后面是不写小括号的 -->
        </div>
    </template>
    <!--定义子模板-->
    <template id="c1">
        <!-- 子组件抛出监听事件 -->
        <div @click="fn">
            <p>child1***********{{ cMsg }}</p>
        </div>
    </template>
    <!--
        子组件将值传递给父组件,叫做逆向传值,需要借助 自定义监听事件。
    -->
    <script src="js/vue.js"></script>
    <script>
        var vm = new Vue({
            el: "#box",
            data: {},
            components: {
                'parent': {
                    template: '#p',
                    data: function(){
                        return {
                            pMsg: "pppppp",
                            message: ''
                        }
                    },
                    methods: {
                        getVal: function(val){
                            //val: 代表传递过来的值
                            console.log("val:" + val);
                            this.message = val; //接收自组件传递过来的值
                            console.log("message:" + this.message)
                        }
                    },
                    components: {
                        child1: {
                            template: "#c1",
                            data: function(){
                                return {
                                    cMsg: "cccc11111"
                                }
                            },
                            methods: {
                                //定义抛出自定义事件
                                fn: function(){
                                    //自定义事件
                                    //$emit('自定义事件名称',传递的值)
                                    this.$emit('change',this.cMsg); //this.cMsg传递子组件中的值
                                }
                            }
                        }
                    }
                }
            }
        });
    </script>
</body>
逆向传值

步骤: 在子组件里面定义 函数 fn -> 创建抛出自定义 事件 -> 父组件 定义接收自定义组件 -> 接收 子组件传递过来的值val。

②正向传值

说明:父组件将值传递给子组件,叫做正向传值;父组件传值 -> 子组件接收。这个时候我们子组件希望从外部得到值: props: [ ]

<body>
    <div id="box">
        <parent></parent>
    </div>
    <script src="js/vue.js"></script>
    <script>
        var vm = new Vue({
            el: "#box",
            data: {},
            components: {
                "parent": {
                    template: '<div><h1>parent</h1><child :message="msg"></child></div>', //绑定msg值
                    data: function(){
                        return {
                            msg: "p"
                        }
                    },
                    components: {
                        'child': {
                            template: "<span>child{{ message }}</span>", //接收父组件传过来的值
                            props: ['message'] //使用props
                        }
                    }
                }
            }
        });
    </script>
</body>
正向传值

注意:vue.js 中允许 正向传值,所以正向传值不需要 条件出发,是主动的。逆向传值,是不允许的,需要主动触发(主动抛出自定义事件监听)。

 

转载于:https://www.cnblogs.com/zhangqigao/p/9604086.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值