WEB前后端交互(UI界面和数据内容)如何实现

来源:互联网 发布:webpack node api 编辑:程序博客网 时间:2024/04/28 08:11

作为刚接触前端的不久的童鞋,大家都会兴奋于CSS和JS所带来漂亮界面,然而,前端工程师除了UI重构外,还有非常重要的职责在正确的区域渲染出服务端的数据。毕竟,我们要构建一个大的web应用,必然不是普普通通的静态页面构成。通常一般情况正常流程是这样子的:

通过对数据库的调用管理进行交互。
前台一般是对数据库内容按照页面代码控制进行捡索并展示出来形成页面。
后台主要是对数据库进行管理,增、删、改

下文将列举将来前端工程师(确切地讲就是全栈工程师)应该必备的同后端打交道的常用技能。。

(注意只适合新手入门使用,老司机可以点评补充。谢谢!)

——————————【常规做法】——————————

HTML赋值

输出到 Element 的 value 或 data-name

<input type="hidden" value="<?php echo $user_avatar;?>" /><div data-value="<?php echo $user_avatar;?>"></div>

渲染结果

<input type="hidden" value="https://avatars1.githubusercontent.com/u/3949015?v=3&s=40" /><div data-avatar="https://avatars1.githubusercontent.com/u/3949015?v=3&s=40"></div>

使用 JS 获取

$('input').val();// http://jquery.bootcss.com/jQuery.data/$('div').data('avatar');

优点:

不占用全局变量,由 JS 自由获取。

使用建议:

适合传递简单数据,也非常适合多个简单数据与 Element 绑定关系。

