网站首页  汉语字词  英语词汇  考试资料  写作素材  旧版资料

请输入您要查询的考试资料:

 

标题 html5+css3之制作header实例与更新
内容
    上次,我们形成了两种header的布局,一种flexbox,一种float,最后与身边做重构的同事交流下来,选择了float的布局。
    事实上布局的选型不需要我关注,我的参与或者一些意见多数是自我提升,但要说html结构完全控制于csser的话就不一定了
    在整个header组件的代码过程中,我与重构同事就一些地方发生了重复的交流,争论,今天就header组件的布局以及功能实现,聊一聊js与css的配合
    然后header组件本身是一个老组件,我们顺便探讨下,这类老组件应该如何翻新比较合适。
    最初的结构
    最开始重构的同事给了我一个已经做好了的页面:
    名单
    我们针对其中一些小的体验上做了讨论,并且知会到设计组,便改了,很顺畅,然后我开始了愉快的代码,这是其中一块HTML的结构:
    代码如下:
    <header>
    <span></span>
    <span>确认</span>
    <span><i></i></span>
    <span><i></i></span>
    <h1>
    页面标题</h1>
    </header>
    这里除去h1标签中的文字不说,因为其中可能表现的非常复杂,我们后面再说,其中的按钮有以下功能:
    ① 第二行:回退按钮
    ② 第三行:确认
    PS:左边采用float布局所以第一个元素在最右边
    ③ 第四行:home标签
    ④ 第五行:三个点,点击会出一个侧边栏
    以上便是HTML的实现,但是对与程序员来说,头部除了按钮(btn)以外就只有图标(icon),所以以上的结构事实上js一般是不买账的
    Jser需要的结构
    与重构同事交流下来,原因是这样的:
    ① 因为回退比较特殊,所以多了一个样式,具体什么我没记住了
    ② icon代表背景图,icond代表CSS3画的,CSS3画的可扩展性高,比如换颜色什么的
    ③ ......
    当时双方的讨论还是比较激烈的,但是对icond全部变成icon,重构同事不同意,于是也就作罢,经过一轮讨论,结构变成了这样:
    代码如下:
    <header>
    <span><i></i></span>
    <span>确认</span>
    <span><i></i></span>
    <span><i></i></span>
    <h1>
    页面标题</h1>
    </header>
    做了很小的变化,将back的结构与其它icon类型按钮做了统一,于是我开始了愉快的代码
    PS:注意,icond与icon类型的标签会不同程度的在header处出现,无法控制
    结构的问题
    因为公司的header一直便存在,我做的过程中必须考虑到两个方面的问题:
    ① 方便扩展但是要做到接口兼容
    ② 需要通过各个标签的tagname与Hybrid进行联调
    也就是说,每个标签叫什么名字,是已经定死了的,甚至一些标签的回调也被限制了,我这里的数据结构大概如下:
    代码如下:
    {
    left: [],
    center: [],
    right: [
    {
    'tagname': 'home', callback: function () {
    console.log('返回');
    }
    },
    { 'tagname': 'search' },
    {
    'tagname': 'list', callback: function (e) {
    //......
    }
    },
    { 'tagname': 'tel', 'number': '56973144' },
    {
    'tagname': 'commit', 'value': '登录', callback: function () {
    console.log('登录');
    }
    },
    {
    'tagname': 'custom', 'value': '定制化',
    itemFn: function () {
    return '<span>定制化</span>';
    },
    callback: function () {
    console.log('定制化');
    }
    }
    ]
    可以看到,一个tagname一个按钮,而现在问题来了:我们并不知道某个tagname应该是icon或者是icond
    但是根据是否存在value字段,我们是可以判断其是否应该具有i子标签,这个时候我们是怎么解决的呢?
    建立tagname与classname的映射关系,比如:
    代码如下:
    var map = {
    'home': 'icon',
    'list': 'icond'
    }
    当然,这种做法,自然十分让人感到难受,如果小图标统一为icon,我在模板中可以统一如此代码:
    代码如下:
    <span >
    <% if(item.value) { %>
    <%=item.value %>
    <% } else { %>
    <i></i>
    <% } %>
    </span>
    但是由于多了一个映射关系,我的代码便不好看了,并且业务逻辑还变得复杂了起来,于是带着这些考量再次找到了重构同事,重构同事也很明事理,马上答应改了:
    代码如下:
    <header>
    <span><i></i></span>
    <span>确认</span>
    <span><i></i></span>
    <span><i></i></span>
    <h1>
    页面标题</h1>
    </header>
    不考虑h1中的样式的话,搞定上面的代码,对我们来说,真的是太简单了啊!!!
    代码如下:
    <header>
    <%
    var i = 0, len = 0, j = 0, keyagain = 0;
    var left = left;
    var right = right.reverse();
    var item = null;
    var dir;
    var btnObj = null;
    %>
    <%for(keyagain=0; keyagain < 2; keyagain++) { %>
    <%
    if(keyagain == 0) { dir = 'fl'; btnObj = left; } else { dir = 'fr'; btnObj = right; }
    %>
    <% for(i = 0, len = btnObj.length; i < len; i++) { %>
    <% item = btnObj[i]; %>
    <%if(typeof item.itemFn == 'function') { %>
    <%=item.itemFn() %>
    <%} else { %>
    <span >
    <% if(item.value) { %>
    <%=item.value %>
    <% } else { %>
    <i></i>
    <% } %>
    </span>
    <%} %>
    <%} %>
    <%} %>
    </header>
    PS:从代码着色来看,js中用到的left与Right是关键字,这个得处理...
    定制化需求
    可以看到,一个循环,我们便可以轻易的生成左边和右边的按钮,但是马上问题来了,我们需要扩展怎么办,上面就会有以下问题:
    ① tel标签默认是a标签,我们这里却是span标签
    代码如下:
    <a href="tel:56973144"><i></i></a>
    ② back按钮我们一般会做成a标签,用以解决javascript出错在Hybrid的假死问题
    说白了,就是虽然标签按钮应该有统一的结构,但是需要保留定制化的能力
    这里定制化的工作交给了各个标签的itemFn这个函数,他返回一个字符串,并且具有一定规则,这里取一个代码片段:
    代码如下:
    handleSpecialParam: function (data) {
    var k, i, len, item;
    for (k in data) {
    if (_.isArray(data[k])) {
    for (i = 0, len = data[k].length; i < len; i++) {
    item = data[k][i];
    if (this['customtHandle_' + item.tagname]) {
    this['customtHandle_' + item.tagname](data[k][i], k);
    } //if
    } //for
    } //if
    } //for
    },
    _getDir: function (dir) {
    var kv = { left: 'fl', right: 'fr' };
    return kv[dir];
    },
    //处理back的按钮逻辑
    customtHandle_back: function (item, dir) {
    dir = this._getDir(dir);
    item.itemFn = function () {
    var str = '<a href="<a href=">" >';
    if (item.value) {
    str += item.value + '</a>';
    } else {
    str += '<i></i></a>';
    }
    return str;
    };
    },
    当发现某个按钮不满足需求或者有定制化需求时,便想办法设置其itemFn即可,时候上这个代码可以直接写到初始化的json串去
    花样百出的title
    到title时,发现其表现便五花八门了,这个时候一般是根据不同的类型生成不同的HTML结构,框架给默认的几个选项,不支持便自己定制itemFn
    代码如下:
    <% item = center; %>
    <%if(typeof item.itemFn == 'function') { %>
    <%=item.itemFn() %>
    <%} else if(item.tagname=='title' || item.tagname=='subtitle') { %>
    <h1 >
    <%if(typeof(item.value) == 'object' && item.title.value == 2) { %>
    <span><%=item.value[0]%></span>
    <span><%=item.value[1]%></span>
    <%} else { %>
    <%=item.value %>
    <%} %>
    </h1>
    <%} else if(item.tagname=='select'){ %>
    <h1 >
    <%=item.value %>
    </h1>
    <%} else if(item.tagname=='tabs') { %>
    <h1 >
    <%for(j = 0; j < item.data.items.length; j ++) { %>
    <span data-key="<%=item.data.items[j].id %>" ><%=item.data.items[j].name %></span>
    <% } %>
    </h1>
    <% } else{ %>
    <%} %>
    事件绑定的实现
    header组件本身继承至Abstract.View这个类,所以只要设置
    this.events = {}
    便能以事件代理的方式将事件绑定至根元素,而header的事件一般就是click事件:
    代码如下:
    setEventsParam: function () {
    var item, data = this.datamodel.left.concat(this.datamodel.right).concat(this.datamodel.center);
    for (var i = 0, len = data.length; i < len; i++) {
    item = data[i];
    if (_.isFunction(item.callback)) {
    this.events['click .js_' + item.tagname] = $.proxy(item.callback, this.viewScope);
    }
    }
    },
    这里有一个需要注意的点便是,事件绑定的钩子便是我们的tagname,这个是唯一的,我们会为每个标签动态生成“.js_tagname”的类,以方便事件绑定
    老接口的兼容
    之前便说了,该组件是一个老组件的翻新,于是各个业务团队已经使用了,比如原来是这样调用的:
    代码如下:
    this.header.set({
    title: '基本Header使用',
    subtitle: '中间副标题',
    back: true,
    backtext: '取消',
    tel: { number: 1111 },
    home: true,
    search: true,
    btn: { title: "登录", id: 'confirmBtn', classname: 'header_r' },
    events: {
    returnHandler: function () {
    console.log('back');
    },
    homeHandler: function (e) {
    }
    }
    });
    而现在我们期望的调用方式是这样的:
    代码如下:
    this.header.set({
    left: [],
    center: {},
    right: [
    { tagname: 'home', callback: function () { } },
    { tagname: 'tagname', value: 'value', data: {}, itemFn: function(){}, callback: function () { } }
    ]
    });
    这个时候我们应该怎么做呢?当然是不破不立,先破后立,当然是要求业务团队改!!!然后被无情的喷了回来,于是做了接口兼容
    翻新老组件,接口兼容是必须的,如果不是底层机制发生颠覆,而颠覆可以带来颠覆性的成绩,接口还是不建议改!
    这里上面便是新接口的调用,下面是老接口的调用,效果如下:
    名单1
随便看

 

在线学习网考试资料包含高考、自考、专升本考试、人事考试、公务员考试、大学生村官考试、特岗教师招聘考试、事业单位招聘考试、企业人才招聘、银行招聘、教师招聘、农村信用社招聘、各类资格证书考试等各类考试资料。

 

Copyright © 2002-2024 cuapp.net All Rights Reserved
更新时间:2025/5/23 1:32:16