关于vue组件的一个小结

用vue进行开发到目前为止也有将近一年的时间了,在项目技术选型的时候隔壁组选 react的时候我们坚持使用vue作为前端的开发框架。虽然两者思想上的差异不大,但是vue的语法在代码的可读性以及后期的维护成本更加的适合,而且最近看到Apache对react的相关许可限制;这里不讨论react和vue的对比哪个好,技术框架没有最好的,只有适合项目才是最好的。

进入主题。。。。。。。

组件,是vue的核心之一。


我们可以把页面各个子模块看成一个组件,可以独立拆分出来。这样不仅维护变得简单了,而且代码复用性也高。

vue组件分为全局组件和局部组件。组件中属性和vue实例基本类似,基本可以使用其所有属性如computed,methods,components,filter,directive.....但data属性不同,在组件中data是函数,而且数据需要return出来;因为组件可能会被引用多次,就会创建多次实例,如果data是个对象的话那引用到这个组件的地方都讲公用一个data这样就回造成了数据的污染。如果使用data属性函数返回一个对象的话就可以解决这个问题,每次引入到这个组件实例的时候就可以在data函数中返回一个初始的数据对象。

组件的介绍

全局组件

使用Vue.component进行全局注册,所有vue实例都会共享此组件

 1   <div id="app">
 2         {{msg}}
 3         <const-comp></const-comp>
 4
 5     </div>
 6     <script>
 7
 8         Vue.component(‘constComp‘, {
 9             template: "<h3>我是全局组件</h3>"
10
11         });
12
13         new Vue({
14             el: "#app",
15             data: {
16                 msg: "hello component"
17             }
18         });
19
20     </script>

局部组件

局部组件只能在引入当前的vue实例中有效,在当前vue实例中components属性加上引入进来的组件实例即可

    <div id="app">
        {{msg}}
        <!-- <const-comp></const-comp> -->
        <local-comp></local-comp>
    </div>
    <script>

        /*Vue.component(‘constComp‘, {
            template: "<h3>我是全局组件</h3>"

        });*/
        let localComp = {
            template: "<div>我是局部组件</div>"
        };
        new Vue({
            el: "#app",
            data: {
                msg: "hello component"
            },
            components: {
                localComp
            }
        });

    </script>    

单文件组件(xxx.vue)

其实就是将写在js中的组件提出到一个vue文件中写而已,这样组件更加的好维护以及阅读性也会好,提取出来了相应的引入即可,不会显得文件很多行很长。

其主要有<template></template><script></script><style></style>这三个标签,每个标签做自己的事。template就像我们在html中写dom,script写js代码当前的组件实例,style写组件样式,注意:加上scoped即可使当前样式只在当前组件生效,组件渲染的时候此组件的dom会加上data-v-xxx属性来选择当前组件样式。如果没加上scoped的话当前组件的样式就会在引入这个组件的实例中造成影响

如我写的一个found.vue文件demo

 1 <template>
 2     <div>
 3         <div class="saerchDiv">
 4             <Search
 5             @result-click="resultClick"
 6             @on-change="changeResult"
 7             :results="results"
 8             v-model="searchVal"
 9             position="absolute"
10             auto-scroll-to-top
11             top="46px"
12             @on-focus="onFocus"
13             @on-cancel="onCancel"
14             @on-submit="onSubmit"
15              ref="search"></Search>
16         </div>
17
18     </div>
19 </template>
20 <script>
21 import {Search} from ‘vux‘;
22
23 export default {
24     name:"found",
25     data() {
26         return {
27             msg:"found page",
28             // searchVal:"寻找更多好文章",
29             searchVal:"",
30             results:[]
31         }
32     },
33     components:{
34         Search
35     },
36     methods:{
37         resultClick(item) { //选中搜索
38             console.log(item.title);
39         },
40         changeResult(val) { //获取搜索关键字
41             console.log(val);
42             /*this.$http.get(‘‘).then(res => {
43
44             }).catch(err => {
45
46             });*/
47
48             this.results = this.getResults(val);
49         },
50         onFocus(){
51             console.log("on focus");
52             // this.searchVal = ""
53         },
54         onCancel(){
55             console.log("点击取消按钮");
56         },
57         onSubmit(){
58             console.log("on submit");
59         },
60         getResults(keyword) { //暂时获取假数据
61             let rsArr = [];
62             for(let i = 0; i < 6; i++) {
63                 rsArr.push({
64                     title:keyword + (i+1),
65                     other:i //文章id
66                 });
67             }
68             return rsArr;
69         }
70
71     }
72 }
73 </script>
74 <style scoped>
75
76     .saerchDiv {
77         height: .75rem;
78         font-size: .27rem;
79     }
80
81 </style>

