组件化开发代码案例分析

发布者: xiaozhimn

今天做了一个移动端的页面,拿出来根大家分享下组件化开发的设计思路,希望可以帮助大家在做业务开发的时候让自己的代码写的更好,开始分享,先上案例!
moble1

moble2
1. 使用rem布局,在不同分辨率下进行等比例缩放

(function (doc, win, undefined) {
    var docEl = doc.documentElement,
        resizeEvt = 'orientationchange' in win? 'orientationchange' : 'resize',
        recalc = function () {
            var clientWidth = docEl.clientWidth;
            if (clientWidth === undefined) return;
            docEl.style.fontSize = 20 * (clientWidth / 320) + 'px';

        };
    if (doc.addEventListener === undefined) return;
    win.addEventListener(resizeEvt, recalc, false);
    doc.addEventListener('DOMContentLoaded', recalc, false)
})(document, window);
解释:按照手机最小尺寸320为基值,将 html的font-size设置为大小 20 * (clientWidth / 320) + 'px'像素
在页面中为节点设置样式的时候使用rem单位便可以进行屏幕适配。
例如你想为一个div设置宽度为50px按照上面的公式转换为rem  (50 / 20)rem = 2.5rem 其中clientWidth / 320为屏幕缩放比例。

2. 页面组件抽取

经过对以上页面的分析,我们发现,
a: 复选功能可以抽离出一个radio组件并且在以后的页面中可能被重复使用,因此我们把它纳入通用组件中。
b: 输入框和选择框布局一样,只是一个可以输入,一个可以选择,我们也可以将其抽离出一个myInput组件只要通过type属性区分即可,后续可以通过type进行功能扩展,并且这个组件也很有可能在以后被重复使用因此我们把它上升为通用业务组件。
c: 提示功能,可以分为警告,成功,失败等在全网的通用性极强,因此我们毫不犹豫的将其抽离成一个通用性组件。
d: 滑动选择对话框,我们将其抽离为通用性功能组件,方便后续复用。
e: 位置定位,我们也将其抽离为通用性功能组件,方便后续复用。

经过以上分析我们产生了5个组件,接下来我们编写各个组件的代码,以及将其拼装成一个完整的页面。先展示下目录结构
moble3
index.html

<div style="padding-top:20px">
    <myInputComponent label="学校名称" type="input" placeholder="请输入" name="schoolName"></myInputComponent>
    <div class="row-title">
        学校类型
    </div>
    <radioComponent label="托" name="base"></radioComponent>
    <radioComponent label="幼" name="child"></radioComponent>
    <radioComponent label="小" name="primary"></radioComponent>
    <radioComponent label="初" name="middle"></radioComponent>
    <radioComponent label="高" name="high"></radioComponent>

    <div class="main-box">
        <myInputComponent label="学校性质" type="select" placeholder="请选择" name="schoolProperty1" :event="showschoolProperty" id="schoolProperty1"></myInputComponent>
        <myInputComponent label="省份" type="select" placeholder="请选择" name="province" :event="showProvince"></myInputComponent>
        <myInputComponent label="市" type="select" placeholder="请选择" name="city" :event="showCity"></myInputComponent>
        <myInputComponent label="区/县" type="select" placeholder="请选择" name="area" :event="showArea"></myInputComponent>
        <myInputComponent label="学校学生数" type="input" placeholder="请输入" name="studentCount"></myInputComponent>
        <myInputComponent label="收费周期" type="select" placeholder="请选择" name="chargeCycle" :event="showChargeCycle"></myInputComponent>
        <myInputComponent label="联系人" type="input" placeholder="请输入" name="contactor"></myInputComponent>
        <myInputComponent label="手机号码" type="input" placeholder="请输入" name="tel"></myInputComponent>
        <myInputComponent label="联系邮箱" type="input" placeholder="请输入" name="email"></myInputComponent>
        <myInputComponent label="教师姓名" type="input" placeholder="请输入" name="teacherName"></myInputComponent>
    </div>
    <div class="row-title">
        学校资质
    </div>
    <myInputComponent label="请先选择学校性质" type="select" placeholder="请选择" name="schoolProperty2" :event="showschoolProperty"></myInputComponent>
    <myInputComponent label="服务商名称" type="input" placeholder="" name="servicerName"></myInputComponent>
    <a href="javascript:void(0)" class="confirm-submit" @click="submit">确认提交</a>
