先点赞后关注,养成习惯再看。
寄语:没有一个冬天不会过去,没有一个春天不会到来。

前言

在前面vue的一些博客中,我们几乎将vue的基础差不多学习完了,而从本篇博客开始将会进入到vue的另一个阶段性学习,本篇博客的内容在以后的vue项目中占很大的比重,所以小伙伴们需要认真学习,本篇博客的内容也比较简单,看过我博客的人都知道我所写的每一篇博客都是非常的详细的,所以大家不要担心学不会。我会尽量将所学的知识讲解的通俗易懂,让大家学习起来更加快乐,那么一起来看看吧!

学完你可以得到什么

  • 学会使用全局组件和局部组件
  • 学会ref引用

初识组件

解释:

组件系统是 Vue 的另一个重要概念,因为它是一种抽象,允许我们使用小型、独立和通常可复用的组件构建大型应用。仔细想想,几乎任意类型的应用界面都可以抽象为一个组件树。

组件单元分割

组件单元分割

组件通常可以用来制作单页应用程序(SPA)

组件的话我们主要分为两类分别是:

局部组件和全局组件

全局组件

全局组件毫无疑问,肯定是很多地方都可以访问的了。
语法:

1Vue.component('组件名',{2template:'模板'3})
全局组件注册方式一
 1<!DOCTYPE html> 2<html> 3    <head> 4        <meta charset="UTF-8"> 5        <title>全局组件注册方式一</title> 6    </head> 7    <body> 8        <div id="app"> 9            <t1></t1>10        </div>11        <div id="demo">12            <t1></t1>13        </div>14        <script type="text/template" id="template1">15            <div>这是一个组件</div>16        </script>17        <script src="../js/vue.js" type="text/javascript" charset="utf-8"></script>18        <script type="text/javascript">19            Vue.component('t1',{20                template:'#template1'21            })22            let vm=new Vue({23                el:'#app'24            })25            let d=new Vue({26                el:'#demo'27            })28        </script>29    </body>30</html>

首先我们使用script标签来定义模板然后将模板在组件中注册,在这里我们定义了两个vue实例,发现在demo和app中都可以使用,证明全局组件注册成功了,这是定义组件的第一种方法,接下来我们学习第二种。

全局组件注册方式二
 1<!DOCTYPE html> 2<html> 3    <head> 4        <meta charset="UTF-8"> 5        <title></title> 6    </head> 7    <body> 8        <div id="app"> 9            <temp></temp>10        </div>11        <template id="template1">12            <div>这是一个组件</div>13        </template>14        <div id="demo">15            <temp></temp>16        </div>17        <script src="../js/vue.js" type="text/javascript" charset="utf-8"></script>18        <script type="text/javascript">19            Vue.component('temp',{20                template:'#template1'21            })22            let vm=new Vue({23                el:'#app',24                data:{2526                },27                methods:{2829                },30                computed:{3132                }33            })34            let app=new Vue({35                el:'#demo'36            })37        </script>38    </body>39</html>

第二种方法我们直接使用vue提供的template标签定义模板然后再组件中注册就可以了。

全局组件注册方式三
 1<!DOCTYPE html> 2<html> 3    <head> 4        <meta charset="UTF-8"> 5        <title></title> 6    </head> 7    <body> 8        <div id="app"> 9            <my-compent></my-compent>10        </div>11        <script src="../js/vue.js" type="text/javascript" charset="utf-8"></script>12        <script type="text/javascript">13            Vue.component('myCompent',{14                template:'<div>这是第三种定义组件的方法</div>'15            })16            let vm=new Vue({17                el:'#app',18                data:{1920                },21                methods:{2223                },24                computed:{2526                }2728            })2930        </script>31    </body>32</html>

这是第三种定义全局组件的方法,三种方法中都可以使用,主要看个人习惯,反正我是比较喜欢第三种,全局组件注册讲到这里就结束了,接下来主要讲解局部组件祖册。

局部组件

局部组件的话当然是定义在vue实例里面定义的了啦。

局部组件只在当前vue实例中有效。

