`
jindw
  • 浏览: 508513 次
  • 性别: Icon_minigender_1
  • 来自: 初到北京
社区版块
存档分类
最新评论

决定在Lite XML中集成编译客户端模板功能

阅读更多

直接在服务断模板中划出一块做客户端模板

在模板编译过程中,会把<c:client节点下的模板内容编译成js代码。渲染到客户端中可以直接通过js调用,因为不需要在客户端直接解析模板源代码,所以,能达到一个更高的性能。

 

支持的方式大概是这样的:



<html>
    <head>
      <title>模板测试</title>
       <!-- 申明一段客户端模板 -->
       <c:client id="userListTemplate ">
            <h3>用户列表</h3>
            <c:for items="${userList}" var="user">
                 <p>用户名:${user.name}</p>
                 <p>所在公司:${user.company}</p>
                 <hr/>
            </c:for>
       </c:client>

    </head>
<body>
    。。。。。。
    <script>
    function onPageChange(userList){
        E("userList").innerHTML = userListTemplate (userList)
    }
    </script>
</body>
</html>

 

 

 

 

 

 

分享到:
评论
21 楼 jiazhigang 2009-04-21  
xml早就有这个技术了,何必另起炉灶。
20 楼 jindw 2009-04-21  
nihongye 写道
编译成js函数,有什么用?


什么用处就在于自己去发掘了。呵呵
目前主要用在需要在前端组装ui的运用中,比如自定义首页那类。

当然也不都是那么极端,我觉得只要需要局部刷新的富客户端运用,都可以尝试。

数据模型也不一定非要服务端给,对于复杂的前端运用来说。
客户端完全应该有一个自己的数据模型,针对模型编程,而不是针对ui编程。
19 楼 nihongye 2009-04-21  
编译成js函数,有什么用?
18 楼 jindw 2009-04-13  
这就是沟通的误差,往往必须反复多次才能减少这种误差,呵呵。

zozoh 写道

引用
对于有工作经验的人,很容易犯先入为主的错误,我也经常犯类似错误,呵呵。
比如:
一提Java,就是JSP。

想问问,你的模板解析在什么时候做的呢? 在编译时,还是在运行时?

没错,实在编译时完成的,不过,这个编译过程可以在程序运行中第一次使用的时候编译。
java和js版本现在是自己编译,php版本可以通过java提供的编译服务远程编译,现在可以直接使用 http://litecompiler.appspot.com的编译服务。

zozoh 写道

引用
一看到xml,名称空间 就会想起jsp taglib。

你的 c: 看来是 client 的意思,哈哈,我说怎么和 jstl 重了呢

还是错了,c:不是 client的意思,我之所以取名c 确实是受jstl影响,不过我更愿意把它理解成condition,但是,现在加上 client之后,condition已经不止condition的意思了,还是叫core吧,呵呵

zozoh 写道

引用
一想起jsptaglib实现,就会认为他每次都会跑一遍。

taglib 是会和 jsp 代码一起变成 java 代码,在被编译成 class, 这个class 中你 taglib 变成的那段 java 调用每次请求都要走一遍,有什么错吗?

影响中jsp的taginf好像可以插入一些申明代码,我想可能也能插入一些静态内容吧,我也没怎么用过,不敢乱说。
不过我我在Lite中的编译是直接吧编译后的js静态插入到中间代码中的,也就是说,吧模板翻译成脚本的工作不会做第二次。


17 楼 zozoh 2009-04-10  
引用
其实也就是一些认识上的先入为主的误区。我上面讲的也不清楚,我罗列一下吧:
1.“jsp的请求”,“必须泡在JSP环境下”
这是一个跨平台的模板引擎,就算在Java环境上用,现在也没有支持jsp的tag,和jsp一点关系都扯不上。

咳,是这样的啊,的确理解错了。

引用
2.“每次对这个jsp的请求,你就会编译一遍”
为什么要这么做呢?这个猜测一定事拍屁股想出来的,^_^。

嗯,这个是我说错了。顺嘴就说了,呵呵。

引用

3.“你根本不输出 <c:client id="userListTemplate "> 这段内容”
其实,上面贴出的例子中也完全可以看出来,这里并没有这种内容的输出(可能我理解错了)。

看来你没明白我的意思是说,根本不输出 <c:client id="userListTemplate "> 编译后的 javascript 内容

引用
对于有工作经验的人,很容易犯先入为主的错误,我也经常犯类似错误,呵呵。
比如:
一提Java,就是JSP。

想问问,你的模板解析在什么时候做的呢? 在编译时,还是在运行时?

引用
一看到xml,名称空间 就会想起jsp taglib。

你的 c: 看来是 client 的意思,哈哈,我说怎么和 jstl 重了呢

引用
一想起jsptaglib实现,就会认为他每次都会跑一遍。

taglib 是会和 jsp 代码一起变成 java 代码,在被编译成 class, 这个class 中你 taglib 变成的那段 java 调用每次请求都要走一遍,有什么错吗?

引用
一想到模板,他一定在服务端运行。前端XHR请求数据
一想起前端模板,他一定要在前端解析。

这个我就不好说什么了,呵呵
16 楼 jindw 2009-04-10  
其实也就是一些认识上的先入为主的误区。我上面讲的也不清楚,我罗列一下吧:

1.“jsp的请求”,“必须泡在JSP环境下”
这是一个跨平台的模板引擎,就算在Java环境上用,现在也没有支持jsp的tag,和jsp一点关系都扯不上。

2.“每次对这个jsp的请求,你就会编译一遍”
为什么要这么做呢?这个猜测一定事拍屁股想出来的,^_^。

3.“你根本不输出 <c:client id="userListTemplate "> 这段内容”
其实,上面贴出的例子中也完全可以看出来,这里并没有这种内容的输出(可能我理解错了)。

对于有工作经验的人,很容易犯先入为主的错误,我也经常犯类似错误,呵呵。
比如:
一提Java,就是JSP。
一看到xml,名称空间 就会想起jsp taglib。
一想起jsptaglib实现,就会认为他每次都会跑一遍。
一想到模板,他一定在服务端运行。前端XHR请求数据
一想起前端模板,他一定要在前端解析。





avidmouse 写道
jindw 写道
zozoh 写道
你实际上是把HTML模板,变成一个 JS 函数,这个函数返回的是字符串。 每次对这个jsp的请求,你就会编译一遍。

我的想法大概是这样的:
当用户请求你的网页的时候,你根本不输出 <c:client id="userListTemplate "> 这段内容,
如果当用户调用 userListTemplate(userList)  你就向服务器发请求,请求一个叫 userList 的模板,拿下来,存在 window 对象上,下次再叫 userListTemplate(userList)的时候,你就直接返回给它。
就写作这么一小段 JS 就足够了。

至于服务器端,可以用php,asp,ruby,java 随便什么都无所谓。



恕我直言,你的理解很多是错的。

很多是错的,很多指什么?没有申明这个变量吧?

15 楼 avidmouse 2009-04-10  
jindw 写道
zozoh 写道
你实际上是把HTML模板,变成一个 JS 函数,这个函数返回的是字符串。 每次对这个jsp的请求,你就会编译一遍。

我的想法大概是这样的:
当用户请求你的网页的时候,你根本不输出 <c:client id="userListTemplate "> 这段内容,
如果当用户调用 userListTemplate(userList)  你就向服务器发请求,请求一个叫 userList 的模板,拿下来,存在 window 对象上,下次再叫 userListTemplate(userList)的时候,你就直接返回给它。
就写作这么一小段 JS 就足够了。

至于服务器端,可以用php,asp,ruby,java 随便什么都无所谓。



恕我直言,你的理解很多是错的。

很多是错的,很多指什么?没有申明这个变量吧?
14 楼 jindw 2009-04-10  
zozoh 写道
你实际上是把HTML模板,变成一个 JS 函数,这个函数返回的是字符串。 每次对这个jsp的请求,你就会编译一遍。

我的想法大概是这样的:
当用户请求你的网页的时候,你根本不输出 <c:client id="userListTemplate "> 这段内容,
如果当用户调用 userListTemplate(userList)  你就向服务器发请求,请求一个叫 userList 的模板,拿下来,存在 window 对象上,下次再叫 userListTemplate(userList)的时候,你就直接返回给它。
就写作这么一小段 JS 就足够了。

至于服务器端,可以用php,asp,ruby,java 随便什么都无所谓。



恕我直言,你的理解很多是错的。
13 楼 Bernard 2009-04-09  
没有能把异常源码行抛出所需的信息么?
我现在也很头疼这个问题。
编译时检查行肯定没问题,可在生产过程出要抛出错误相关行就必须记录住源码行或者按照一定的特征信息重新扫描模版源文件。
其实给出错误区块描述也可以。

呃~~你不是不喜欢xslt么~~我看这个怎么越写越像xslt。

还有一种修饰性模版操作方法,非常直观,侵入性很小。
和这主题关系不是很大,但在写Js时比较常用,可以参考一下。

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js"></script>
<script type="text/javascript">
    jQuery(document).ready(function(){
        var data = [
            {title:"title_1"},
            {title:"title_2"},
            {title:"title_3"},
            {title:"title_4"},
            {title:"title_5"}
        ];
        var ex = jQuery("._example");
        var el = null;
        for(var i = data.length - 1;i >= 0;i--){
            el = ex.clone();
            el.removeClass("_example");
            el.html((el.html() || "").replace("{$title}",data[i].title));
            ex.after(el);
        }
        ex.remove();
    });
</script>


<ul>
    <li class="myli _example">{$title}</li>
</ul>
12 楼 whaosoft 2009-04-09  
这个比v和f 那俩个好用吗??
11 楼 zozoh 2009-04-09  
你实际上是把HTML模板,变成一个 JS 函数,这个函数返回的是字符串。 每次对这个jsp的请求,你就会编译一遍。

我的想法大概是这样的:
当用户请求你的网页的时候,你根本不输出 <c:client id="userListTemplate "> 这段内容,
如果当用户调用 userListTemplate(userList)  你就向服务器发请求,请求一个叫 userList 的模板,拿下来,存在 window 对象上,下次再叫 userListTemplate(userList)的时候,你就直接返回给它。
就写作这么一小段 JS 就足够了。

至于服务器端,可以用php,asp,ruby,java 随便什么都无所谓。

10 楼 jindw 2009-04-09  
zozoh 写道
恩,这个不是关键,但是这个解决方案只能跑在 JSP 容器, 如果你用纯 JS 来作会不会更好。
因为你这个框架要作的事情就是替别人来缓存一组 HTML 字符串,一个不超过 50 行的 JS 文件就能全部搞定,而根本不用任何服务器端的代码才对。



我想你理解错了。我为什么要在服务端做?
因为我需要在模板编译环节做脚本的前端模板的编译,只要一次。

因为如果不这样做,模板的解析放在客户端,每次都要解析一遍,开销算谁的。
仍外,这个貌似50行代码是做不了这个事情的,至少我没有这本事。呵呵
9 楼 zozoh 2009-04-09  
恩,这个不是关键,但是这个解决方案只能跑在 JSP 容器, 如果你用纯 JS 来作会不会更好。
因为你这个框架要作的事情就是替别人来缓存一组 HTML 字符串,一个不超过 50 行的 JS 文件就能全部搞定,而根本不用任何服务器端的代码才对。
8 楼 jindw 2009-04-08  
zozoh 写道
原来是这样啊,呵呵。 看来我理解错了,你说的没错,这里基本不包括复杂的逻辑,当然不太会出错。

如果 <c:client> 的就是把自己的 body 那些内容变成一个字符串返回的话,你为啥每次都拼接呢? 为啥不在 document onload 的时候放在一个全局的 object 里面,key 就是你的 client id, values 就是这段 innerHTML。 如果这个全局变量叫做 window.$patterns  我在使用的时候,直接调用 window.$patterns[modleId]
就能取得我要的 innerHTML,这样我在使用的时候,会更方便吧?


呵呵,这个建议太技术人员了吧^_^。用户体验不要求性能的极限,只是要求性能问题不要让用户体验到。
在这种要求下,微乎其微的可能的性能提升远没有保持代码的简单优雅重要。
7 楼 zozoh 2009-04-08  
原来是这样啊,呵呵。 看来我理解错了,你说的没错,这里基本不包括复杂的逻辑,当然不太会出错。

如果 <c:client> 的就是把自己的 body 那些内容变成一个字符串返回的话,你为啥每次都拼接呢? 为啥不在 document onload 的时候放在一个全局的 object 里面,key 就是你的 client id, values 就是这段 innerHTML。 如果这个全局变量叫做 window.$patterns  我在使用的时候,直接调用 window.$patterns[modleId]
就能取得我要的 innerHTML,这样我在使用的时候,会更方便吧?
6 楼 jindw 2009-04-07  
zozoh 写道
呵呵,泼点冷水:

你这个想法和我几年前的想法不谋而合,总体的思路是:通过一层中间层,提供更简便灵活的视图书写方法。
但是现在回头来看,这种思路颇有隔靴搔痒的感觉,因为很难用 Firebug 直接 Debug 我写的代码,我最多能 Debug “你的通过我写的代码而生成的代码” 你的框架就是靴子,我再怎么样,都要隔着靴子去解决我的问题(找我的 Bug)。所以,在开发时,还不如直接写几个真正有用的 jQuery 的插件来的痛快。

但同时,是我也真心期望你的项目能够成功,因为你的成功就意味着你成功的改变了别人的使用习惯,能做到这一点很不简单。我现在设计的框架,基本上都本着“不改变或者尽量不改变用户的使用习惯”为原则的,起码,在这点上,你很用勇气,所以赞一个先,期待你的突破。



回来解释一下这些疑问吧。


[list]
 
  • 语法错误让编译器解决。
  •   如果你模板中表达式本身有错,那么,你的编译器就会报告给你。
     
  • 不应该有太多调试的需求
  •   保持模板简单的原则,如果你的模板需要调试,那我可以认为你的模板设计的不好。
      半年前,那就那着LiteXML的早期版本做开发。压根就没有遇到调试需求。
      设计这个模板的时候,有一个目标,那就是尽量不需要文档。
      我们在开发过程中,没有做过任何相关培训,只有极少的关于语法的私下询问(貌似只有一次,当能,这也说明我们团队成员的水平还是非常不错的^_^)
     
  • 就算有调试需求,那就打开Firebug去Debug
  •   模板处理的逻辑是简单的,生成的代码结构也就是简单的。
      可以看一下对比:模板源代码
        <!-- 这里的内容会编译成JS函数(函数名userTemplate) -->
        <c:client id="userTemplate">
          <h1>前后端统一模板实例</h1>
          <div id="content">
            <h2>${title}</h2>
            <table cellspacing="0" cellpadding="0">
              <tr>
                <th>姓名</th>
                <th>公司</th>
                <th>年龄</th>
                <th>城市</th>
              </tr>
              <c:for var="item" items="${data}">
                <tr>
                  <td>${item.name}</td>
                  <td>${item.company}</td>
                  <td>${item.age}</td>
                  <td>${item.city}</td>
                </tr>
              </c:for>
            </table>
          </div>
        </c:client>
    

    这是自动生成的JS代码
    <script>/*<![CDATA[*/function userTemplate(_$0,_$1,_$2){
    	_$1={};
    	for(_$2 in _$0){_$1[_$2]=_$0[_$2]};
    	_$0=_$1,_$1=[];
    	_$2=function(c){return "&#"+c.charCodeAt()+";";}
    	with(_$0){
    		_$1.push("\t\t<h2>");
    		_$1.push(String(title).replace(/[<>&]/g,_$2));
    		_$1.push("</h2><table cellpadding=\"0\" cellspacing=\"0\">\t<tr>\t<th>姓名</th>\t<th>公司</th>\t<th>年龄</th>\t<th>城市</th>\t</tr>\t");
    		
    		var _$3=data;
    		var _$2=0;
    		if(typeof _$3 == 'number'){
    			_$3= new Array(_$3);
    		}else if(!(_$3 instanceof Array)){
    			var _$4= [];
    			for(item in _$3){
    				_$4.push({key:item,value:_$3[item]});
    			}
    			_$3=_$4;
    		}
    		for(;_$2<_$3.length;_$2++){
    			var item=_$3[_$2];
    			_$1.push("\t<tr>\t<td>");
    			_$1.push(String(item.name).replace(/[<>&]/g,_$2));
    			_$1.push("</td>\t<td>");
    			_$1.push(String(item.company).replace(/[<>&]/g,_$2));
    			_$1.push("</td>\t<td>");
    			_$1.push(String(item.age).replace(/[<>&]/g,_$2));
    			_$1.push("</td>\t<td>");
    			_$1.push(String(item.city).replace(/[<>&]/g,_$2));
    			_$1.push("</td>\t</tr>\t");
    		}
    		_$1.push("\t</table>\t");
    	}
    	return _$1.join('');
    }/*]]>*/</script>
    
    

     
  • “不改变或者尽量不改变用户的使用习惯”
  •   这一点确实很明智!!
    [/list]



    5 楼 jindw 2009-04-07  
    zozoh 写道
    呵呵,泼点冷水:

    你这个想法和我几年前的想法不谋而合,总体的思路是:通过一层中间层,提供更简便灵活的视图书写方法。
    但是现在回头来看,这种思路颇有隔靴搔痒的感觉,因为很难用 Firebug 直接 Debug 我写的代码,我最多能 Debug “你的通过我写的代码而生成的代码” 你的框架就是靴子,我再怎么样,都要隔着靴子去解决我的问题(找我的 Bug)。所以,在开发时,还不如直接写几个真正有用的 jQuery 的插件来的痛快。

    但同时,是我也真心期望你的项目能够成功,因为你的成功就意味着你成功的改变了别人的使用习惯,能做到这一点很不简单。我现在设计的框架,基本上都本着“不改变或者尽量不改变用户的使用习惯”为原则的,起码,在这点上,你很用勇气,所以赞一个先,期待你的突破。



    回来解释一下这些疑问吧。


    [list]
     
  • 语法错误让编译器解决。
  •   如果你模板中表达式本身有错,那么,你的编译器就会报告给你。
     
  • 不应该有太多调试的需求
  •   保持模板简单的原则,如果你的模板需要调试,那我可以认为你的模板设计的不好。
      半年前,那就那着LiteXML的早期版本做开发。压根就没有遇到调试需求。
      设计这个模板的时候,有一个目标,那就是尽量不需要文档。
      我们在开发过程中,没有做过任何相关培训,只有极少的关于语法的私下询问(貌似只有一次,当能,这也说明我们团队成员的水平还是非常不错的^_^)
     
  • 就算有调试需求,那就打开Firebug去Debug
  •   模板处理的逻辑是简单的,生成的代码结构也就是简单的。
      可以看一下对比:模板源代码
        <!-- 这里的内容会编译成JS函数(函数名userTemplate) -->
        <c:client id="userTemplate">
          <h1>前后端统一模板实例</h1>
          <div id="content">
            <h2>${title}</h2>
            <table cellspacing="0" cellpadding="0">
              <tr>
                <th>姓名</th>
                <th>公司</th>
                <th>年龄</th>
                <th>城市</th>
              </tr>
              <c:for var="item" items="${data}">
                <tr>
                  <td>${item.name}</td>
                  <td>${item.company}</td>
                  <td>${item.age}</td>
                  <td>${item.city}</td>
                </tr>
              </c:for>
            </table>
          </div>
        </c:client>
    

    这是自动生成的JS代码
    <script>/*<![CDATA[*/function userTemplate(_$0,_$1,_$2){
    	_$1={};
    	for(_$2 in _$0){_$1[_$2]=_$0[_$2]};
    	_$0=_$1,_$1=[];
    	_$2=function(c){return "&#"+c.charCodeAt()+";";}
    	with(_$0){
    		_$1.push("\t\t<h2>");
    		_$1.push(String(title).replace(/[<>&]/g,_$2));
    		_$1.push("</h2><table cellpadding=\"0\" cellspacing=\"0\">\t<tr>\t<th>姓名</th>\t<th>公司</th>\t<th>年龄</th>\t<th>城市</th>\t</tr>\t");
    		
    		var _$3=data;
    		var _$2=0;
    		if(typeof _$3 == 'number'){
    			_$3= new Array(_$3);
    		}else if(!(_$3 instanceof Array)){
    			var _$4= [];
    			for(item in _$3){
    				_$4.push({key:item,value:_$3[item]});
    			}
    			_$3=_$4;
    		}
    		for(;_$2<_$3.length;_$2++){
    			var item=_$3[_$2];
    			_$1.push("\t<tr>\t<td>");
    			_$1.push(String(item.name).replace(/[<>&]/g,_$2));
    			_$1.push("</td>\t<td>");
    			_$1.push(String(item.company).replace(/[<>&]/g,_$2));
    			_$1.push("</td>\t<td>");
    			_$1.push(String(item.age).replace(/[<>&]/g,_$2));
    			_$1.push("</td>\t<td>");
    			_$1.push(String(item.city).replace(/[<>&]/g,_$2));
    			_$1.push("</td>\t</tr>\t");
    		}
    		_$1.push("\t</table>\t");
    	}
    	return _$1.join('');
    }/*]]>*/</script>
    

    [/list]
    4 楼 jindw 2009-04-07  
    zozoh 写道
    呵呵,泼点冷水:

    你这个想法和我几年前的想法不谋而合,总体的思路是:通过一层中间层,提供更简便灵活的视图书写方法。
    但是现在回头来看,这种思路颇有隔靴搔痒的感觉,因为很难用 Firebug 直接 Debug 我写的代码,我最多能 Debug “你的通过我写的代码而生成的代码” 你的框架就是靴子,我再怎么样,都要隔着靴子去解决我的问题(找我的 Bug)。所以,在开发时,还不如直接写几个真正有用的 jQuery 的插件来的痛快。

    但同时,是我也真心期望你的项目能够成功,因为你的成功就意味着你成功的改变了别人的使用习惯,能做到这一点很不简单。我现在设计的框架,基本上都本着“不改变或者尽量不改变用户的使用习惯”为原则的,起码,在这点上,你很用勇气,所以赞一个先,期待你的突破。


    太晚了,明天再来答复你的疑问吧,先概括一下:
    你的担心不是没有道理,但是根据以往经验。我们没有碰到,也许基于Lite的实现就很难碰到。
    3 楼 jindw 2009-04-07  
    已经在Lite XML1.0Alpha7中实现了。

    用法如下:
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" xmlns:c="http://www.xidea.org/ns/lite/core">
    	<head>
    		<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    		<title>前后端统一模板实例</title>
    		<link href="tablecloth.css" rel="stylesheet" type="text/css" media="screen" />
    	</head>
    	<body>
    		<div id="container">
    			<h1>前后端统一模板实例</h1>
    			<div id="content">
    				<h2>${title}</h2>
    				<table cellspacing="0" cellpadding="0">
    					<tr>
    						<th>姓名</th>
    						<th>公司</th>
    						<th>年龄</th>
    						<th>城市</th>
    					</tr>
    					<c:for var="item" items="${data}">
    						<tr>
    							<td>${item.name}</td>
    							<td>${item.company}</td>
    							<td>${item.age}</td>
    							<td>${item.city}</td>
    						</tr>
    					</c:for>
    				</table>
    			</div>
    			<div>
    				<c:for var="item" items="${[1,2,3,4,5,6]}">
    					<a href="#" onclick="reset(${item});return false;">${item}</a>
    				</c:for>
    			</div>
    		</div>
    		<!-- 这里的内容会编译成JS函数 -->
    		<c:client id="userTemplate">
    			<!-- 偷懒有道,xpath直接包含前面那段模板片断 -->
    			<c:include xpath="//*[@id='content']/*" />
    		</c:client>
    		<script>/*<![CDATA[*/
    		function reset(id){ 
    			var content = document.getElementById('content');
    			var model = ${JSON.stringify({title:"客户端模板",data:data})}
    			//我们对模型做一点简单的修改(当能你也可以XHR从服务断获取数据,或者从客户端数据模型获取)
    			model.title +=id;
    			for(var i=0;i!=model.data.length;i++){
    				var item = model.data[i];
    				for(var n in item){
    					item[n]+=id;
    				}
    			}
    			content.innerHTML = userTemplate(model);
    		}/*]]>*/
    		</script>
    	</body>
    </html>
    
    
    2 楼 zozoh 2009-04-06  
    呵呵,泼点冷水:

    你这个想法和我几年前的想法不谋而合,总体的思路是:通过一层中间层,提供更简便灵活的视图书写方法。
    但是现在回头来看,这种思路颇有隔靴搔痒的感觉,因为很难用 Firebug 直接 Debug 我写的代码,我最多能 Debug “你的通过我写的代码而生成的代码” 你的框架就是靴子,我再怎么样,都要隔着靴子去解决我的问题(找我的 Bug)。所以,在开发时,还不如直接写几个真正有用的 jQuery 的插件来的痛快。

    但同时,是我也真心期望你的项目能够成功,因为你的成功就意味着你成功的改变了别人的使用习惯,能做到这一点很不简单。我现在设计的框架,基本上都本着“不改变或者尽量不改变用户的使用习惯”为原则的,起码,在这点上,你很用勇气,所以赞一个先,期待你的突破。

    相关推荐

      X-Lite sip客户端

      **X-Lite sip客户端**是基于SIP(Session Initiation Protocol)协议的VoIP(Voice over Internet Protocol)软件电话,专为用户提供免费的通信服务。SIP是一种互联网信令协议,用于建立、管理和终止多媒体通信会话...

      PaddleLite在windows下编译需要的dirent.h文件

      PaddleLite在windows下编译需要的dirent.h文件

      后台管理模板Karmanta-lite

      【后台管理模板Karmanta-lite】是一款专为开发者设计的高效、简洁且功能丰富的后台界面模板。这款模板基于现代Web技术构建,旨在提供一个快速开发后台应用的基础框架,帮助开发者节省时间和精力,专注于业务逻辑的...

      MMS-Lite中文参考手册.pdf

      在阅读和理解MMS-Lite中文参考手册的过程中,需要特别注意对协议栈配置、ACSE认证、MVL接口、对象管理以及MMS服务器与客户端设施的详细介绍,这些都是实现和使用MMS-Lite不可或缺的重要知识点。

      navicat8lite下载 navicat8lite_mysql_en下载 navicat8lite_mysql_en mysql客户端下载

      navicat8lite下载 navicat8lite_mysql_en下载 navicat8lite_mysql_en mysql客户端下载 非常不错的mysql客户端

      navicat8lite mssql_zh客户端

      不过,由于标题明确提到的是MSSQL客户端,我们可以推测这可能是 Navicat 8 Lite 版本的安装文件,只是在压缩包中可能包含了错误的或不相关的文件,或者是版本或平台混淆的结果。 Navicat8lite的主要功能可能包括: ...

      coreftp_lite_64bit FTP客户端软件,开源易用

      开源易用的coreftp_lite_64bit FTP客户端软件,方便通过FTP上传或下载文件

      树莓派zero交叉编译tensorflow-lite所需依赖,工具链及编译好的库文件

      树莓派zero交叉编译tensorflow-lite所需依赖,工具链及编译好的库文件(tensorflow2.4.1) 使用说明参考博客: https://blog.csdn.net/weixin_41973774/article/details/114807080

      liteide

      liteIDE是一款专为Go语言(Golang)设计的开源集成开发环境(IDE),它由中国的开发者基于Qt框架开发,旨在提供一个轻量级且功能强大的编程工具。在Go语言的开发社区中,liteIDE因其简洁的界面、良好的性能以及对Go...

      IMSlite客户端软件使用手册.docx

      IMS lite 客户端软件使用手册是 IMS lite 客户端软件的使用指南,旨在指导用户如何正确地使用 IMS lite 客户端软件,实现视频预览、设备管理、本地回放、远程回放、录像计划、系统设置等功能。 IMS lite 客户端软件...

      rt7lite软件制作集成XP驱动光盘

      在IT行业中,制作集成驱动的光盘是一项常见的任务,特别是在安装旧版操作系统如Windows XP时。这个过程可以显著简化系统安装,确保所有必要的硬件驱动都能顺利工作。rt7lite是一款专为此目的设计的工具,它使得用户...

      x-lite呼叫软件 客户端

      x-lite,sip的客户端,非常好用的一款呼叫软件,方便使用,稳定性好,是最受欢迎的SIP客户端软件。

      SIP 电话PC客户端X-Lite_Win32

      X-Lite客户端的安装文件"X-Lite_Win32_1103k_53621.exe"是该软件的下载包,它包含了运行在Windows系统上的所有必要组件。这个文件大小为1103千字节,版本号可能为53621,这通常表示开发者对软件进行的一次更新或优化...

      X-Lite-Win32-1011s-41150.7z

      标题中的“X-Lite-Win32-1011s-41150.7z”是指一个适用于Windows操作系统的X-Lite软件的压缩包文件,版本号为1011s,版本编号41150,格式为7z。X-Lite是一款轻量级的SIP(Session Initiation Protocol)客户端,广泛...

      x-lite 3.0 用户手册

      X-Lite 3.0 是由CounterPath Solutions公司开发的一款下一代软电话客户端,旨在为用户提供媲美传统电话的所有功能,并在此基础上增加了桌面和移动计算机增强功能。通过简单的鼠标点击或键盘操作,用户可以拨打电话、...

      mysql中文绿色图形化客户端Navicat Lite for MySQL

      MySQL是一种广泛使用的开源关系型数据库管理系统,而Navicat Lite for MySQL是一款专为MySQL设计的中文图形化管理工具,它提供了便捷的界面,使得数据库管理变得更加直观和高效。这款工具适用于初学者和专业开发人员...

      Rt7Lite中文英文语言文件

      在Rt7Lite中,语言文件的作用是定义了程序界面的所有文字和提示信息,包括菜单、按钮、对话框等元素上的文本。英文.resX文件包含了所有英文界面的字符串,而中文.resX文件则提供了相应的中文翻译。当用户选择不同的...

      X-Lite 3.0 汉化版

      X-Lite是一款流行的SIP(Session Initiation Protocol)客户端,主要用于VoIP(Voice over Internet Protocol)通信。它为用户提供了便捷的软电话服务,允许通过互联网进行语音通话。X-Lite 3.0汉化版是该软件的一个...

    Global site tag (gtag.js) - Google Analytics