Web前端-Vue--组件

组件

1.全局组件     在所有被vue挂载的页面目标中都可以使用

        全局组件的渲染

         Vue.component("组件标签名称",{
            //组件的封装信息
            template:"组件显示的页面html",
//            data: 组件使用的变量
            methods:{
                组件的事件驱动函数

            }
         })
       组件的优点:
                提高了页面代码的复用率 因为组件可以反复使用

                后期维护更方便


       全局组件 是 所有被Vue对象挂载的目标里面都可以使用的组件

       注意:
            组件的标签内部不能写任何内容  写了也会被覆盖  不会渲染到页面
            除非使用 slot插槽(后面讲)


          组件标签的行内样式 也同样会生效 但是不推荐
          建议在组件的template模板里面写
          因为组件要多次复用  在模板里面写 所有引入该组件的地方都会生效

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">

    <h1>{{msg}}</h1>

    <!--在页面使用组件-->
      <aaa >
          <!--此处内容不会被渲染-->
          哈哈,我是aaa组件标签的内部内容
      </aaa>
        <bbb></bbb>
        <bbb></bbb>
        <bbb></bbb>

</div>

<div id="box">
    <h1>{{msg}}</h1>
    <aaa></aaa>
    <aaa></aaa>
    <bbb></bbb>
    <bbb></bbb>

</div>
<script src="js/vue.js"></script>
<script>

//        注册全局组件
        Vue.component("aaa",{
//                        推荐在这写样式
            template:"<h1 style='font-size: 100px;'>我是aaa组件的页面模板</h1>"



        })


        Vue.component("bbb",{
            template:"<ul><li>我是第一条</li><li>唐雪案终于平反</li></ul>"


        })


        var vm=new Vue({
            el:'#app',
            data:{
                msg:'我是app的vue对象挂载的目标',
            }
        })
    const vm1=new Vue({
        el:"#box",
        data:{
            msg:"我是box的vue对象挂载的目标"
        }
    })
</script>
</body>
</html>

2.局部组件(使用的最多)

 所谓的局部组件
            就是在那个Vue对象里面注册的  就只能在那个Vue挂载的目标里面使用


          如何注册局部组件:

                在Vue对象的大括号里面写上
                    components:{
                           组件标签名:{
//                            组件的配置对象

                           }     

              }

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
        <h1>{{msg}}</h1>
        <aaa></aaa>
        <aaa></aaa>

</div>
<div id="box">
    <h1>{{msg}}</h1>
    <!--<aaa></aaa>  报错 不存在这个组件 因为aaa是vm对象的局部组件-->

    <bbb></bbb>
</div>

<script src="js/vue.js"></script>
<script>

        var vm=new Vue({
            el:'#app',
            data:{
                msg:'我是app的vue',
            },
            components:{
                aaa:{
                    template:"<ul><li>我是第一条</li><li>唐雪案终于平反</li></ul>"


                }

            }
        });

        const vm1=new Vue({
            el:"#box",
            data:{
                msg:"我说box的vue"

            },
            components:{
                bbb:{
                    template:"<ol><li>我是bbb第一条</li><li>唐雪案bbb终于平反</li></ol>"
                }

            }

        })
</script>
</body>
</html>

组件的变量数据和事件的使用:

1.组件所渲染的变量
                在组件的配置大括号里面定义data
                data必须是一个函数
                这个函数必须return一个大括号
                在大括号里面定义变量

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
        <h1>{{msg}}</h1>
        <aaa></aaa>
        <aaa></aaa>
        <aaa></aaa>
        <v-qq></v-qq>

</div>
<script src="js/vue.js"></script>
<script>

    Vue.component("aaa",{
        template:"<h1 @click='show'>我是aaa组件的模板----{{msg}}---{{str}}</h1>",
        data:function(){
            return{
                msg:"我是组件的msg变量",
                str:"我是第二个变量"

            }
        },
       /* data:{
            msg:"呵呵"  这种格式不对
        }
*/
       methods:{
           show(){
               alert("我是aaa组件的点击事件")
           }
       }


    })

        var vm=new Vue({
            el:'#app',
            data:{
                msg:'我是app的vue代码',
            },
            components:{
               "v-qq":{
                   template:"<h1 @click='show'>我是v-qq组件---{{msg}}</h1>",
                   data(){
                       return{
                           msg:"我是qq组件数据"
                       }
                   },
                   methods:{
                       show(){
                           alert("我是qq组件的点击事件")
                       }
                   }

                }

            }
        });

</script>
</body>
</html>