局部组件注册
 1<!DOCTYPE html> 2<html> 3    <head> 4        <meta charset="UTF-8"> 5        <title>局部组件注册</title> 6    </head> 7    <body> 8        <div id="app"> 9            <hello></hello>10            <!--<hi></hi>-->11        </div>12        <div id="demo">13            <hi></hi>14            <!--<hello></hello>-->15        </div>16        <script src="../js/vue.js" type="text/javascript" charset="utf-8"></script>17        <script type="text/javascript">18            let vm1=new Vue({19                el:'#app',20                data:{2122                },23                methods:{2425                },26                computed:{2728                },29                components:{30                    'hello':{31                        template:'<div>我叫hello,你叫什么</div>'32                    }33                }34            })35            let vm2=new Vue({36                el:'#demo',37                components:{38                    'hi':{39                        template:'<div>我叫hi,你叫什么</div>'40                    }41                }42            })43        </script>44    </body>45</html>

结果的话我就不贴出来了,大家可以尝试一下,如果我们在app中使用hi组件或者在demo中使用hello组件的话。

vue将会给出警告的,因为我们注册的是局部组件,所以无法使用。

ref引用

在介绍ref引用之前,我想带大家实现一个小demo,需求是这样的,页面上共有四个按钮分别为红,黄,绿,蓝,当我们点击某个按钮的时候就显示对应的颜色,如下图所示:

当我们点击红色的时候,显示红色,依次类推,那就由我带大家实现这个小demo吧!当然还是应用组件的知识,毕竟趁热打铁。

添加组件布局
 1<!DOCTYPE html> 2<html> 3    <head> 4        <meta charset="UTF-8"> 5        <title>ref引用</title> 6        <style type="text/css"> 7            .box{ 8                width: 200px; 9                height: 200px;10                border: 2px solid black;11                margin-top: 10px;12            }13        </style>14    </head>15    <body>16        <div id="app">17            <color-template></color-template>18        </div>19        <script src="../js/vue.js" type="text/javascript" charset="utf-8"></script>20        <script type="text/javascript">21            let vm=new Vue({22                el:'#app',23                data:{2425                },26                methods:{2728                },29                computed:{3031                },32                components:{33                    colorTemplate:{34                        data(){35                            return{36                                colorArray:['red','yellow','green','blue']37                            }38                        },39                        template:`<div class="btn_group">40                            <button v-for="color in colorArray" :style="{background:color}">{{color}}</button>41                            <div class="box"></div>42                        </div>`,43                    }44                }45            })4647        </script>48    </body>49</html>

结果:

在这里我们定义了局部组件,然后在局部组件中返回了颜色对应的数组,渲染的时候将颜色渲染到对应的按钮上,并且为每个按钮绑定对应的背景颜色。

绑定事件

接下来我们为每一个按钮添加事件,然后点击的时候获取对应的颜色,我们在事件中传入对应的颜色值名称就可以

 1<!DOCTYPE html> 2<html> 3    <head> 4        <meta charset="UTF-8"> 5        <title>ref引用</title> 6        <style type="text/css"> 7            .box{ 8                width: 200px; 9                height: 200px;10                border: 2px solid black;11                margin-top: 10px;12            }13        </style>14    </head>15    <body>16        <div id="app">17            <color-template></color-template>18        </div>19        <script src="../js/vue.js" type="text/javascript" charset="utf-8"></script>20        <script type="text/javascript">21            let vm=new Vue({22                el:'#app',23                data:{2425                },26                methods:{2728                },29                computed:{3031                },32                components:{33                    colorTemplate:{34                        data(){35                            return{36                                colorArray:['red','yellow','green','blue']37                            }38                        },39                        template:`<div class="btn_group">40                            <button v-for="color in colorArray" :style="{background:color}" @click="handleClick(color)">{{color}}</button>41                            <div class="box"></div>42                        </div>`,43                        methods:{44                            handleClick(color){45                                console.log(color);46                            }47                        }48                    }49                }50            })5152        </script>53    </body>54</html>

结果:

效果图

效果图

当我们依次点击对应的按钮的时候,对应颜色的值已经取到了,当然我们现在已经实现这个功能了,但是为了巩固一下以前的知识,我也会教大家使用另一种方法来获取就是下文提到的dataset的使用。

dataset的使用