组件的通信

vue组件的通信是vue组件的核心,组件不仅仅是要把模板的内容进行复用;更主要的是组件间要进行通信;组件之间的通信数据传递是组件的生命力之一。

props单向数据流,父组件向子组件传递数据

props可以是一个数据类型也可以是一个数组,也可以是对象,对象下的数据有3个属性type,default,require。其中default,require值都是布尔类型值。type有Number,String,Boolean,Array,Object,Function,Symbol。如果props数据是对象或数组时默认值default必须是一个函数来返回初始化数据。而且因为对象或数据是引用类型,指向的是同一个内存空间所以当props数据是这两个类型时,数据改变时子组件内改变是会影响父组件的。

props数据类型及相关样例

 1 // props: [‘propsDataA‘],
 2         props: {
 3             propA: {
 4                 type: String,
 5                 default: "",
 6                 require: true
 7             },
 8             propB: {
 9                 type: Number,
10                 default: 1,
11                 require: false
12             },
13             propC: {
14                 type: Array,
15                 default: function() {
16                     return [];
17                 },
18                 require: true
19             },
20             propD: {
21                 type: Object,
22                 default: function() {
23                     return {};
24                 },
25                 require: true
26             },
27             propE: {
28                 type: Function,
29                 fn: function(val) { //一个时间未满两位数前面补零验证
30                     return val > 9 ? val : ‘0‘ + val;
31                 },
32                 require: true
33             },
34             propF: {
35                 type: Boolean,
36                 default: false,
37                 require: true
38             },
39             propG: [String, Number],
40             propH: Number
41         }

这里稍微改动一下局部组件的代码,父组件向子组件传递数据;

 1    <div id="app">
 2         {{msg}}
 3         <!-- <const-comp></const-comp> -->
 4         <local-comp :props-a="info"></local-comp>
 5     </div>
 6     <script>
 7
 8         /*Vue.component(‘constComp‘, {
 9             template: "<h3>我是全局组件</h3>"
10
11         });*/
12         let localComp = {
13             template: "<div>我是局部组件<p>父组件传过来的数据为-->{{propsA}}</p></div>",
14             props: {
15                 propsA: {
16                     type: String,
17                     default: "",
18                     require: true
19                 }
20             }
21         };
22         new Vue({
23             el: "#app",
24             data: {
25                 msg: "hello component",
26                 info: "hello props"
27             },
28             components: {
29                 localComp
30             }
31         });
32
33     </script>

自定义事件$emit,子组件向父组件通信

这里还是在原来的基础上改,子组件使用$emit自定义一个send事件向父组件发送数据

 1    <div id="app">
 2         {{msg}}
 3         <!-- <const-comp></const-comp> -->
 4         <div>子组件数据为---->{{fromChildData}}</div>
 5         <local-comp :props-a="info" @send="getChildData"></local-comp>
 6     </div>
 7     <script>
 8
 9         /*Vue.component(‘constComp‘, {
10             template: "<h3>我是全局组件</h3>"
11
12         });*/
13         let localComp = {
14             template: "<div>我是局部组件15                     <p>父组件传过来的数据为-->{{propsA}}</p>16                     <button @click=‘sendMsg‘>使用$emit子组件向父组件传递事件</button>17                 </div>",
18             props: {
19                 propsA: {
20                     type: String,
21                     default: "",
22                     require: true
23                 }
24             },
25             data() {
26                 return {
27                     msg: "子组件数据"
28                 }
29             },
30             methods: {
31                 sendMsg(evt) {
32                     this.$emit(‘send‘, this.msg);
33                 }
34             }
35         };
36         new Vue({
37             el: "#app",
38             data: {
39                 msg: "hello component",
40                 info: "hello props",
41                 fromChildData: ""
42             },
43             components: {
44                 localComp
45             },
46             methods: {
47                 getChildData(val) {
48                     this.fromChildData = val
49                 }
50             }
51         });
52
53     </script>

非子父组件通信,使用一个空的Vue实例作为一个事件总线监听数据变化

