用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属性加上引入进来的组件实例即可

  1. <div id="app">
  2. {{msg}}
  3. <!-- <const-comp></const-comp> -->
  4. <local-comp></local-comp>
  5. </div>
  6. <script>
  7.  
  8. /*Vue.component('constComp', {
  9. template: "<h3>我是全局组件</h3>"
  10.  
  11. });*/
  12. let localComp = {
  13. template: "<div>我是局部组件</div>"
  14. };
  15. new Vue({
  16. el: "#app",
  17. data: {
  18. msg: "hello component"
  19. },
  20. components: {
  21. localComp
  22. }
  23. });
  24.  
  25. </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组件索引。

  1. <div id="app">
  2. {{message}}
  3. <component-a ref="a"></component-a>
  4. <component-a ref="b"></component-a>
  5. </div>
  6. <script>
  7. const bus = new Vue({});
  8.  
  9. Vue.component('component-a', {
  10. data () {
  11. return {
  12. msg: 1
  13. }
  14. },
  15. template: '<button @click="handleEvent">传递事件</button>',
  16. methods: {
  17. handleEvent () {
  18. bus.$emit('on-message', '来自组件 com-a 的内容');
  19. }
  20. }
  21. });
  22.  
  23. const app = new Vue({
  24. el: '#app',
  25. data: {
  26. message: ''
  27. },
  28. mounted () {
  29. bus.$on('on-message', (msg) => {
  30. this.message = msg;
  31. });
  32.  
  33. this.$children.msg = 2;
  34.  
  35. }
  36. })
  37. </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. </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;

  1. <div id="app">
  2. <child-component></child-component>
  3.  
  4. </div>
  5. <script>
  6. Vue.component('child-component', function (resolve, reject) {
  7. window.setTimeout(function () {
  8. resolve({
  9. template: '<div>异步组件的内容</div>'
  10. })
  11. }, 2000)
  12. });
  13. new Vue({
  14. el: '#app'
  15. })
  16. </script>

在路由中异步组件可以这样用:

  1. {
  2. path:"/路由地址",
  3. name:"routeName",
  4. component: resolve => require(["../components/xxx.vue"], resolve)
  5. 5 }

组件相关属性

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

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

vue组件的一个总结的更多相关文章

  1. 关于vue组件的一个小结

    用vue进行开发到目前为止也有将近一年的时间了,在项目技术选型的时候隔壁组选 react的时候我们坚持使用vue作为前端的开发框架.虽然两者思想上的差异不大,但是vue的语法在代码的可读性以及后期的维 ...

  2. vue 组件发布记录

    好久没做独立的 vue 组件了,最近突然想把一个常用的 vue 组件打成一个 npm 包,方便使用.好久不用,发现已经忘记环境怎么搭建.翻看以前的组件,才慢慢回想起来,中间还出现些错误.在这记录下开发 ...

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

    作者 | Jeskson 来源 | 达达前端小酒馆 Vue组件的概述 组件是什么呢,了解组件对象的分析,Vue组件中的data属性,props传递数据的原理到底是什么. 事件通信的那些事 如何了解父子 ...

  4. vue组件,撸第一个

    实现此例您可以学到: vue-cli的基本应用 父组件如何向子组件传递值 单文件组件如何引入scss v-on和v-for的基础应用 源码下载 一.搭建vue开发环境 更换镜像到cnpmnpm ins ...

  5. 【vue系列之三】从一个vue-pdf-shower,说说vue组件和npm包

    前言 从去年年初开始,自己便下决心要写一个vue系列的博客,但时至今日,才写系列的第三篇博客,想来甚是惭愧. 但是慢归慢,每一篇都要保证质量,以及要写出自己的心路历程,防止自己工作中填的坑再让读者走一 ...

  6. 写一个vue组件

    写一个vue组件 我下面写的是以.vue结尾的单文件组件的写法,是基于webpack构建的项目.如果还不知道怎么用webpack构建一个vue的工程的,可以移步到vue-cli. 一个完整的vue组件 ...

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

    原文:https://blog.csdn.net/zhouweixue_vivi/article/details/78550738 2017年11月16日 14:22:50 zhouweixue_vi ...

  8. Laravel 项目中编写第一个 Vue 组件

    和 CSS 框架一样,Laravel 不强制你使用什么 JavaScript 客户端框架,但是开箱对 Vue.js 提供了良好的支持,如果你更熟悉 React 的话,也可以将默认的脚手架代码替换成 R ...

  9. 使用Vue cli3搭建一个用Fetch Api的组件

    系列参考 ,英文原文参考 我的git代码: https://github.com/chentianwei411/Typeahead 目标: 建立一个输入关键字得到相关列表的组件,用Vuejs2和Fet ...

随机推荐

  1. 【USACO2006 Mar】滑雪缆车 skilift

    [USACO2006 Mar] 滑雪缆车 skilift Time Limit 1000 msMemory Limit 131072 KBytes Description 科罗拉多州的罗恩打算为奶牛建 ...

  2. Lua相关回调总结【转】

    原文 http://www.zaojiahua.com/lua-callback-functions.html 最近做一个小项目,是用Lua写的,中间用到了很多的回调,基本Cocos中的那几种常用回调 ...

  3. 查询分析器执行SQL很快但是ado.net很慢:请为你的SQLparameter设置DbType

    我们都知道,参数化查询可以处理SQL注入,以及提高查询的效率,因为参数化查询会使MSSQL缓存查询的计划. 但是会出现一个问题:有的时候参数化查询比直接拼接sql字符串效率低好多,甚至是查询超时. 原 ...

  4. JQuery 记第N次被坑 - ajax请求字符集问题

    前言:两个功能差不多的页面,都是使用$.post()请求后台,页面A传递到后台的中文参数正常,页面B传递到后台的中文参数则为乱码 分析过程: ①使用chrome的开发者工具,分析两个页面的ajax请求 ...

  5. SPA设计架构

    1.SPA是采用单页应用(Single Page Application)的方式来开发 2.SPA的框架有如Augular.js.Vue.js等.

  6. 网络中 ping 不通 路由表

    不管是在window还是在linux中,我们经常会遇到ping不通的问题. 这里的原因很多,比如不同的网段交换机做了一些限制等,这些问题是我们人工不能解决的. 但是,当你发现各自的网关是可以ping的 ...

  7. eclipse安装python开发pydev插件

    eclipse安装python开发pydev插件 下载eclipse的python开发插件pydev http://pan.baidu.com/s/1qXHt8pI 下载python.exe,并安装. ...

  8. .net 内嵌 GeckoWebBrowser (firefox) 核心浏览器

    引用nuget包: 注意:Geckofx45 nuget包必须是最后引用,否则初始化会出错 简单示例: using Gecko; using System; using System.Collecti ...

  9. codevs 3385 拯救Oier(一) Save Oier—first

    3385 拯救Oier(一) Save Oier—first 传送门  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 青铜 Bronze 题解       题目描述 Descr ...

  10. 7-13 航空公司VIP客户查询 (25 分)

    题意: 思路: 读完题目之后的第一思路就是用map将客户的id(string类型)与里程road(int类型)形成映射,然后直接用id查找添加里程或输出里程.但是400ms的限制妥妥的超时了.然后意识 ...