template属性

    *        如果没定义该属性 则Vue对象的默认页面就是el的挂载目标所在的html部分为默认页面
    *
    *       但是一旦定义template 那么会把template里面的模板页面直接覆盖el的挂载目标
    *           甚至连挂载目标本身都没有了 直接全部覆盖

        组件的模板必须至少包含一个根元素
        也就是说 组件的模板最外层必须是单个元素
        里面包含着可以有很多兄弟元素

解决代码过长:

        1.字符串作为template的值  作为页面模板

        2.反引号 模板字符串 作为template的值


        3.利用template标签(推荐使用)
               在vue的挂载目标之外  定义template标签
                内部定义组件的模板内容
                给template标签添加id
                在组件的template属性写上值:  #template标签的id即可

<template id="aa">
    <div>

        <h1>我是aaa组件</h1>
        <ol>
            <li>我是新闻1</li>
            <li>奥利给</li>
            <li>新闻3</li>
        </ol>

    </div>
</template>


<div id="app">




        <aaa></aaa>

</div>
<script src="js/vue.js"></script>
<script>
        Vue.component("aaa",{
//            1.字符串页面模板
//            template:"<h1>我是aaa组件</h1>",
//            2.利用ES6的反引号 模板字符串
            /*template:`
                <div>
                    <h1>我是h1</h1>
                     <ul>
                        <li>我是列表1</li>
                        <li>我是2</li>
                        <li>我不是3</li>

                       </ul>

                </div>

            `,*/

//            3.利用template标签关联组件的模板
            template:"#aa"


        })

        var vm=new Vue({
            el:'#app',
            data:{
                msg:'Hello Vue!',
            }
        });
</script>

子组件的渲染方式:

    *       1.在指定的组件的大括号里面 定义components属性
    *
    *       2.在components的大括号里面 定义一个键
    *
    *       3.键名就是子组件的标签名  值是一个json
    *
    *       4.在子组件的json里面配置 template data  methods
    *
    *       子组件就只能在父组件的模板里面使用
    *       出了父组件 再也找不到这个组件

<template id="parent">

    <div>
        <h1>我是parent父组件的模板</h1>
        <ol>
            <li>我是父组件的列表1</li>
            <li>我是列表2</li>
            <li>我是3</li>
        </ol>

        <!--在父组件的模板里面 引入子组件标签-->
        <child></child>

    </div>
</template>

<template id="child">
    <div>
        <h2>我是child子组件的模板</h2>
        <ol>
            <li>我是子组件的列表1</li>
            <li>我是列表2</li>
            <li>我是3</li>
        </ol>
    </div>
</template>

<div id="app">
        <parent></parent>
        <!--<child></child>  报错  因为 child是parent的子组件
            只能在parent的template模板里面引入

        -->
</div>
<script src="js/vue.js"></script>
<script>

    Vue.component("parent",{
        template:"#parent",
//        定义子组件
        components:{
            child:{
                template:"#child",

            }
        }
    })



        var vm=new Vue({
            el:'#app',
            data:{
                msg:'Hello Vue!',
            }
        });
</script>

 通过component标签能够实现渲染指定组件

            component标签是vue特有的  所以必须写到vue里面
         component  标签的is属性 值是一个组件的标签名
         is=哪个组件的标签名 就渲染哪个组件
         如果把 is用v-bind指令绑定 就可以实现动态切换显示的组件

<template id="index">
    <div>
        <h1>我是首页</h1>
        <ul>
            <li>猜你喜欢</li>
            <li>限时抢购</li>
            <li>今日推荐</li>
        </ul>
    </div>
</template>
<template id="gwc">
    <div>
        <h1>我是购物车</h1>
        <ul>
            <li>商品1</li>
            <li>商品2</li>
            <li>商品3</li>
        </ul>
    </div>
</template>
<template id="user">
    <div>
        <h1>我是个人中心</h1>
        <ul>
            <li>修改密码</li>
            <li>VIP板栗</li>
            <li>退出登录</li>
        </ul>
    </div>
</template>


<div id="app">
        <!--<component is="user"></component>-->
   <p>
        <button @click="show(index)" v-for="(item,index) in btnArr">{{item}}</button>

   </p>
    <component :is="msg"></component>

</div>

<script src="js/vue.js"></script>
<script>

    Vue.component("index",{
        template:"#index"
    })

    Vue.component("gwc",{
        template:"#gwc"
    })

    Vue.component("user",{
        template:"#user"
    })

    var vm=new Vue({
            el:'#app',
            data:{
                msg:"index",
                btnArr:["首页","购物车","个人中心"]
            },
            methods:{
                show(index){
                   if(index==0){
                       this.msg="index"

                   }else if(index==1){
                       this.msg="gwc"


                   }else if(index==2){
                        this.msg="user"
                   }
                }
            }
        });