在html5中新增了data-xx的属性,我们知道data-xx可以用来存数据所以我们也可以将对应的颜色保存在data-xx中,然后通过dataset获取。

 1<!DOCTYPE html> 2<html> 3    <head> 4        <meta charset="UTF-8"> 5        <title>ref引用</title> 6        <style type="text/css"> 7            .box{ 8                width: 200px; 9                height: 200px;10                border: 2px solid black;11                margin-top: 10px;12            }13        </style>14    </head>15    <body>16        <div id="app">17            <color-template></color-template>18        </div>19        <script src="../js/vue.js" type="text/javascript" charset="utf-8"></script>20        <script type="text/javascript">21            let vm=new Vue({22                el:'#app',23                data:{2425                },26                methods:{2728                },29                computed:{3031                },32                components:{33                    colorTemplate:{34                        data(){35                            return{36                                colorArray:['red','yellow','green','blue']37                            }38                        },39                        template:`<div class="btn_group">40                            <button v-for="color in colorArray" :style="{background:color}" @click="handleClick" :data-color="color">{{color}}</button>41                            <div class="box"></div>42                        </div>`,43                        methods:{44                            handleClick(e){45                                const color=e.target.dataset.color;46                                console.log(color);47                            }48                        }49                    }50                }51            })5253        </script>54    </body>55</html>

使用这种方法也可以实现依次点击,获取对应颜色的值,结果的话和上面的结果一样,在这里我就不截图了。

实现效果

获取到对应的颜色之后我们就要实现如上的效果,现在就必须用到ref的引用了

 1<!DOCTYPE html> 2<html> 3    <head> 4        <meta charset="UTF-8"> 5        <title>ref引用</title> 6        <style type="text/css"> 7            .box{ 8                width: 200px; 9                height: 200px;10                border: 2px solid black;11                margin-top: 10px;12            }13        </style>14    </head>15    <body>16        <div id="app">17            <color-template></color-template>18        </div>19        <script src="../js/vue.js" type="text/javascript" charset="utf-8"></script>20        <script type="text/javascript">21            let vm=new Vue({22                el:'#app',23                data:{2425                },26                methods:{2728                },29                computed:{3031                },32                components:{33                    colorTemplate:{34                        data(){35                            return{36                                colorArray:['red','yellow','green','blue']37                            }38                        },39                        template:`<div class="btn_group">40                            <button v-for="color in colorArray" :style="{background:color}" @click="handleClick(color)" :data-color="color">{{color}}</button>41                            <div class="box" ref="squareBox"></div>42                        </div>`,43                        methods:{44                            handleClick(color){45                                const box=this.$refs.squareBox;46                                box.style.backgroundColor=color;47                            }48                        }49                    }50                }51            })5253        </script>54    </body>55</html>

结果:

效果的话我们已经实现了,但是我们还是不知道什么是ref,别着急,且听我一一道来。

我们知道JavaScript操作dom是非常消耗性能的

因此在vue中提供了ref来获取相应的dom元素获取方法是this.$refs获取的是所有含有ref引用的dom元素。

主要分为四种,如下实例。

单独绑定

单独绑定的话,主要就是获取相应的dom元素,就像原生的JavaScript获取元素一样或者是jQuery中的$获取元素一样,看下实例就知道了。

 1<!DOCTYPE html> 2<html> 3    <head> 4        <meta charset="UTF-8"> 5        <title>ref单独绑定</title> 6    </head> 7    <body> 8        <div id="app"> 9            <div ref="square_box" class="box"></div>10            <button @click="handleClick">获取元素</button>11        </div>12        <script src="../js/vue.js" type="text/javascript" charset="utf-8"></script>13        <script type="text/javascript">14            let vm=new Vue({15                el:'#app',16                data:{1718                },19                methods:{20                    handleClick(){21                        var dom=document.getElementsByClassName('box')[0];22                       console.log(this.$refs.square_box);23                        console.log(dom);24                    }25                },26                computed:{2728                }2930            })3132        </script>33    </body>34</html>

在这个实例中,我们使用了两种方法来获取dom元素,

一种是使用ref来获取,另一种使用原生的JavaScript来获取。

可以看到两种方法都获取到了dom元素。
结果:

