如何优雅的把一个静态网页变成动态网页

2,037 阅读5分钟
原文链接: www.gzzysoft.cn

一般来说,我们做网页的流程是这样的

        设计稿->静态网页->动态网页

从设计稿到静态网页的过程,相对来说还是比较愉快的,因为你可以看到一个美丽的网页慢慢呈现的过程。但是从静态网页到动态网页的过程相对来说就有些令人讨厌了。以前,我们都是拼接字符串,然后用innerHTML的方式生成网页。那样的代码真的很丑陋,而且你又不能直接预览静态网页。后来,有了JS模板,我们写起来可能就相对优雅一些,我们可以把代码写在这样的script标签里面。

<script type="text/x-jquery-tmpl" id="tpl2">
    <div class="row video-entry-row">
        <div id="video_${id}" data-video-id="${id}" class="col-xs-12">
            <div class="media video-entry">
                <div class="pull-left video-left">
				<a href="###" class="thumbnail">
				<img
                        class="media-object img-responsive"
                        src="${albumUrl}" alt="teaching"
                        onerror="this.onerror=null;this.src='img/video-preview-unavailable.png';">
				</a>
                    <button data-toggle="popover"
                            class="popover-trigger btn btn-default btn-xs avideo"
                            data-original-title="" title="">Created:${vCount}</button>
                    <br>
					<a href="create_en.html?vid=${id}" class="btn btn-primary btn-xs avideo">Create</a>
                    <div class="thumbnail-callout">
					</div>
                </div>
                <div class="media-body">
                    <h6>
					<span class="title">${title}</span>
                    <small class="duration">${$item.transTime()}</small>
                    </h6>
                    <div class="description">${description}</div>
                </div>
            </div>
        </div>
    </div>
</script>

到此,似乎已经很方便了。可是,我们仍然有点不满意。因为我们不能直接把html代码写在正常的标签里面,意味着我们不能像静态网页去浏览,而且我们必须把代码从正常的标签里面移到script标签里面去。

基于此,我有了一个想法,为什么不直接解析正常的dom,然后填充动态的数据呢?!于是有了下面的写法:

<div id="list">
    <div class="day">
        <div class="dayTitle">
            <a data="date">日期:2018年10月14日</a>
        </div>


        <div class="postTitle">
            <a class="postTitle2" data="title">Form表单之复选框checkbox操作</a>
        </div>
        <div class="postCon">
            <div class="c_b_p_desc">
                <div data="isEdit"><span data="desc" val="false">摘要: </span><span data="desc" contenteditable="true"
                                                                                  val="true">摘要: </span></div>
            </div>
        </div>
        <div class="clear"></div>
        <div class="postDesc"><span data="fav">0</span> posted @ <span data="time">2018-10-14 23:14</span> <a
                rel="nofollow" class="edit" data="edit">编辑</a></div>
        <div class="clear"></div>

    </div>
</div>

我们通过data属性把数据跟dom关联起来,个人觉得这是最简的写法了。你可能觉得两个大括号不是更简单吗?问题是,那种不是标准的html,意味着他不能正常解析,而且其实看起来挺恶心的,在你没有映射数据的时候,看起来就是一坨屎。我们这种写法的好处在于,他在没有数据的时候,看起来仍然是一个正常的网页。意味着你只要在你静态网页的基础上添加一个属性就OK了,是不是很优雅~~

好了,事情好像可以到此为止了。哦,不对,要更新数据怎么办。OK,那我们通过上面的写法,已经把dom跟数据映射起来了,当然也可以通过数据找到要更新的dom了,所以只要定义一个类似这样的函数就OK了。

function updateData(data) {
    var args = [];
    for (var i = 1; i < arguments.length; i++) {
        args.push(arguments[i]);
    }
    if (args.length) {
        mapDom(data, data._dom, null, args)
    } else {
        mapDom(data, data._dom)
    }
}

当然,反过来,我们也可以通过dom找到对应的数据了~

function getData(dom){
    for(var i=0;i<_m.length;++i){
        if(_m[i].dom==dom){
            return _m[i].data;
        }
    }
}

好了,事情好像真的可以到此为止了。可是,我们是不是经常会遇到很多页面公用一个模块。我总是在想,要是能从其他页面直接拖过来就好了。嗯,当然,这个想法就要借助ide了,事情就会变得复杂了。所以,纯粹一点的方法就是定义一个标签。其他页面引进去就好了。类似这样~~

<post c="7" id="post1"></post>

OK,现在我们终于可以实现组件化了。当然我们还要先做一些事,就是把对应的标签解析成相应的模块。嗯,这个其实就是把上面的过程封装成一个对象就OK了。

var post=new MMM("post",t, function(){
    var n=parseInt(this.container.attr("c"));
    if(!n){
        n=100;
    }
    var o={
        "date": "2015-09-09",
        time: '2015-09-09 08:08',
        title: 'JAVA 入门手册',
        desc: '很快,我们就将进入JAVA的新世界~~',
        isEdit: false,
        fav:0,
        _events:_events
    };
    var t=Date.now();
    var arr=[];
    for(var i=0;i<n;++i){
        arr.push(deepClone(o));
    }
    this.setData(arr);
});

然后通过标签找到对应的模块就好了~

我们好像还漏了一件事,事件交互呢?没事,我们可以在data里面定义啊,只要把相应的data字段跟定义的事件绑定起来,就相当于绑定了dom跟事件,如下:

var _events= [{
    type: "blur", handler: function (parent, el) {
        parent.isEdit = false;
        parent.desc = el.text();
        updateData(parent, "isEdit", "desc");
        //mapData(list, 'list1');
    }, "data": "desc"
},{
    type: "click", handler: function (parent, el) {
        parent.isEdit = true;
        console.log("click");
        var dom=_getDom(parent,'desc');
        updateData(parent, "isEdit");
        dom.focus();
    }, "data": "edit"
},{
    type:'click',handler:function(parent,el){
        ++parent.fav;
        updateData(parent,"fav");
    },'data':'fav'
}];

好了,基本就是这样了,最后,代码在这里~~ coding.net/u/guodayang…

本文由 melody 创作,采用 知识共享署名4.0 国际许可协议进行许可
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名
最后编辑时间为: 2019/02/16 12:05