</script>

slot插槽

    *   我们之前学习组件时 就说到了 组件标签内部所有的内容
    *   在组件加载出来后 都会被覆盖掉 再也找不到
    *   但是如果这个组件不是我们封装的
    *   我们在使用时 需要插入一些自定义内容 根本无法实现
    *
    *   所以Vue为了能够让组件实现封装后 别人也能插入内容
    *   也就是 组件标签内部的内容做一个保留
    *   推出了一个人slot插槽
    *
    *   在组件模板中 自己找个位置  定义slot标签
    *   这样 以后 该组件在使用时 内部所有嵌套的内容
    *   自动被保存 并放到模板的slot标签的那个位置
    *
    *   slot标签只能使用一次  也就是所保留的内容只能渲染一次
    *
    *   slot标签默认的就是会 把组件标签内部的所有内容  都保留下来
    *   但是如果只想保留一部分 或者 分批次保留呢?
    *
    *   那么就要通过 name和slot属性做对应
    *
    *   步骤:
    *       1.把想保留你的页面的父元素  加一个slot属性
    *               等于一个自己起的名字
    *
    *        2.在组件模板里面  定义slot标签  name属性等于刚才外部起的那个slot名字
    *
    *        就实现了保留指定元素的效果
    *
    *        多个部分可以起不同的slot名字  进行不同位置的保留

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<template id="bbb">
    <h1>我是bbb组件的内容</h1>
</template>

<template id="aaa">
    <div>

        <h1>我是一个aaa组件</h1>
        <!--<slot></slot>-->
        <slot name="a"></slot>
        <ul>
            <li>奥利给</li>
            <li>奥利奥</li>
            <li>泡一泡</li>
        </ul>

        <!--<slot></slot>-->

        <!--<child></child>-->

        <slot name="b"></slot>
        <!--<slot name="b"></slot> 只能保留一次-->
    </div>
</template>


<div id="app">
        <!--<aaa>
            <ol>
                <li>我是要放入这个自定义组件内部的内容1</li>
                <li>我是内容2</li>
            </ol>
        </aaa>-->

    <!--<aaa>
        <bbb></bbb>
        哈哈

    </aaa>-->

    <aaa>
        <dl slot="a">
            <dt>四大坚果</dt>
            <dd>花生</dd>
            <dd>瓜子</dd>
            <dd>烤鱼片</dd>
            <dd>把脚收一下</dd>
        </dl>

        <ol slot="b">
            <li>2020年</li>
            <li>哈哈哈</li>
        </ol>
    </aaa>
</div>
<script src="js/vue.js"></script>
<script>
        Vue.component("bbb",{
            template:"#bbb"


        })
        Vue.component("aaa",{
            template:"#aaa",


        })

        var vm=new Vue({
            el:'#app',
            data:{
                msg:'Hello Vue!',
            }
        });
</script>

父组件给子组件传参

    *   父组件的变量zai9子组件无法直接使用
    *   所以我们要使用 父组件给子组件传参的方式 让数据传给子组件使用
    *
    *   父-->子传参的步骤:
    *   1.在父组件的模板里面 找到子组件标签
    *
    *   2.给这个子组件标签通过v-bind绑定一个自定义属性(属性名自己起)
    *
    *   3.绑定的这个自定义属性的值就是父组件要传给子组件的变量
    *
    *   4.在子组件的对象大括号里面 定义props
    *
    *   5.props的值有两种格式:
    *       1.props:["qq"]   值是一个数组  数组里面都是字符串元素
    *                       每一个字符串就是父组件模板中 给子组件标签绑定的那个自定义属性名
    *
    *                   这个自定义属性  就可以直接当做当前子组件date里面的一个变量
    *                      直接可以在子组件页面上渲染使用
    *
    *       2.props:{
    *           那个自定义属性名:大写的传过来的值的类型名称,
    *           那个自定义属性名:大写的传过来的值的类型名称,
    *
    *       }
    *       props:{
    *           自定义属性名1:String,
    *           自定义属性名:Number,
    *
    *       }


    *   传给子组件的变量 在父组件 值发生改变时 会自动再次传给子组件
    *   让子组件也跟着更新

