• Vue--组件


    组件化开发介绍

    WEB中的组件是页面组成的一部分,是一个具有独立逻辑的功能或界面,同时又能根据规定的接口规则进行融合,变成一个完整的应用。比如导航,列表,弹窗等。

    将一个巨大复杂的东西分成粒度合理的小东西。

    优点: 提高开发效率,方便重复使用,简化调试步骤,提升整个项目的可维护性,便于协同开发。

    Link : Element可以学习里面的组件开发

    Vue中的组件

    vue中的组件是一个自定义标签,在哪里写上这个标签就可以在这里使用即插入组件。

    基本组成:样式结构,行为逻辑,数据。

    注册组件

    分为全局注册与局部注册。

    1、全局注册

    可以在任何模板中使用

    语法:使用Vue.component("组件名", 选项对象)

    其中组件名命名约定:驼峰(camelCase)或 烤串(kebab-case)

    使用:在html中组件时必须使用烤串命名法的标签,插入组件在该位置

    例:一个简单的下拉组件

    Vue.component("pull-list",{
        template:`<section class="warp">
                <div class="searchIpt clearFix">
                    <div class="clearFix">
                        <input type="text" class="keyWord" value="" />
                        <input type="button" value="查询">
                        <span></span>
                    </div>
                    <ul class="list">
                        <li>html+css</li>
                        <li>html5+css3</li>
                        <li>javascript</li>
                        <li>vue</li>
                        <li>jquery</li>
                    </ul>
                </div>
            </section>`
    });
    new Vue({
        el:"#app",
    });

    在html中的使用:

    <div id="app">
        <h2>自定义的下拉框</h2>
        <pull-list></pull-list>    
    </div>

    受限制的元素

    在某些元素中放入了自定义标签,不符合w3标准,会解析错误。可以通过使用特殊属性 is 来解决这个问题,但还是不提倡的。

    2、局部注册

    在组件实例vm中通过在选项对象的component中注册,只在所注册的作用域使用。

    如下,将组件custom-select写在实例中,这样只能在#app中使用。如果还有一个挂载app2的实例,是不可以使用的。

    new Vue({
        el:"#app",
        component:{
            "custom-select":{
                template:`<section class="warp">
                    <div class="searchIpt clearFix">
                        <div class="clearFix">
                            <input type="text" class="keyWord" value="" />
                            <input type="button" value="查询">
                            <span></span>
                        </div>
                        <ul class="list">
                            <li>html+css</li>
                            <li>html5+css3</li>
                            <li>javascript</li>
                            <li>vue</li>
                            <li>jquery</li>
                        </ul>
                    </div>
                </section>`
            }
        }
    });  

     

    组件间的通信

    为什么通信:父组件要给子组件传递数据;子组件需要将它内部发生的事情告诉父组件。

    1、父组件 给 子组件 传递数据

    组件实例的作用域是独立的,不能在子组件直接用父组件的数据。这里#app所在可以看做父组件,custom-select为子组件。要想自定义custom-select组件里面的一些信息,比如按钮显示 搜索 而不是 查询 ,这就需要向其传递一些数据。

    <div id="app">
        <h2>自定义的下拉框1</h2>
        <custom-select></custom-select>    
        <h2>自定义的下拉框2</h2>
        <custom-select></custom-select>    
    </div>

    方法:在自定义标签上来一个自定义属性,再在子组件中用props声明这个自定义的属性名。

    step1: html中使用传值:<custom-select btn-value="查询"></custom-select>

    <div id="app">
        <h2>自定义的下拉框1</h2>
        <custom-select btn-value="查询"></custom-select>    
        <h2>自定义的下拉框2</h2>
        <custom-select btn-value="搜索"></custom-select>    
    </div>

    step2: 在组件props中声明自定义属性

    step3: template模板中绑定属性

    Vue.component("custom-select",{
                props:["btnValue"],
                template:`<section class="warp">
                    <div class="searchIpt clearFix">
                        <div class="clearFix">
                            <input type="text" class="keyWord" value="" />
                            <input type="button" :value="btnValue">
                            <span></span>
                        </div>
                        <ul class="list">
                            <li>html+css</li>
                            <li>html5+css3</li>
                            <li>javascript</li>
                            <li>vue</li>
                            <li>jquery</li>
                        </ul>
                    </div>
                </section>`
            })     

    组件选项对象的data属性

    Question:让下拉列表一开始是隐藏的状态,在点击输入框时才显示?

    用到组件的选项对象里的data属性组件中的data必须是函数。因为每个组件都是独立的,如果他们共用一个对象,在更改一个组件数据的时候,会影响其他组件;如果是函数的话,每个组件都有自己独立的数据,相互之间不会影响。

    然后通过绑定click事件来进行显隐控制,结合v-show和v-on指令实现:

    data:function(){
        return {
            selectShow:false
        };
    },
    <input type="text" class="keyWord" value="" @click="selectShow = !selectShow" />
    <custom-li v-show="selectShow"></custom-li>

    上面的<custom-li>为ul列表组件,是<custom-select>的子组件

    更多层的数据传递

    #app是<custom-select>的父组件,<custom-select>是<custom-li>的父组件。这样的传递是一层一层往内传递,依次进行即可。

    step1:实例化对象中要有数据

    data:{
        list1:["北京","上海","杭州"],
        list2:["2017-10-12","2017-10-20","2017-10-23"]
    }

    step2:html中使用组件并绑定属性

    <custom-select btn-value="查询" :list="list1"></custom-select>    
    <custom-select btn-value="搜索" :list="list2"></custom-select>    

    step3:custom-select组件选项对象的props中添加自定义属性名

    props:["btnValue","list"],

    step4:子组件<custom-li>中绑定list属性

    <custom-li v-show="selectShow" :list="list"></custom-li>

    step5:子组件添加声明自定义属性,模板中遍历list获得li

    props:["list"],
    template:`<ul class="list">
                    <li v-for="item of list">{{item}}</li>
                </ul>`

    这样就将数据传递了下来。

    2、子组件 给 父组件 传递数据

    Question: 点击列表项时相应显示在输入框里?

    父组件传递数据到子组件用到自定义属性,子组件传递数据到父组件需要用到自定义事件。

    继续上面的例子:

    step1: 在子组件的li上添加点击事件

    <li v-for="item of list" @click="selectValueHandle(item)">{{item}}</li>

    step2: 在子组件的methds里添加selectValueHandle函数,用来触发自定义事件

    selectValueHandle:function(item){
        //告知父级,改变val的值,需要触发一个自定义事件
        this.$emit("recieve",item);
    }

    step3:在父组件中的 custom-li标签 上绑定自定义事件

    <custom-li v-show="selectShow" :list="list" @recieve="changeValueHandle"></custom-li>

    step4:在父组件的methods里添加changeValueHandle函数

    changeValueHandle:function(value){
        this.val=value;
    }

    step5:将val双向绑定到input框。此时点击列表项就可以相应的显示到输入框了。

    单向数据流

    数据从父组件流向(传递给)子组件,只能单向绑定。在子组件内部不允许直接修改父组件传递过来的数据。

    如果要改的话,可以:

    1. 将从父组件传递来的数据 作为data中数据来使用,然后改data里的值。

    2.作为子组件的computed属性

    props验证

    组件可以为props绑定验证要求。如果类型不对,vue会警告。

    props:{
        count:{
            type:Number, //String,Number,Function,Object,Boolean,Array
            default:10, //默认值,不传参数时为这个值
            required:true, //count参数必须传,不然报错
            validator:function(value){ //自定义验证规则,传的必须大于10,否则报错
                return value>10;
            }
        }
    },

    内容分发

    使用一种方式混合父组件的内容和子组件自己的模板,这个过程称为内容分发。在子组件中使用特殊的<slot>元素作为内容的插槽。简单来说就是定制模板,自定义子组件中的内容。

    单个slot

    向组件的html标签中添加内容:

    <custom>
        <div>我是html标签</div>
    </custom>

    向组件模板中加入<slot>标签,即可将html中自定义的内容呈现在slot位置,没有内容则显示slot模板中的默认内容:

    template:`
        <div>
            <slot>我是默认的结构</slot>
            <p>这是第一个提醒</p>
            <p>这是第二个提醒</p>
            <p>这是第三个提醒</p>
        </div>
    `

    当然,如果将slot标签包裹整个结构,则显示为父组件的内容。

    具名slot

    slot标签可以用name属性来配置如何分发内容:

    template:`
        <div>
            <slot name="one"><p>这是第一个提醒</p></slot>
            <slot name="two"><p>这是第二个提醒</p></slot>
            <p>这是第三个提醒</p>
        </div>

    在html中对应要替换的部分:

    <custom>
        <div slot="one">我是html标签</div>
    </custom>

    这样,结果就为:

    我是html标签

    这是第二个提醒

    这是第三个提醒

    组件封装

    props参数:数据传递给组件

    slot定制模板:外部模板混合子组件模板

    event自定义事件:监控子组件交互状态

    动态组件

    多个组件可以使用同一挂载点,动态的在它们之间切换。

    使用<component>元素加is特性进行动态绑定,决定显示哪一个组件。

    使用keep-alive把切出去的组件保存在内存中,这样再次切回来时可以保留它的状态,避免重新渲染。

        <div id="app">
                <input type="button" value="切换到第1个组件" @click="tabComponent(1)" />
                <input type="button" value="切换到第2个组件" @click="tabComponent(2)"/>
                <input type="button" value="切换到第3个组件" @click="tabComponent(3)"/>
                <keep-alive>
                    <component :is="current"></component>
                </keep-alive>
            </div>
            <script>
                var custom1 = Vue.component("custom1",{
                    template:`<div @click="changeDivbg">我是第1个组件</div>`,
                    methods:{
                        changeDivbg(ev){
                            ev.target.style.background = "red";
                        }
                    }
                });
                var custom2 = Vue.component("custom2",{
                    template:`<div>我是第2个组件</div>`
                })
                 var custom3  = Vue.component("custom3",{
                    template:`<div>我是第3个组件</div>`
                })
    
                new Vue({
                    el:"#app",
                    data:{
                        current:custom1
                    },
                    methods:{
                        tabComponent(index){
                            if(index === 1){
                                this.current = custom1
                            }else if(index === 2){
                                this.current = custom2
                            }else if(index === 3){
                                this.current = custom3
                            }
                        }
                    }
                })
            </script>

    Demo:下拉选择列表组件

    <!DOCTYPE html>
    <html lang="en">
    <head>
    
        <meta charset="UTF-8">
        <title>下拉组件</title>
        <link rel="stylesheet" type="text/css" href="style.css">
        <script type="text/javascript" src="vue.js"></script>
    
    </head>
    <body>
    
        <div id="app">
            <h2>自定义的下拉选择框</h2>
            <custom-select btn-value="查询" v-bind:list="list1"></custom-select>    
            <h2>自定义的下拉选择框</h2>
            <custom-select btn-value="搜索" v-bind:list="list2"></custom-select>    
        </div>
        
        <script type="text/javascript">
    
            Vue.component("custom-select",{
                data:function(){
                    return {
                        selectShow:false,
                        val:''
                    };
                },
                props:["btnValue","list"],
                template:`<section class="warp">
                        <div class="searchIpt clearFix">
                            <div class="clearFix">
                                <input type="text" class="keyWord" value="" @click="selectShow = !selectShow" v-bind:value="val"/>
                                <input type="button" v-bind:value="btnValue">
                                <span></span>
                            </div>
                            <custom-li v-show="selectShow" v-bind:list="list"
                                v-on:recieve="changeValueHandle"
                                ></custom-li>
                        </div>
                    </section>`,
                    methods:{
                        changeValueHandle:function(value){
                            this.val=value;
                        }
                    }
    
            });
            //ul组件
            Vue.component("custom-li",{
                props:["list"],
                template:`<ul class="list">
                                <li v-for="item of list" @click="selectValueHandle(item)">{{item}}</li>
                            </ul>`,
                methods:{
                    selectValueHandle:function(item){
                        //告知父级,改变val的值,需要触发一个自定义事件
                        this.$emit("recieve",item);
                    }
                }
                
            });
    
    
            new Vue({
                el:"#app",
            data:{
                list1:["北京","上海","杭州"],
                list2:["2017-10-12","2017-10-20","2017-10-23"]
            }
            });
        </script>
    </body>
    </html>
    View Code
  • 相关阅读:
    input搜索框实时检索功能实现(超简单,核心原理请看思路即可)
    django blank 和autonow
    dwebsocket的坑
    vue 动态添加active+父子传值
    NO 2,人生苦短,我学python之python+selenium元素定位
    NO 1,人生苦短,我学python之python+selenium自动化环境搭建
    SPU与SKU概念
    数据库,缓存数据一致性常用解决方案总结
    利用注解 + 反射消除重复代码
    Nacos学习与实战
  • 原文地址:https://www.cnblogs.com/PeriHe/p/7884314.html
Copyright © 2020-2023  润新知