这种场景用于组件之间不为子父层级关系的时候相关通信,我们使用的那个空vue实例里也可以放vue的属性。用这个空的vue实例来$emit自定义一个事件然后再用这个实例来$on监听自定义事件,从而达到非子父组件之间的通信。(PS:这里暂时不讨论vuex),看demo代码。demo例子使用了ref组件索引。

    <div id="app">
        {{message}}
        <component-a ref="a"></component-a>
        <component-a ref="b"></component-a>
    </div>
    <script>
        const bus = new Vue({});

        Vue.component(‘component-a‘, {
            data () {
                return {
                    msg: 1
                }
            },
            template: ‘<button @click="handleEvent">传递事件</button>‘,
            methods: {
                handleEvent () {

                    this.$parent

                    bus.$emit(‘on-message‘, ‘来自组件 com-a 的内容‘);
                }
            }
        });

        const app = new Vue({
            el: ‘#app‘,
            data: {
                message: ‘‘
            },
            mounted () {
                bus.$on(‘on-message‘, (msg) => {
                    this.message = msg;
                });

                this.$children.msg = 2;

            }
        })
    </script>

slot组件内容分发

单个就默认slot,多个使用具名slot,$slots访问对应slot,vue2.0新增;因为vue2使用render函数来渲染,所以需要使用this.$slots来访问slot。this.$slots.xxx访问具体的slot,即slot中name指定的值 值类型{ [name: string]: ?Array<VNode> }

如果需要给slot添加默认内容的时候直接在slot上写就可以了,这个时候默认的slot内容所在的作用域就是其所在的组件实例,可以根据其所在的组件来控制slot默认的内容展示如:<slot>{{msg}}</slot>。如果没有指定默认数据的话slot内容根据其父组件所在的作用域。

当 vue 组件中当需要组件混合使用的时候需要用到内容分发,内容不确定的时候需要用到slot内容分发。

看demo代码;

 1        <div id="app">
 2         <com-out>
 3             <div slot="b">{{msgB}}</div>
 4             <div slot="a">{{msgA}}</div>
 5
 6         </com-out>
 7     </div>
 8     <template id="co">
 9         <div>
10             hello
11             <slot name="a"></slot>
12             <slot name="b"></slot>
13         </div>
14     </template>
15     <script>
16         Vue.component(‘com-out‘, {
17             template: "#co",
18             mounted() {
19                 console.log("com-out slot" + this.$slots.a[0]);
20             }
21         });
22         new Vue({
23             el: "#app",
24             data: {
25                 msgA: ‘父组件数据a‘,
26                 msgB: ‘父组件数据b‘
27             }
28         })
29     </script>    

递归组件

递归组件要记住两点:

1.递归组件必须要给组件设置name。

2.要在一个合适的时间(条件)跳出递归否则会报栈溢出异常。

 1 <div id="app">
 2         <com :count="1"></com>
 3     </div>
 4     <template id="cr">
 5         <div><com :count="count + 1" v-if="count < 3"></com>{{count}}</div>
 6     </template>
 7     <script>
 8         Vue.component(‘com‘, {
 9             name: ‘comr‘,
10             template: "#cr",
11             props: {
12                 count: {
13                     type: Number,
14                     default: 1
15                 }
16             }
17         })
18         new Vue({
19             el: ‘#app‘
20         })
21
22
23     </script>

动态组件

vue动态组件其实就是在组件中使用:is属性根据值来判断显示哪个组件。

 1 <div id="app">
 2         <button @click="changeCom">点击让子组件显示</button>
 3         <com v-bind:is="activeCom"></com>
 4     </div>
 5 <script>
 6     new Vue({
 7         el: ‘#app‘,
 8         data: {
 9             activeCom: "comA"
10         },
11         methods: {
12             changeCom: function () {
13                 let arr = ["comA", "comB", "comC"], index;
14                 index = Math.ceil(Math.random()*arr.length);
15                 this.activeCom = arr[index];
16             }
17         },
18         components: {
19             comA: {
20                 template: "<div>组件comA</div>"
21             },
22             comB: {
23                 template: "<div>组件comB</div>"
24             },
25             comC: {
26                 template: "<div>组件comC</div>"
27             },
28         }
29     });
30 </script>  

异步组件

异步组件在性能上有一定的优势,不仅加快了渲染时间也减少了不必要的加载;在路由中经常用到

看demo;

<div id="app">
        <child-component></child-component>

    </div>
    <script>
        Vue.component(‘child-component‘, function (resolve, reject) {
            window.setTimeout(function () {
                resolve({
                    template: ‘<div>异步组件的内容</div>‘
                })
            }, 2000)
        });
        new Vue({
            el: ‘#app‘
        })
    </script>

组件相关属性

$nextTick  虚拟dom完成后触发回调。进行dom操作。不过相关dom操作一般都建议放在指令中,或者自己自定义指令来进行操作,用合适的方式来做合适的事才能达到最优。

$ref当组件使用ref来作为索引时$ref获取当前组件

时间: 2024-10-25 13:48:12

关于vue组件的一个小结的相关文章

vue组件-另一个编写方式