<ul><li>nimojs <span data-userid="1" >删除</span></li><li>nimo22 <span data-userid="2" >删除</span></li><li>nimo33 <span data-userid="3" >删除</span></li><li>nimo44 <span data-userid="4" >删除</span></li><li>nimo55 <span data-userid="5" >删除</span></li></ul><script>$('span').on('click',function(){  $.post('/ajax/remove/',$(this).data('userid'),function(data){    // ...  })})</script>

JS赋值

将数据填充到 <script> 的 JavaScript 变量声明中。

<script>var user_avatar = "<?php echo $user_avatar;?>";// 渲染结果// var user_avatar = "https://avatars1.githubusercontent.com/u/3949015?v=3&s=40";</script>

或使用 Smarty 后端模板引擎:

<script>
var user_avatar = "{$user_avatar}";
</script>

优点:
传递数据非常方便。前端直接调用 user_avatar 变量使用数据。

缺点:

为了传递一个字符串数据占用了全局变量 user_avatar,当有很多数据需要传输时则会占用很多全局变量。
如果返回数据存在换行将会导致JS报错

// 渲染结果有换行符var user_id = "https://avatars1.githubusercontent.com/u/3949015?v=3&s=40";// Uncaught SyntaxError: Unexpected token ILLEGAL

优化:

可以通过指向的某一个变量存放所有后端返回的内容,最小程度占用全局变量。例:

// PHP 代码var SERVER_DATA = {  username: {$username},  userid: {$userid},  title: {$title}}// 渲染结果var SERVER_DATA = {  username: "NimoChu",  userid: 1,  title: 'F2E'}

使用建议:

需要最快速度传递数据给 JS 并十分确定此数据稳定时,使用此方式。数据格式复杂的建议使用script填充JSON 或AJAX获取JSON 方法。

script填充JSON
什么是JSON?

填充 JSON 数据到 <script> 标签中,前端通过 DOM 获取 JSON字符串并解析成对象。

<script type="text/template" id="data">{"username":"nimojs","userid":1}</script><script>var data = JSON.parse($('#data').html());//{username:"nimojs",userid:1}</script>

优点:

页面加载完成后就可以获取到数据。不占用全局变量,可传递大量数据集合。

缺点:

数据量特别大时会导致页面初次加载变慢。变慢并不只是文件大小导致的,也因为服务器查询数据并返回合集是需要时间,可使用AJAX获取JSON完成按需加载和加载等待。

使用建议:

适合传递在DOM加载完成时就需要用到的大量数据集合。例如:前端控制页面渲染,后端将JSON数据源填充到 <script> 由前端使用 JavaScript模板引擎进行页面渲染。


————————【交互做法】——————————

服务端渲染

谈起服务端渲染,对于动态服务而言,这个世界上跑的大多数页面都经历过服务端的数据渲染,接口->前端赋值->模版渲染 。这一切都在服务器完成,我们查看源码时候,可以看到完整的html代码,包括每个数据值。

常用的php模版有,Smarty,Blade,Mustache,如果你们团队使用Smarty,我们可以看到一些view的文件里会前套Smarty的模版语言;

<div>  {foreach $list as $item}    <h3>{$item['name']}</h3>    <p>{$item['desc']}</p>{/foreach}</div>

如果Node,js作为服务端的话,这个时候我们可以使用前端模版渲染的模块,比如ejs,doT,jade等等。

注意不同的模版可能存在不同模版语法,需要自己学习使用

AJAX

当然服务端渲染随着单页应用以及Restful接口的兴起,Ajax逐渐成为目前前后端交流最为频繁的方式。Ajax实际核心是XmlHttpRequest,我们通过对该对象的操作来进行异步的数据请求。

// 一般流程var oReq = new XMLHttpRequest();  oReq.addEventListener("load", function(res) {      // your code to do something});oReq.open("GET", "http://www.example.org/example.txt");  oReq.send();

实际上我们接触到最多jQuey就有很好的封装,比如$.ajax$.post等,如果用Angular的话我们可以用$http服务,除了这些之外,我们可以使用第三方的Ajax库qwest等。

如果使用Ajax的话,我们不得不面临一些问题,由于同源限制的问题,我们不得不去克服这个问题,这个时候我们可以要求服务端,设置header头,header('Access-Control-Allow-Origin: *');或者叫设置nginx配置

add_header 'Access-Control-Allow-Origin' 'http://yourweb.com';  add_header 'Access-Control-Allow-Credentials' 'true';  add_header 'Access-Control-Allow-Methods' 'GET';

当然这不是最好的做法,实际现在我们也可以这么做:

ajax -> 代理 -> API

我们可以用php的curl或者通过服务器的配置来实现反向代理。从而达到同源的效果。

前端工程师一定要要求每次请求的数据接口一严格遵循基础的数据结构要求,尽管js是弱变量类型语言,但是我们还是应该严格要求,是数组,就不应该是对象,是数字就不应该是字符串,这样做有利于降低隐藏bug并且提升前后端工作效率。

JSONP

JSONP算作JSON的一种”使用模式”,可用于解决主流浏览器的跨域数据访问的问题。由于CORS的支持,我们可以简单的将数据封装成一个js脚本请求,当然我们在jquery中会用到。

function logResults(json){    console.log(json);}$.ajax({  url: "https://yourapi.com/api",  dataType: "jsonp",  jsonpCallback: "logResults"});

comet

聊Comet我们还得说下短轮询,由于某些特定的业务需求,比如通知,我们需要有及时的数据更新,我们能够想到的就是使用setInterval每隔一定时间比如10s去获取一次请求,从而做到一些通知更新,但是这并不一种高效的做法,这会增加服务器的请求数量。这个时候有了另外一种概念,“反向Ajax”,由服务器进行数据推送, Comet能够让信息近乎实时的被推送到页面上,非常适合要求实时性的获取的数据的页面。

如图所示,就是一个简单的Comet模型,就是数据请求后挂起,直到有数据响应推送到客户端,这个时候客户端再发起一个新的连接。

这样相对来说可以减少一定数量的请求,以及数据的及时响应,从而一定意义的实现所谓推送。

一个简单的PHP Demo代码,就是我们需要这端代码一直运行着…

while(true) {      set_time_limit(0);    echo 'data';    flush();    b_flush();    sleep(3);}

JavaScript:

function createStreamingClient(url,progress,finished){    var xhr=new XMLHttpRequest(),received=0;    xhr.open("get",url,true);    xhr.onreadystatechange=function(){        var result;        if(xhr.readyState==3){            result=xhr.responseText.substring(received);            received+=result.length;            progress(result);        }else if(xhr.readyState==4){             finished(xhr.responseText);        }    };    xhr.send(null);    return xhr;}//  var client = createStreamingClient(url,fuc1,func2)

SSE Server-Sent Events

SSE是围绕只读Comet交互推出的API或者模式。SSE API用于创建到服务器的单向连接,服务器通过这个连接可以发送任意数量的数据。服务器响应的MIME类型必须是text/event-stream,而且是浏览器中的Javascript API能解析的格式输出。

现对于Comet,我们可以看出我们只进行了一次连接,然后服务端会去控制数据的响应,从而发送给客户端。这样相对来说,但是如同定义的描述,这种只适合只读数据的情形。比如一些通知和状态码这样的。SEE的使用非常简单,只需要掌握这几个api就行:

var es = new EventSource('http://your.api.com'  function listener(event) {      console.log(event.data);}// 创建一个SSE连接es.addEventListener("open", listener);  // 响应获取消息的事件es.addEventListener("message", listener);  // 发生错误es.addEventListener("error", listener);

注意:如果在回话过程中遇见错误后,默认程序会重新发起一次新的连接,从而防止挂掉就不再响应了

服务端(node,php)的代码,可以参考:https://github.com/Yaffle/EventSource

Web Sockets

HTML5 WebSocket 设计出来的目的就是要取代轮询和 Comet 技术,使客户端浏览器具备像 C/S 架构下桌面系统的实时通讯能力。 浏览器通过 JavaScript 向服务器发出建立 WebSocket 连接的请求,连接建立以后,客户端和服务器端就可以通过 TCP 连接直接交换数据。也就是我们可以使用web技术构建实时性的程序比如聊天游戏等应用。

其实Web Sockets 的API很少,就下面这些

websocket = new WebSocket("ws://your.socket.com:9001");  // 大开websocket.onopen = function(evt) { /* do stuff */ }; //on open event  // 当web socket关闭websocket.onclose = function(evt) { /* do stuff */ };  // 进行通信时websocket.onmessage = function(evt) { /* do stuff */ };  // 发生错误时websocket.onerror = function(evt) { /* do stuff */ };  // 向服务器发发送消息websocket.send(message); //send method  websocket.close(); //close method

对于服务端的话,PHP支持了很多socket 相关api,但是我们可以使用更加成熟的框架(实用)比如phpsocket.io,Ratchet.当然node.js写 socket也非常得心应手,node.js对高并发支持相对较好,可以使用http://socket.io/。

服务端大概会做下面的事情: + 创建一个socket + 绑定地址和端口 + 监听进入的连接 + 接收新的连接 + web socket 握手 + 解码数据

Demo教程

注意:SSE和 Web Sockets 都是新的api,需要大家考虑兼容性*

小结

说了那么多简单总结下,大家想明白几点就行了,客户端与服务端谁先主动,是否强调数据的实时性。

  • AJAX – 请求 → 响应 (频繁使用)
  • Comet – 请求 → 挂起 → 响应 (模拟服务端推送)
  • Server-Sent Events – 客户单 ← 服务端 (服务端推送)
  • WebSockets – 客户端 ↔ 服务端 (未来趋势,双工通信)

1 0