Vue.js组件化开发简述

一、组件的分类

一般来说,Vue.js 组件主要分成三类:

  1. vue-router 产生的每个页面,它本质上也是一个组件(.vue),主要承载当前页面的 HTML 结构,会包含数据获取、数据整理、数据可视化等常规业务。整个文件相对较大,但一般不会有 props 选项和 自定义事件,因为它作为路由的渲染,不会被复用,因此也不会对外提供接口。

    在项目开发中,我们写的大部分代码都是这类的组件(页面),协同开发时,每人维护自己的页面,很少有交集。这类组件相对是最好写的,因为主要是还原设计稿,完成需求,不需要太多模块和架构设计上的考虑。

  2. 不包含业务,独立、具体功能的基础组件,比如日期选择器模态框等。这类组件作为项目的基础控件,会被大量使用,因此组件的 API 进行过高强度的抽象,可以通过不同配置实现不同的功能。每个公司都有自己的组件使用规范或组件库,但要开发和维护一套这样的组件库,投入的人力和精力还是很重的,所以出于成本考虑,很多项目都会使用已有的开源组件库。

    独立组件的开发难度要高于第一类组件,因为它的侧重点是 API 的设计、兼容性、性能、以及复杂的功能。这类组件对 JavaScript 的编程能力有一定要求,也会包含非常多的技巧,比如在不依赖 Vuex 和 Bus(因为独立组件,无法依赖其它库)的情况下,各组件间的通信,还会涉及很多脑壳疼的逻辑,比如日期选择器要考虑不同时区、国家的日历习惯,支持多种日期格式。

  3. 业务组件。它不像第二类独立组件只包含某个功能,而是在业务中被多个页面复用的,它与独立组件的区别是,业务组件只在当前项目中会用到,不具有通用性,而且会包含一些业务,比如数据请求;而独立组件不含业务,在任何项目中都可以使用,功能单一,比如一个具有数据校验功能的输入框。

    业务组件更像是介于第一类和第二类之间,在开发上也与独立组件类似,但寄托于项目,你可以使用项目中的技术栈,比如 Vuex、axios、echarts 等,所以它的开发难度相对独立组件要容易点,但也有必要考虑组件的可维护性和复用性。

二、组件的构成

一个再复杂的组件,都是由三部分组成的:prop、event、slot,它们构成了 Vue.js 组件的 API。如果你开发的是一个通用组件,那一定要事先设计好这三部分,因为组件一旦发布,后面再修改 API 就很困难了,使用者都是希望不断新增功能,修复 bug,而不是经常变更接口。如果你阅读别人写的组件,也可以从这三个部分展开,它们可以帮助你快速了解一个组件的所有功能。

2.1 属性 prop

prop定义了这个组件有哪些可配置的属性,组件的核心功能也都是它来确定的。写通用组件时,props 最好用对象的写法,这样可以针对每个属性设置类型、默认值或自定义校验属性的值,这点在组件开发中很重要,然而很多人却忽视,直接使用 props 的数组用法,这样的组件往往是不严谨的。下面是我在商城首页引入商品列表的例子。以下代码是商品列表GoodList.vue的部分代码:

<template>
  <div class="goods">
    <goods-list-item v-for="(item,index) in goods" :goods-item="item" :key="index"/>
  </div>
</template>

<script>
  import GoodsListItem from './GoodsListItem';

  export default {
    name: 'GoodsList',
    components:{
      GoodsListItem
    },
    //在商品列表组件中定义商品变量,并设置初始类型为数组
    props:{
      goods:{
        type:Array,
        default(){
          return []
        }
      }
    }
  };
</script>

接着在Home.vue组件中引入商品列表组件并且通过:goods(与子组件的props中定义的变量名保持一致)传值给子组件的props,以下代码是Home.vue的部分代码:

<template>
  <div id="home" class="wrapper">
     <goods-list :goods="showGoods"/>
  </div>
</template>

<script>

  //导入商品列表组件
  import GoodsList from '../../components/content/goods/GoodsList';


  export default {
    name: 'Home',
    components: {
      GoodsList,
    },

    computed: {
      showGoods() {
        return this.goods[this.currentType].list;
      }
    },

  };
</script>

要注意的是,组件里定义的 props,都是单向数据流,也就是只能通过父级修改,组件自己不能修改 props 的值,只能修改定义在 data 里的数据,非要修改,也是通过后面介绍的自定义事件(event)通知父级,由父级来修改。

2.2 插槽 slot

vue的插槽在我看来类似于给页面定义一个模板,再使用插槽时可以自定义插槽的内容,但是插槽中的模板例如样式,布局可以复用。比如我定义一个导航插槽位置分别为,left、center和right,后续再使用导航时,可以自己选择一个插槽来定义样式。下面是导航栏插槽组件NavBar.vue的部分代码:

<template>
  <div class="nav-bar">
    <div class="left">
      <slot name="left"></slot>
    </div>
    
    <div class="center">
      <slot name="center"></slot>
    </div>
    
    <div class="right">
      <slot name="right"></slot>
    </div>
    
  </div>
</template>

<script>
  export default {
    name: 'NavBar',
    components:{

    }
  };
</script>

下面是首页Home.vue中使用导航栏插槽组件的部分代码:

<template>
  <div id="home" class="wrapper">

    <nav-bar class="home-nav">
      <div slot="center">购物街</div>
    </nav-bar>
    
  </div>
</template>

<script>

	//导入导航栏组件
  	import NavBar from '../../components/common/navbar/NavBar';
	
</script>

2.3 自定义事件 event

用上面的首页引入商品子组件代码为例,在点击子组件的时候,通过定义一个事件,来传递信息给父组件,部分代码如下:

<template>
  <button @click="handleClick"/>
</template>
<script>
  export default {
    methods: {
      handleClick (event) {
        this.$emit('on-click', event);
      }
    }
  }
</script>

通过 $emit,就可以触发自定义的事件 on-click传递的参数是后面的event点击事件 ,在父组件中通过 @on-click 来监听(注意名字要与$emit的第一个参数保持一致,否则监听不到):

<i-button @on-click="handleClick"></i-button>

上面的 click 事件,是在组件内部的 <button> 元素上声明的,这里还有另一种方法,直接在父级声明,但为了区分原生事件和自定义事件,要用到事件修饰符 .native,所以上面的示例也可以这样写:

<i-button @click.native="handleClick"></i-button>

如果不写 .native 修饰符,那上面的 @click 就是自定义事件 click,而非原生事件 click,但我们在组件内只触发了 on-click 事件,而不是 click,所以直接写 @click 原生点击是不会监听到点击事件的。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值