Vue单文件组件实践

小明是个前端新人,他在开发过程中,拿到一个替换模块的需求,面对茫茫然一堆文件文件,一脸懵逼,于是他开始了以下步骤:

  1. 回想了一下到底html/template模板部分在哪里,找到了,替换;
  2. 又回想了一下css/sass样式部分写在哪,重复上一步。
  3. 找了半天到底逻辑部分写在哪个文件,打开,替换。
  4. 也许小明学了一些模块化开发的步骤,稍微轻松了一些。

但是还是很麻烦,很痛苦不是吗?
没关系,现在我们可以使用Vue的单文件组件构建项目来告别这类问题!

单文件组件介绍

先来看一段官方指南对于单文件组件的描述:

在中大型项目开发过程中,使用模块构建系统非常重要。使用Vue.js中提供的单文件组件的思路,我们可以将界面拆分为多个小组件,每个组件在同一地方封装它的 CSS 样式,模板和 JavaScript 定义。
Alt text

采用单文件组件构建项目:

  1. 利于代码复用,我们可能在同一个项目中多处用到同一个类型的模块,而我们需要做的仅仅只是将这个组件放入它应该在的位置,借助MVVM框架的各种渲染控制,各个模块随意组合,随心所欲。
  2. 替换或者增减相应的模块非常方便。在实际开发过程中,增减功能或者模块十分频繁,在这类情况下,我们只需要改变对应的组件即可。

案例

本文仅描述采用单文件组件构建项目的思路,webpackVue.js等相关基础知识请查阅官方文档。

组件分析

在使用一种基于组件开发的模式时,最为重要的一件事就是组件分解了。先来看一个页面:
Alt text

图中页面大致可分解为:

  • 主体,带头部导航,左右滑动切换栏目
  • 每个栏目为单独一个模块。
  • 在一个栏目内,最上面有一个轮播图组件,下面为列表页。
  • 但是列表页是有两种不同的类型,因此我们将其分为两个组件。

所以完成整体架构所需模块如下:

components
├──comunity.vue    //主模块
├──hot.vue         //热门模块
├──banner.vue      //轮播
├──block.vue       //列表中的大图展示
├──list.vue        //正常的list项

主模块

首先针对主模块,部分代码如下:

---
comunity.vue
---
<template>
    <nav class="nav">
        <ul id="swiper-nav">
            <template v-for="nav in navList">
              <li  v-on:click="switchSwiper($index)"  v-bind:class="curIndex == $index ? 'active': ''">
                  <span>{{nav}}</span>
              </li>
            </template>
        </ul>
    </nav>
    <section>
        <div class="swiper-container" id="index-swiper">
            <div class="swiper-wrapper">
                <div class="swiper-slide">
                    <section id="index-scroll">
                        <Hot></Hot>
                    </section>
                </div>
                <div class="swiper-slide">second slider</div>
                <div class="swiper-slide">third slider</div>
            </div>
        </div>
    </section>
</template>
<script>
    var mySwiper=null;
    import Hot from './hot.vue';
    module.exports = ({
        data: function() {
            return {
                curIndex: 0,
                navList: ['热门', '搭配师', '穿衣茶话会', '潮流穿搭志']
            }
        },
        ready: function() {
            var that = this;
            mySwiper = new Swiper("#index-swiper", {
                onSlideChangeStart: function() {
                    that.curIndex = mySwiper.activeIndex;
                }
            });
        },
        components: {
            Hot
        },
        methods: {
            switchSwiper(index) {
                this.curIndex = index;
                mySwiper.slideTo(index);
            }
        }
    })
</script>
<style lang="scss">
</style>

我们在其中加入了我们的第一个栏目,热门:

  1. 首先,在script部分把模块引入:
    import Hot from './hot.vue';
    
  2. 设置页面内需要的组件:
    components: {
     Hot
    },
    
  3. 将该模块加入模板文件合适的位置:
    <section id="index-scroll">
     <Hot></Hot>
    </section>
    

栏目模块

在引入了hot.vue模块之后,我们来设计和编写具体内容。
根据组件分解,在该页面有三个模块:轮播、大图列表项和小图列表项。我们将三个模块分别为命名为swiperblocklist
因为大图列表和小图列表是混杂在一起排列的,顺序不定,所以在我们需要后台返回的数据中,包含对于列表项类型的参数。
假设后台返回的数据中对于类型的描述为{...,type:"block"}{...,type:"list"}
此时,根据返回数据lists我们可以通过v-if来控制此处需要选择的类型。

<template v-for="content in lists">
    <block v-if="content.type=='block'"></block>
    <list v-if="content.type=='list'"></list>
</template>

因此模板可以写成:

<template>
    <swiper></swiper>
    <template v-for="content in lists">
        <block v-if="content.type=='block'"></block>
        <list v-if="content.type=='list'"></list>
    </template>
</template>

同样地,我们任然需要导入组件和设置页面包含组件,设置与上一步类似。

具体内容模块

经过上述步骤,我们现在需要编写最内层的三个模块,相信大家可以很轻松完成。

总结

在完成了上述工作之后,当项目内的其他页面需要用到相同模块时,我们可以直接重用相关组件。在需求变动时,也可以很轻松的替换对应组件,大大的提高了开发效率。

我是王浩然,15年毕业于合肥工业大学,现就职于趣分期。</br>乐于分享,喜欢折腾。