绑定重复的元素
在JavaScript中,我们获取相同的节点是通过document.getElementsByClassName('节点名称')或者document.getElementByName('节点名称'),但是jQuery中使用$来获取的,返回的是一个数组,但是ref绑定多个相同的元素之后,后面绑定的会覆盖前面绑定的,这就是ref绑定元素神奇的一方面。
 1<!DOCTYPE html> 2<html> 3    <head> 4        <meta charset="UTF-8"> 5        <title>ref绑定重复的元素</title> 6    </head> 7    <body> 8        <div id="app"> 9            <div class="box" ref="v_box"></div>10            <div class="box" ref="v_box"></div>11            <button @click="hanldeClick">获取元素</button>12        </div>13        <script src="../js/vue.js" type="text/javascript" charset="utf-8"></script>14        <script type="text/javascript">15            let vm=new Vue({16                el:'#app',17                data:{1819                },20                methods:{21                    hanldeClick(){22                        var doms=document.getElementsByClassName('box');23                        console.log(doms);24                       console.log(this.$refs.v_box);25                    }26                },27                computed:{2829                }3031            })3233        </script>34    </body>35</html>

在这个示例中,我们同样使用上面的两种方法来获取元素,这样一对比结果就出来了,使用ref获取的元素只用一个,就是最后面写的会覆盖前面写的,总之无论有多个重复的元素使用ref总是会返回最后一个结果。
结果:

效果图

效果图

v-for中ref实现的效果

如果在实际项目中真的有这个需求,需要绑定多个相同的元素呢?很简单使用v-for就可以了。

 1<!DOCTYPE html> 2<html> 3    <head> 4        <meta charset="UTF-8"> 5        <title>v-for中ref实现的效果</title> 6    </head> 7    <body> 8        <div id="app"> 9            <template v-for="index of 10">10                <div class="box" ref="f_box"></div>11            </template>12            <button @click="handleClick">获取元素</button>13        </div>14        <script src="../js/vue.js" type="text/javascript" charset="utf-8"></script>15        <script type="text/javascript">16            let vm=new Vue({17                el:'#app',18                data:{1920                },21                methods:{22                    handleClick(){23                        console.log(this.$refs.f_box);24                        let doms=document.getElementsByClassName('box');25                        console.log(doms);26                    }27                },28                computed:{2930                }3132            })3334        </script>35    </body>36</html>

同样还是使用两种方法来获取节点,现在的话,我们发现使用ref在v-for循环中获取的dom元素是一个数组(集合),原生的JavaScript还是没有变和之前的一样。

效果图

效果图

绑定组件

ref强大之处不仅仅表现在前三个方面,它还可以绑定组件呢?绑定组件返回的是组件实例(组件的应用是组件的实例对象)

这个也可以说是还有一点用处,这也是ref最后需要介绍的一项。

 1<!DOCTYPE html> 2<html> 3    <head> 4        <meta charset="UTF-8"> 5        <title>ref绑定组件</title> 6    </head> 7    <body> 8        <div id="app"> 9            <hello ref="hello"></hello>10            <button @click="handleClick">获取元素</button>11        </div>12        <script src="../js/vue.js" type="text/javascript" charset="utf-8"></script>13        <script type="text/javascript">14            let vm=new Vue({15                el:'#app',16                data:{1718                },19                methods:{20                    handleClick(){21                        console.log(this.$refs.hello);22                    }23                },24                computed:{2526                },27                components:{28                    'hello':{29                        'template':'<div>你好</div>',30                    }31                }32            })33        </script>34    </body>35</html>

结果:

效果图

效果图

可以看到ref绑定组件返回组件实例,ref的使用到这里我就已经讲解完了,总体来说ref还是比较简单的。

结尾

如果觉得本篇文章对您有用的话,麻烦您给笔者点亮那个点赞按钮

对于二太子木吒(一只流浪的KK)这个暖男来说:真的非常有用,您的支持就是我前进的动力,我们下篇文章见。

注意:博客园、CSDN等其它网站上含有一只流浪的KK的呢称,均属于笔者,至于为什么使用二太子木吒这个昵称,我觉得到时候会有相关文章进行解释。

作者:一只流浪的KK|二太子木吒

原创不易,请勿白嫖。
二太子木吒,一个在互联网前端苟且偷生的小白一枚,专注于前端开发,善于分享技术。
如需转载,请联系作者或者保留原文链接,微信公众号搜索二太子木吒

杨戬
46 声望7 粉丝

学习编程不仅要有深度也要有广度