</div>

解释: 从以上页面我们可以看到主页面全部由组件拼装而成,代码结构很清晰,位置可以任意调整。

index.js

use([
    "public/pages/index/indexService.js",
    "public/pages/components/common/myInput/myInput.js",
    "public/pages/components/common/radio/radio.js",
    "public/common/mobiscroll.css",
    "public/common/mobiscroll.js",
    "public/pages/components/common/slideDialog/slideDialog.js"
], function() {
    function init(storage) {
        var app = new VueRoot({
            template: 'public/pages/index/index.html',
            data: {
                    formData: {},
                    showschoolProperty: function (callback) {//显示用户资质对话框
                        slideDialog.init().show(function(val) {
                            callback(val);
                        });
                    },
                    showProvince: function(callback) {//显示省对话框

                    },
                    showCity: function(callback) {//显示市对话框

                    },
                    showArea: function(callback) {//显示区对话框

                    },
                    studentCount: function(callback) {//显示学生数对话框

                    },
                    showChargeCycle: function(callback) {//显示缴费周期对话框

                    }
            },
            created: function() {},
            mounted: function() {},
            destroyed: function() {},
            methods: {
                submit: function() {
                    var self = this;
                    flux.call("myInput", "getVal", function(result) {
                        self.formData[result.name] = result.val;
                    });
                    flux.call("radio", "getSelectState", function(result) {
                        self.formData[result.name] = result.val;
                    });
                }
            }
        });
        return app;
    }
    module.exports = init;
    if(typeof window != "undefined") {
        var mainComponent = init(storage);
        mainComponent.$mount("#app");
    }
});

解释: 首先我们通过use的方式将组件和需要的样式以模块加载的机制进行载入,因为这里是并行加载所以基本不存在性能问题。
其次我们在 myImputComponent组件上定义prop属性:label:左部显示的标题,type: 组件类型(输入,下拉)placeholder:
提示内容,name:表单的输入框名称,event:下拉类型组件的点击事件.
最后我们在主组件index.js的data属性中为各个下拉组件定义点击响应的事件,callback为在外部弹框选择后调用并写入选择的值例如:callback("hello 我选择了女"),让其在myImputComponent组件内显示。 submit为表单提交的方法,我们通过框架提供的flux.call方法来调用myInput实例中定义的getVal方法来获取用户输入或选择的内容,最后将结果写入到formData中用于最后ajax请求的提交。

myInput.html

<div @click="execClick">
    <div class="myInput-box">
        <span class="label">{{label}}</span>
        <input type="text" class="myInput input" :placeholder="placeholder" v-model.lazy="defaultVal" v-if="type=='input'">
        <input type="text" :id="id" class="myInput arrow" readonly :placeholder="placeholder" v-model.lazy="defaultVal" v-else-if="type=='select'">
    </div>
</div>

myInput.js

use([], function() {
    Vue.component('myInputComponent', {
        pageName: "common",
        props:["label", "type", "placeholder","event", "name", "id"],
        template: "public/pages/components/common/myInput/myInput.html",
        data:function() {
            return {
                defaultVal: ""
            }
        },
        created: function() {},
        mounted: function() {},
        destroyed: function() {},
        methods: {
            execClick: function() {
               if(this.event) {
                   var ev = this.event;
                   ev(this.setVal);
               }
            },
            setVal: function(val) {
                this.defaultVal = val;
            },
            getVal: function(callback) {
                var result = {
                    name: this.name,
                    val: this.defaultVal
                };
                callback(result);
            }
        }
    });
});

其他的组件就不再做过多的展示了,这里只是介绍一种设计思路,方便你代码的复用和后期的维护,感兴趣的同学请多关注我的视频课程,后续进行更多项目实战的讲解。

10赞