1 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <script src="bower_components/vue/dist/vue.js"></script> <style> </style> &l

来吧!一文彻底搞定Vue组件!

作者 | Jeskson 来源 | 达达前端小酒馆 Vue组件的概述 组件是什么呢,了解组件对象的分析,Vue组件中的data属性,props传递数据的原理到底是什么. 事件通信的那些事 如何了解父子组件事件通信,和遇到非父子组件事件通信如何处理. 组件类型又是什么鬼 自定义组件双向绑定v-model,动态组件,又是如何称为动态的,为啥是动态呢,递归组件,如何理解递归. Vue组件的了解 Vue的理解,可以找我上一篇vue.js-详解三大流行框架VUE_快速进阶前端大咖-Vue基础,组件是什么,

webpack单独构建scss文件与.vue组件里构建scss的一个坑

在入口main.js里构建scss是通过引入模块的方式 import './assets/_reset.scss'; import './assets/_flex.scss'; import './assets/_functions.scss'; 在.vue组件里是单独构建的 <style lang="scss" scoped> img { width: rem(300px); } #product, .gallery, .detail { width: rem(750px

写一个vue组件

写一个vue组件 我下面写的是以.vue结尾的单文件组件的写法,是基于webpack构建的项目.如果还不知道怎么用webpack构建一个vue的工程的,可以移步到vue-cli. 一个完整的vue组件会包括一下三个部分: template:模板 js: 逻辑 css : 样式 每个组件都有属于自己的模板,js和样式.如果将一个页面比喻成一间房子的话,组件就是房子里的客厅.卧室.厨房.厕所.如果把厨房单独拿出来的话,组件又可以是刀.油烟机...等等.就是说页面是由组件构成的,而组件也可以是组件构成

vue学习——刚学Vue组件,吐槽一个东西

Vue组件的props是用来传值的 这里是官方链接 template:"<bbb @click='onClick()'>{{value}}</bbb>", //"<div>{{value}}</div>" 讨厌的东西就出在这行代码,一个组件的 template 调用同级别的组件 bbb 然后使用 props 传值,结果是行不通的,并且没有报错!虽然,明知道是什么问题,可是还是令我感到不舒服. 测试代码: <!DO

Vue父组件向子组件传递一个动态的值,子组件如何保持实时更新实时更新?

原文:https://blog.csdn.net/zhouweixue_vivi/article/details/78550738 2017年11月16日 14:22:50 zhouweixue_vivi 阅读数:29918 最近用vue做一个新项目,经历了各种折磨,每次遇到问题都想大喊,格劳资上JQuery,氮素肯定是不行的,今天遇到一个小问题,Vue父组件向子组件传递一个动态的值,子组件只能获取初始值,不能实时更新? 这就有点折磨人了,设想的是,父组件发生变化获取数据,动态传递给子组件,子组

【转】制作并发布第一个vue组件的npm包

最近在网上找到一个网页制作辅助工具-jQuery标尺参考线插件,觉得在现在的一个项目中能用的上,插件是基于JQuery的,但是现在的项目是用vue写的.So...,就照葫芦画瓢改装成了Vue组件,总的来说算是一个用处较多的组件,于是乎,就想着把它上传到Npm上分享出来.以前只用过别人的包,这一次自己上传一个乐呵乐呵...顺便记录发布一下过程. 项目地址 https://github.com/gorkys/vue... 初始化项目 这里用的是webpack-simple,可以理解为精简版的vue-

封装Vue组件的一些技巧

封装Vue组件的一些技巧 本文同步在个人博客shymean.com上,欢迎关注 写Vue有很长一段时间了,除了常规的业务开发之外,也应该思考和反思一下封装组件的正确方式.以弹窗组件为例,一种实现是在需要模板中引入需要弹窗展示的组件,然后通过一个flag变量来控制弹窗的组件,在业务代码里面会充斥着冗余的弹窗组件逻辑,十分不优雅. 本文整理了开发Vue组件的一些技巧,包含大量代码示例. 开发环境 vue-cli3提供了非常方便的功能,可以快速编写一些测试demo,是开发组件必备的环境.下面是安装使用

vue组件中的通信

一.组件间的关系 1.父子关系 2.兄弟关系 3.隔代关系 二.组件间的通信方式 1.props 2.$emit/$on 3.VUEX 4.$parent/$children 5.$attrs/$listeners 6.provide/inject 三.通信方式举例 新建了一个过程,采用webpack来管理项目.  方法一:props / $emit 1.props---父组件向子组件传值 子组件:sub1.vue 父组件:app.vue 父组件通过props向下传递给子组件.注:组件中的数据共