<template id="parent">
    <div>
        <h1 @click="show">我是父组件的模板----{{msg_parent}}----{{num_parent}}</h1>
        <ul>
            <li >我是父组件数据1</li>
            <li>奥利给</li>
            <li>哈哈</li>
        </ul>

        <child :qq="msg_parent" :ww="num_parent">

        </child>
    </div>
</template>

<template id="child">
    <div>

        <h1>我是子组件的模板-----{{qq}}----{{ww}}</h1>
        <ul>
            <li>我是子组件数据1</li>
            <li>我也是2</li>
            <li>嘿嘿</li>
        </ul>
    </div>

</template>
<div id="app">
        <parent></parent>


</div>
<script src="js/vue.js"></script>
<script>

        Vue.component("parent",{
            template:"#parent",
            data(){
                return{
                    msg_parent:"我是父组件的变量数据",
                    num_parent:56
                }
            },
            methods:{
                show(){
//                    点击父组件 把 数据改变
                    this.msg_parent="我是新改变的父组件数据"

                }
            },

            components:{
                child:{
                    template:"#child",
//                    注册 子组件标签上面绑定的那个自定义属性
//                    props:["qq","ww"]
                    props:{
                        qq:String,
                        ww:Number
//
                    }
                }
            }
        })

        var vm=new Vue({
            el:'#app',
            data:{

            }
        });

</script>

子组件给父组件传参

        子组件的变量无法在父组件中直接使用
        所以需要子组件给父组件传参

        子组件--->父组件传参的步骤:

            前提: 子组件给父组件传参必须依靠一个子组件的事件驱动(点击事件 鼠标移入 键盘按下等等等等等等)
        1.给子组件添加一个事件(什么事件都行 看具体需求)

        2.在事件驱动函数里面  调用  this.$emit()方法
        3.this.$emit("自己起一个事件名称 随便什么名字",要给父组件传过去的变量数据);
        4.在父组件的模板里面 找到子组件标签
        5.给子组件标签 通过v-on绑定 $emit第一个参数的这个事件
                @$emit第一个参数的名称="父组件的methods里面的一个驱动函数"

        6.通过绑定事件  关联一个父组件的驱动函数

        7.这个驱动函数第一个参数对应的就是$emit第二个参数  也就是那个传过来的变量

        8.这个时候这个变量还无法直接渲染到父组件页面

        9.在父组件的data里面定义一个变量 作为转接

        10.在父组件对应的驱动函数被触发时   直接在驱动函数里面 给data的变量赋值

        11.而data变量就可以直接渲染在父组件的页面上了

ps:
        如果子组件的数据发生改变 但是没有重新执行$emit 那么父组件是无法接受到改变的

<template id="parent">
    <div>
        <h1 >我是父组件的模板----{{parent_aa}}</h1>
        <ul>
            <li >我是父组件数据1</li>
            <li>奥利给</li>
            <li>哈哈</li>
        </ul>

        <child @child_event="parent_method">

        </child>
    </div>
</template>

<template id="child">
    <div>

        <h1 @click="show">我是子组件的模板----{{msg_child}}</h1>
        <ul @click="change">
            <li>我是子组件数据1</li>
            <li>我也是2</li>
            <li>嘿嘿</li>
        </ul>
    </div>

</template>
<div id="app">
        <parent></parent>

</div>
<script src="js/vue.js"></script>
<script>
        Vue.component("parent",{
            template:"#parent",
            data(){
                return{
                    parent_aa:""
                }
            },
            methods:{

                parent_method(a){
//                    这句话是$emit方法触发的  第一个参数 就是子组件穿过来的数据
                    console.log("父组件的驱动函数被触发,接收第一个参数:",a);
                    this.parent_aa=a;  //给data变量赋值 让data里面的变量渲染页面

                }

            },

            components:{
                child:{
                    template:"#child",
                    data(){
                        return {
                            msg_child:"我是子组件的变量数据"
                        }
                    },
                    methods:{
                        show(){
//                            给父组件传参的方法
                            this.$emit("child_event",this.msg_child)
                        },
                        change(){
//                            改变this.msg_child变量的数据  但是不$emit
                            this.msg_child="子组件新数据";
//                            如果只是改变子组件本身数据 而不重新执行$emit 那么父组件不会接受改变


//                            this.$emit("child_event",this.msg_child);//更新一下父组件的数据

                        }
                    }
                }
            }
        })

        var vm=new Vue({
            el:'#app',
            data:{

            }
        });

</script>

父组件调用子组件的方法

    methods:{
      parentMethod() {
        console.log(this.$refs.child1) //返回的是一个vue对象,所以可以直接调用其方法
        this.$refs.child1.childMethod(this.flag); 
      }
    }


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值