2014年7月2日星期三

使用jquery ajax代替iframe - Darly

本邮件内容由第三方提供,如果您不想继续收到该邮件,可 点此退订
使用jquery ajax代替iframe - Darly  阅读原文»

大家在实际编写网页时可能会遇到网页中需要嵌套网页的情况,这时候通常想法就是通过iframe标签。

但实际用过的人都知道其有种种的不方便,比较直观的问题就是iframe的自适应高度,这也是处理起来比较麻烦的问题,随便百度下都是一大串的代码。

iframe貌似还有个重大的缺点,那就是搜索引擎的“爬虫”程序无法解读这种页面,当“爬虫”遇到多个页面嵌套的网页时只看到框架却找不到链接,然后认定此网站是死站点并离开。

学过SEO(搜索引擎优化)的朋友都知道,这对网页无疑是毁灭性的打击。

但是我们确实需要嵌套网页怎么办?比如:

这里拿个微信举例,用户都知道当切换下面的功能时顶部的页头及询问的工具栏样式是不变的。所以我们只需要在用户点击下面不同的功能按钮时改变中间的内容即可。

那即使不考虑SEO,至少布局上有没有比iframe更方便的东西呢?jquery ajax就能做到,它不仅能发起请求还能装载页面。

稍微介绍下jquery ajax,首先我们来比较下传统和jquery的ajax的不同

传统javascript ajax封装函数:

function ajax(method,url,param,flag,returnFun){
var httpRequest="";
if(window.XMLHttpRequest){
httpRequest
=new XMLHttpRequest();
}
else if(window.ActiveXObject){
httpRequest
=new ActiveXObject("Microsoft.XMLHTTP");
}
httpRequest.onreadystatechange
=function(){
if(httpRequest.readyState==4 && httpRequest.status==200){
returnFun(httpRequest.responseText);
}
};
if(method=="get"){
var queryString="";
if(param !="" || param !=null){
queryString
="?"+param;
}
httpRequest.open(
"get",url+queryString,flag);
httpRequest.send(
null);
}
else if(method=="post"){
httpRequest.open(
"post",url,flag);
httpRequest.setRequestHeader(
"content-type","application/x-www-form-urlencoded");
httpRequest.send(param);
}
}

封装后的写法:

