几种web数据渲染模板对比
在web开发,实现视图、数据的分离,由前端工程师专门负责编写html页面,有php后台工程师写php接口返回json数字,那么中间如何将json数据绑定到html页面上有几种方法呢。基于这种需求大体上尝试了几种方法:
1)用jQuery加载json数据,操作DOM:
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title>1、测试传统的数据绑定</title> <!--引入jquery.js--> <script type="text/javascript" src="jquery.js"></script> <script type="text/javascript"> $(document).ready(function(){ alert("点击之后,修改p1"); document.getElementById("p1").innerHTML="修改了p1:javascript的DOM操作"; $("#btn").click(function(){ showMessage("信息提示:正在请求网络"); getJSON2(); }); }); function showMessage(msg){ alert(msg) } function getJSON2() { //jQuery.post()方法 $.post("http://192.168.1.122/yne_siteM/index.php/Home/Interface/mess2","username=188888", function(data,status) { alert("status="+status); try{ /*测试解析json var jsontext = '{"firstname":"Jesper","surname":"Aaberg","phone":["555-0100","555-0120"]}'; var data0 = JSON.parse(jsontext); alert(data0.surname);*/ //如果取到的已经是json对象,再JSON.parse就可能出错 // var data = JSON.parse(json); }catch (e){ alert(e.message); } document.getElementById("p1").innerHTML=data.status; //Y var dataArray = data.data; //data包含的json数组 var contents; for(var i=0 ; i<dataArray.length ; i++) { var jsonObject = dataArray[i]; //这里可以直接取数组下索引 var id = jsonObject.id; var title = jsonObject.title; var content = jsonObject.content; contents = "<li>"+title+" "+title+" "+content+"</li>"; $("#ol").append(contents); } }, "json" ); } </script> </head> <body> <h2>This is a heading</h2> <p id="p1">This is a paragraph.</p> <p id="p2">This is another paragraph.3333</p> <div id="newDiv"> <ol id="ol"> </ol> </div> <button type="button" id="btn">Click me</button> </body> </html>
2)用jsRender/jsView操作DOM,绑定数据:
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title>2、测试jsView的数据绑定</title> </head> <body> <h2>This is a heading</h2> <p id="p1">This is a paragraph.</p> <p id="p2">This is another paragraph.3333</p> <div id="newDiv"> </div> <div id="newDiv2"> </div> <button type="button" id="btn">Click me</button> <!--官方demo--> <script id="theTmpl" type="text/x-jsrender"> <b>{{:title}}</b> <ul> {{for members}} <li >{{:name}} lives in <b>{{:address.city}}</b></li> {{/for}} </ul> </script> <script> var data = { "title": "The A team", "members": [ { "name": "Pete", "address": { "city": "Seattle" } }, { "name": "Heidi", "address": { "city": "Sidney" } } ] }; var template = $.templates("#theTmpl"); var htmlOutput = template.render(data); $("#newDiv").html(htmlOutput); </script> <script id="theTmpl2" type="text/x-jsrender"> <b>status={{:status}}</b> <b>msg={{:msg}}}</b> <ul id="ul1"> {{for data}} <a href="/id={{:id}}"> <li id="{{:id}}">id={{:id}} title={{:title}} content={{:content}}</li> </a> {{/for}} </ul> <ul id="ul2"> {{for data}} <li class="xx.css" id="{{:id}}">id={{:id}} title={{:title}} content={{:content}}</li> {{/for}} </ul> </script> <!--引入jquery.js--> <script type="text/javascript" src="jquery.js"></script> <script type="text/javascript" src="jsviews.js"></script> <script type="text/javascript"> var dataArray; $(document).ready(function(){ alert("点击之后,修改p1"); document.getElementById("p1").innerHTML="修改了p1:javascript的DOM操作"; $("#btn").click(function(){ showMessage("信息提示:正在请求网络"); getJSON2(); }); }); function showMessage(msg){ alert(msg) } function getJSON2() { //jQuery.post()方法 $.post("http://192.168.1.122/yne_siteM/index.php/Home/Interface/mess2","username=1888888", function(data,status) { alert("status="+status); //绑定UI var template = $.templates("#theTmpl2"); var htmlOutput = template.render(data); $("#newDiv2").html(htmlOutput); //监听UI //选取id=ul2 的ul组件下的所有li $("ul#ul2 li").click(function() { alert("id="+$(this).attr("id")); }); //监听所有id以a开头的li // $("li[id^='a']").click(function() { // alert("id="+$(this).attr("id")); // }) }, "json" ); } </script> </body> </html>
3)用angularJS绑定数据:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <script src="angular.js"></script> <script src="jquery.js"></script> </head> <body> <body> <div ng-app="app1"> <div id="A1"> <input ng-model="name" type="text" placeholder="请输入姓名"> <p>我的姓名: {{name}}</p> </div> <div id="A2"> <input ng-model="age" type="number" placeholder="请输入年龄"> <p>我的年龄: {{age}}</p> </div> <div id="A3" ng-init="names=['Jani','Hege','Kai']"> <p>使用 ng-repeat 来循环数组</p> <ul> <li ng-repeat="x in names"> {{ x }} </li> </ul> </div> <div id="A4" ng-init="names=[ {name:'Jani',country:'Norway'}, {name:'Hege',country:'Sweden'}, {name:'Kai',country:'Denmark'}]"> <p>循环对象:</p> <ul> <li ng-repeat="x in names"> {{ x.name + ', ' + x.country }} </li> </ul> </div> <div id="A5" ng-controller="myCtrl1"> 名字: <input ng-model="name"> <h1>你输入了: {{name}}</h1> </div> <!--get方法--> <div id="A6" ng-controller="myCtrl2"> <p>ssss {{msg}}</p> <ul> <li ng-repeat="x in data">id={{x.id}},picurl={{x.picurl}}</li> </ul> </div> <!--post方法--> <div id="A7" ng-controller="myCtrl3"> <p>ssss {{msg}}</p> <ul> <li ng-repeat="x in data">id={{x.id}},picurl={{x.picurl}}</li> </ul> </div> </div> <!--尽量一个html里面只声明一个ng-app--> <div id="div2" ng-app="app2" ng-init="points=[1,15,19,2,40]"> <p>第三个值为 {{ points[2] }}</p> <button type="button" id="btn">Click me</button> </div> <script> <!--这里不能引入jQuery,会冲突--> var app1 = angular.module("app1",[]); var app2 = angular.module("app2",[]); angular.bootstrap(document.getElementById("div2"),['app2']); app1.controller("myCtrl1",function($scope){ $scope.name = "Joker"; }); //get方法 app1.controller('myCtrl2', function($scope, $http) { $http.get("http://192.168.1.122/yne_siteM/index.php/Home/Interface/GetBanner") .success(function(response) { $scope.status = response.status; $scope.msg = response.msg; $scope.data = response.data; }); }); // $.get("http://192.168.1.122/yne_siteM/index.php/Home/Interface/GetBanner") // .success(function(){ //// app1.controller("myCtrl2",function($scope){ //// $scope.msg = "jQuery Get"; //// }); // alert("ok"); // }); </script> </body> </body> </html>
4)用vue.js绑定数据:
<!DOCTYPE html> <html xmlns:v-on="http://www.w3.org/1999/xhtml"> <head lang="en"> <meta charset="UTF-8"> <title>测试vue.js</title> </head> <body> <div id="app"> {{message}} </div> <!--双向绑定--> <div id="app2"> <p>{{message}}</p> <input v-model="message"> </div> <!--渲染列表--> <div id="app3"> <ul> <li v-for="todo in todos"> {{ todo.text }} </li> </ul> </div> <!--处理用户输入--> <div id="app4"> <p>{{ message }}</p> <button v-on:click="reverseMessage">Reverse Message</button> </div> <div id="app5"> <input v-model="newTodo" v-on:keyup.enter="addTodo"> <ul> <li v-for="todo in todos"> <span>{{ todo.text }}</span> <button v-on:click="removeTodo($index)">X</button> </li> </ul> </div> <div id="app6"> <ul> <li v-for="todo in todos"> {{ todo.id }} {{ todo.title }} </li> </ul> </div> <!--引入vue.js框架--> <script type="text/javascript" src="vue.js"></script> <!--引入jQuery框架--> <script type="text/javascript" src="jquery.js"></script> <script> new Vue({ el:"#app", data:{ message: 'Hello Vue.js!' } }); new Vue({ el:"#app2", data:{ message: 'Hello Vue.js!' } }); new Vue({ el:"#app3", data:{ todos:[ { text: 'Learn JavaScript', title:"111" }, { text: 'Learn Vue.js', title:"222" }, { text: 'Build Something Awesome', title:"333" } ] } }); new Vue({ el:"#app4", data:{ message: 'Hello Vue.js' }, methods:{ reverseMessage: function(){ this.message = this.message.split('').reverse().join('') } } }); new Vue({ el:'#app5', data:{ newTodo:'', todos:[ { text:'Add some todos'} ] }, methods:{ addTodo:function() { var text = this.newTodo.trim(); if(text) { this.todos.push({text:text}); this.newTodo = '' } }, removeTodo: function (index) { this.todos.splice(index,1) } } }); //使用jQuery的post方法获取数据 $(document).ready( function getJSON(){ $.post('http://192.168.1.122/yne_siteM/index.php/Home/Interface/mess2','username=1888888',function(data,status){ var todos = data.data; //绑定数据 new Vue({ el: "#app6", data: { todos: todos } }); },'json'); } ); </script> </body> </html>
总结一下几种方法的体验:
方法一,jQuery直接操作DOM,会使原来HTML内容不完整,并且数据绑定之后用到大量的字符拼接,在可读性和可维护性上较差;
方法二,一定程度上改善了HTML的可读性,但是也是将一整块html标签抽离了放到<script id="theTmpl2" type="text/x-jsrender"></script>里面,也不够直观。
方法三,angularJS扩展了html,在兼容原来html的基础上通过模型绑定、控制器回调等方法,可以实现不破坏原来html内容的基础上实现数据绑定。但是,测试demo过程中,觉得写起来不够自然和有一定复杂性,而且框架比较大,和jQuery混用的效果也不好,会有一定冲突,在移动端性能可能不太好。
方法四,vue.js一定程度上融合了angularJS的一些优点,如不破坏html结果的前提绑定数据,更加轻量,可以同时用在移动端上,个人觉得比较合适快速开发使用。
具体项目demo已上传至github:
https://github.com/chq3272991/testJS.git