ajax("post","../login.do","username="+username+"&pwd="+pwd,true,function(text){}

参数:1.请求方式 2.请求路径 3.参数传递 4.是否异步刷新 5.回调函数

jquery ajax:

$.ajax({ 选项 })

jquery ajax的选项有很多,简单例几个常用的比如:

data:数据

cache:是否缓存

success/error:成功/失败时的回调函数

type:请求类型

url:请求路径

要想更深入的了解可以下个jquery API看看。

比较实用的两种用法

第一种用法,对服务器的数据进行操作:

var username="jack";
var password=123;
$.ajax({
type:
"post",
url:
"../insert.do",
data:
"username="+username+"&password="+password,
success:
function(msg){
if(msg=="ok"){
alert(
"complete");
}
}
})

这就是个最简单的通过node.js添加数据的jquery ajax请求。

type设置类型为post;url设置请求路径;data设置要传递的参数,注意写法;如果要查询数据,回调函数中的回调值msg一般转换为JSON字符串的格式传回,要显示出来通过JSON.parse(msg)转换为JSON对象。

第二种用法,就是如何装载页面:

$.ajax({
url: "index.html",
cache:
false,
success:
function(html){
$(
"#content").html(html);
}
});

注意此时回调函数的返回值不再是JSON字符串类型的数据了,而是html网页。

做个简陋的例子:

<div id="content" style="border: 1px solid red;width: 210px"></div>
<button onclick="turnPage('weixin.html')">微信</button>
<button onclick="turnPage('tongxunlu.html')">通讯录</button>
<button onclick="turnPage('zhaopengyou.html')">找朋友</button>
<button onclick="turnPage('wo.html')"></button>
function turnPage(url){
$.ajax({
type:
"post",
url:url,
success:
function(html){
$(
"#content").html(html);
}
})
}

设置一id为content的没有定义高度的div,下有四个按钮对应四个不同路径。路径值作为参数传递给turnPage函数,获取指定页面的所有内容,将获取的内容装入id为content的div中。

点击“微信”跳转到weixin.html页面,其中只有一个h1标签:

基于链表的C语言堆内存检测 - clover_toeic  阅读原文»

说明

本文基于链表实现C语言堆内存的检测机制,可检测内存泄露、越界和重复释放等操作问题。

本文仅提供即视代码层面的检测机制,不考虑编译链接级的注入或钩子。此外,该机制暂未考虑并发保护。

相关性文章参见:

C语言通用双向循环链表操作函数集

C语言内存使用的常见问题及解决之道

一 原理

堆内存泄漏检测机制的基本原理是截获对内存分配和释放函数的调用,从而跟踪每块内存的生命周期。例如,每次成功分配一块内存后,将内存分配信息(如指向它的指针、文件名、函数名、行号和申请字节数等)加入一个全局链表中;每当释放一块内存时,再从链表中删除相应的内存信息。这样,当程序结束时,链表中剩余的内存信息结点就对应那些未被释放的内存。

当运行环境支持断点调试时,记录下内存分配的序号会很有用;当运行环境支持堆栈回溯时,可记录回溯信息以便观察泄露时的函数调用栈。此外,可根据使用者指定的文件名和行号信息过滤链表结点,以输出指定内存申请代码处的回溯信息。

对于隐式内存泄露,可在程序运行过程中监控当前内存的总使用量和分配释放情况。以分配内存时的文件名和行号为索引,遍历链表结点即可计算出各处已分配但未释放的内存总量。若在连续多个时间间隔内,某文件中某行所分配的内存总量不断增长,则基本可确定属于隐式内存泄露(尤其是多线程引起的)。

当模块提供动态内存管理的封装接口时,可采用“红区”技术检测内存越界。例如,接口内每次申请比调用者所需更大的内存,将其首尾若干字节(守护字节,Guard Bytes)设置为特殊值,仅将中间部分的内存返回给调用者使用。通过检查特殊字节是否被改写,即可获知是否发生内存越界。其结构示意图如下:

需要注意的是,这些检测机制均会造成目标程序性能上的损失,因此最好能在编译时(通过编译选项)或运行时(通过设置使能标志等)可选地激活。

二 实现

本节将基于《C语言通用双向循环链表操作函数集》一文中的链表接口,实现堆内存检测机制。

文中“OMCI_”和“Omci”前缀为代码所在模块名信息,使用接口时可按需修改这些前缀。

2.1 数据结构

定义内存管理信息结构体如下:

1 typedef struct{
2 const CHAR *pFileName; //内存管理函数调用处所在文件名
3 const CHAR *pFuncName; //内存管理函数调用处所在函数名
4 INT32U dwCodeLine; //内存管理函数调用处所在代码行号
5 INT32U dwMemSize; //内存管理函数申请到的内存字节数
6 VOID *pvMemAddr; //内存管理函数返回的内存指针地址
7 }OMCI_MEM_INFO;

这些信息将作为结点数据插入下面的全局链表中:

1 T_OMCI_LIST gtMemLeakCheckList = {.pHead=NULL, .pTail=NULL, .dwNodeNum=0, .dwNodeDataSize=0};

为统计内存分配情况,还定义如下结构体:

1 typedef struct{
2 INT32U dwAllocBytes; //申请内存的总字节数
3 INT32U dwAllocTimes; //申请内存的总次数
4 INT32U dwFreeBytes; //申请内存的总字节数
5 INT32U dwFreeTimes; //释放内存的总次数
6 }T_MEM_STATIS;

这些统计值将存入下面的全局结构中:

1 static T_MEM_STATIS gMemStatis = {0};

2.2 宏代码

为完成基本的内存分配和释放工作,必须调用系统提供的相应库函数(如malloc/calloc和free)。但直接使用库函数无法得到文件名等信息,因此需要借助宏对库函数进行封装:

1 //动态内存宏,使用方式同系统函数calloc和free,但不可与后者混用
2 #define OMCI_ALLOC(dwMemSize) OmciAlloc((dwMemSize), __FILE__, FUNC_NAME, __LINE__)
3 #define OMCI_FREE(pvMemBuf) OmciFree((pvMemBuf), __FILE__, FUNC_NAME, __LINE__)

此处考虑到OmciAlloc/ OmciFree函数可内置内存统计和越界检查,且相比内存泄露检测对系统资源和性能的影响不大,因此未使用条件编译控制。若不需要这些额外的好处,可采用下面的封装方式:

1 #ifdef OMCI_MEM_CHECK
2 #define OMCI_ALLOC(dwMemSize) OmciAlloc((dwMemSize), __FILE__, FUNC_NAME, __LINE__)
3 #define OMCI_FREE(pvMemBuf) OmciFree((pvMemBuf), __FILE__, FUNC_NAME, __LINE__)
4 #else
5 #define OMCI_ALLOC(dwMemSize) calloc((dwMemSize), 1)
6 #define OMCI_FREE(pvMemBuf) free((pvMemBuf))
7

没有评论:

发表评论