尚学堂_马士兵_AJAX_学习笔记

★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
AJAX:Asynchronous Javascript And XML
    核心是JavaScript 不是XML
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
web2.0 的应用:

web2.0 的核心:XML + AJAX:博客 就是web2.0 的应用:

RSS也叫聚合RSS是在线共享内容的一种简易方式
(也叫聚合内容,Really Simple Syndication)
Really Simple Syndication是一种描述和同步网站内容的格式
RSS:
    web2.0 的应用
    我博客上的所有的文章,转换成一种XML 格式,就有一个好处
    1.
    文章名是什么,文章内容是什么,大家认同这种写法,
    搜索引擎就可以直接搜到你们家博客上 
    2.
    我给你一个客户端,这个客户端可以读任何博客,任何的网站博客都会公布一个RSS
    RSS 的标签是固定的,任何的客户端都可以进行分析,分析好后给读者做展现

    说白了还是一个XML 的应用
    有人叫推模式(push):服务器端直接推给客户端,不需请求,每个人要一个客户端。
    网络经济,就是客户端的经济,给你装插件,任意给你推东西
    发请求的是拉模式(pull)。


我们要打好底子,迎接将来的各种潮流。

★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
正常情况下,到服务器取东西:
要点连接,发请求,等待处理(刷新整个页面),拿到结果(显示)
AJAX情况下,不刷新页面,发起请求
AJAX:我不再刷新页面,就能从服务器取东西。看起来像本机的应用程序了
        拿到处理,只刷新一部分页面,
AJAX 实例:使用不刷新页面的验证方法:注册的时候提示用户名已经被使用
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★

AJAX 基本概念:

* 构建网页的一种综合使用JavaScript 和 XML 的技术(XML 可有可无)
* 不是什么划时代的技术(javascript 旧的,只是刷新了人的脑子)
* HTML 网页的异步传输技术
    * 在等待网页的传输过程中,用户依然可以和系统进行交互
    * 页面不用刷新就可以更新内容
        * 合理的运用可以让用户感觉更好更方便
        * 但也不要滥用    

* Asynchronous Javascript and XML    :可以不用XML
    同步:一直等小孩醒,什么事都不干(一直的等待)
    异步:你一边干别的事,小孩醒了调用一个方法给你一个通知(网络传输的过程中,可以干别的)
    
    AJAX 就是异步的Javascript ,有没有 XML 无所谓
    客户端发出请求,继续干别的,服务器端处理好请求后,调用事先写好的JS 代码
* 典型的流程
    1. 客户端触发异步操作
    2. 创建新的XMLHttpRequest 对象(关键)
    3. 与 Server 进行连接
    4. 服务器端进行连接处理
    5. 返回包含处理结果的XML 文档
    6. XMLHttpRequest 对象接收处理结果并分析
    7. 更新页面
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
    
XMLHttpRequest(浏览器内置的一个对象,内置的一个组件)
* 重要的JavaScript 对象,通过它提起对服务器端的(http)请求
    这个请求提起后不会刷新页面,只是在背后运行
* 可以通过JavaScript 提起请求
    * 如果要提起多个请求,需要多个XHR 对象
* 请求的结果被预先定义好的方法处理(处理好后,调用预先定义好的方法)    

平常我们要访问一个http server ,要在浏览器里敲http://www...
这是直接敲,手动来敲。
编程上,我们可以使用XMLHttpRequest 这个对象来自动的发起一个向服务器端某个页面的请求

★★★★★★★★★★
XMLHttpRequest 属性:(particl list)

* readyState    (this is a property of many JavaScript objects)
            XHR 对象自己有一下内部的状态,状态值是一些int 类型的数
    - 0 = UNINITIALIZED; open not yet called
                    //还没有初始化
    - 1 = LOADING; send for request not yet called
                    //请求还没有发到服务器端,打开了,跟服务器端建立连接了
    - 2 = LOADED; send called, headers and status are avalilable
                    //调用了一个方法,已经把我的请求发过去了,服务器端给了反馈
                    //http 头信息
    - 3 = INTERACTIVE; downloading response,
                        responseText only partially set
                    //头信息拿到了,正在取得服务器给我的内容
    - 4 = COMPLETED; finished downloading response
                    //取得服务器端的信息完成
                    //usually wait for XHR.readyState == 4

* responseText        //反馈回来的当成纯文本
    - response as text; null if error occurs of ready state < 3
* responseXML        //反馈回来的当成XML 文档对象,一个 DOM 模型
    - response as DOM Document object; null if error occurs or ready state < 3
* status 
    - integer status code
* statusText 
    - string status
    
★★★★★★★★★★                
XMLHttpRequest 方法:(partial list)

    
* Basic methods
    - open(method, url[, async]) -initializes a new HTTP request
        * method can be "GET", "POST", "PUT"or"DELETE"
        * url must be an HTTP URL(start with "http://")
        * async is a boolean indicating whether request should be sent
            saynchronously - defaults to true
    - send(body) -sends HTTP request     //body can be null
                //可以传XRH 的内容(body),一般情况下,参数跟后面就ok,传null
    - abort() - called after send() to cancel request
* Herder methods
    - void setRequestHeader(name, value)
    - String getResponseHeader(name)
    - String getAllResponseHeaders()
        * return a string where
            "header: value" pairs
            are delimited y carriage returns
    Example return value:
    Connection: Keep-Alive
    Date: Sun, 15 May 2005 23:55:25 GMT
    Content-Type:text/xml
    Server:WEBrick/1.3.1 (Ruby/1.8.2/2004-12-25)
    Content-Length:1810





★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★    

示例:    检查用户名是否被注册:register.jsp    25:25
    
        写javascript 不要全部写好再调试,定义方法后,马上看能不能调用
        写一个方法就alert 一下,看他有没有执行

★★★★★★★★★★★★★★★        
1. 客户端触发:
    <input type="text" size="20" id="userid" 
    name="username" onblur="validate();" >
    <span id="usermsg"></span>

★★★★★★★★★★★★★★★    
2. JavaScript 写触发的方法,向服务器端发起一个请求,让服务器端去处理
    必须创建XHR 对象:
    不刷新页面向服务器端发起请求
    <script type="text/javascript" >
        var req;    //定义一个全局的对象
                    //validate() 方法初始化 req 对象
        function validate() {
            var idField = document.getElementById("userid");    
                    //拿到id是userid的元素
            var url = "validate.jsp?id=" + escape(idField.value);
                    //发起请求的页面url:escape:返回url编码的字符串(识匹码)
                    //不同的浏览器,req 对象创建的语句不同
            if(window.XMLHttpRequest) {    
                    //netscape 浏览器,if window 的属性
                req = new XMLHttpRequest();    
            } else if(window.ActiveXObject) {    //IE
                req = new ActiveXObject("Microsoft.XMLHttp");
            }
            //req对象在后面(悄悄的)调用url 页面
            //1.什么方法open(get: 参数接后面),2.打开的网址 3.使用异步的模式
            req.open("GET", url, true);
            req.onreadystatechange = callback;    
//callback 函数回调,函数指针:不用(),多次调用,
//改变一次状态调用一次函数指针指向的函数        
            //处理完状态变化的时候调用callback 方法
            req.send(null);            
            //发送HTTP 请求
        }
    
    
    
        function callback() {
            alert(req.readyState);
        }
    
    </script>
    
★★★★★★★★★★★★★★★    
3.        Server 端进行处理,JSP 在Server 端是万能的

        创建要访问的JSP 页面:validate.jsp
        
        <%
                        //设置反馈页面信息,不能出现中文,要加上一个JSP 头
<%@ page contentType="text/html; charset=gb2312"%>                        
response.setContentType("text/xml");                
                        //return XML file
response.setHeader("Cache-Control", "no-store");    
                        //HTTP 1.1    prevents caching at IE
response.setHeader("Pragma", "no-cache");            
                        //HTTP 1.0
response.setDateHeader("Expires", 0);                
                        //prevents caching at the proxy server
                        //no chinese  
                        
                        //处理
response.getWriter().write("<msg>invalid</msg>");                    
%>

用户存在:在UserManager 中添加 boolean userExists,连上数据库,查一下,存在返回true
        JSP 中根据 JavaBean userExists 方法 返回的boolean 值,
                        判断返回给客户端的是valid 还是 invalid
客户端根据你返回的是valid 还是invalid,设定相关的DIV 里的内容                        

★★★★★★★★★★★★★★★        
4.        Server 端反馈,客户端接收
        Server 处理请求的方式不变,输出内容不一定是XML,
                            可以输出一个JS 语句,直接传到客户端运行
        服务器端反馈给客户端信息

        找不到validate.jsp TomCat 也会给你一个状态4 的反馈:404:没有
        判断Server 的反馈是正确的反馈

        拿到 Server 端的反馈后,在 客户端进行展现
        :解析XML
        
        function callback() {
        //alert(req.readyState);
        if(req.readyState == 4) {
            if(req.status == 200) {
                var msg = req.responseXML.getElementsByTagName("msg")[0];
//可能拿到标签的很多元素,是一个数组
//当一个元素里有一个text 文本的时候,相当于这个元素下面有子元素(数组)
                //alert(msg.childNodes[0]);                    
                setMsg(msg.childNodes[0].nodeValue);
            }
        }
    }
    
    function setMsg(msg) {        //把拿到的结果显示在<span> 里
        if(msg == "invalid")
            document.getElementById("usermsg").innerHTML = 
            "<font color='red'>用户名无效</font>";
        else
            document.getElementById("usermsg").innerHTML = 
            "<font color='black'>用户名可以使用</font>";
            
//getElementsByName        name 可能多个元素
//getElementById        id 就一个元素
    }
    
    这就是AJAX 基础 OVER ,不复杂,但很灵活
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
调试记录:
    JavaScript 最常错误:少写 } ,单词拼写错误

★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★

示例:下拉条的连动

    首页:
    1. 分类显示,可以分无限层,把原来的分类都删了
    2. 搜索分类,第一个分类select 显示根分类,第二个分类显示根分类对应的子分类

★★★★★★★★★★★★★★
删除旧商品:product.jsp
    删除的时候,给一个提示,是不是确定删,取消就不执行(javascript 实现)
    
    <a href="productdelete.jsp?id=<%=p.getId() %>" 
    target="detail" onclick="return confirm('确定删除')">删除</a>
    return false 就不执行链接

★★★★★★★★★★★★★★
    1. 直接在数据库删:
        delete from product;
        delete from category;
    2. 添加新类别,添加的是根类别
    2.1    电脑/软件/网络/办公
    2.2    珠宝首饰/礼品
    2.3    运动/户外/休闲
                一般根类别确定后很少改变
    添加子类别:
    2.1 笔记本、台式机、掌上电脑、应用软件
    2.2 项链、戒指
★★★★★★★★★★★★★★
    非AJAX 动态生成二级连动菜单:
    
    非 AJAX:    一次性拿到全部的菜单项,一级,二级都拿到
      AJAX:根据一级,到数据库拿二级
    
    
    开始写菜单连动,首先写一个静态的让他能动起来
    左右显示,别上下显示:放table 里,左一个td 右一个td

    非AJAX 不适合多级,
    
<%!
//定义一个内部使用方法,每当拿到一个topCategories 就为这个Category 生成一段二级目录JavaScript 代码
private String getSecondCategoryStr(List<Category> categories, 
Category topCategory) {
    StringBuffer buf = new StringBuffer();
    //buf.append("if(document.getElementById('cat1').
    options[document.getElementById('cat1').selectedIndex].value == "  
    + topCategory.getId() + ") {");
    
    int childCount = 1;                //请选择二级目录头,默认有一个
     
    for(int i=0; i<categories.size(); i++) {
        Category c = categories.get(i);
        if(c.getPid() == topCategory.getId()) {        //根类别的孩子
            //显示二级的后面代码,字符串要加引号,有双引号,用单引号
            buf.append("document.getElementById('cat2').options[" 
            + childCount + "].text = '" + c.getName() + "';\n");
            buf.append("document.getElementById('cat2').options[" 
            + childCount + "].value = '" + c.getId() + "';\n");
            childCount ++;
        }
    }
    //有双引号了,里面用单引号
    buf.insert(0, "document.getElementById('cat2').options[0].text 
    = '请选择二级目录';\n");
    buf.insert(0, "document.getElementById('cat2').options[0].value = '-1';\n");
    buf.insert(0, "document.getElementById('cat2').selectedIndex = 0;\n");
    buf.insert(0, "document.getElementById('cat2').options.length = " + childCount + ";\n");
    buf.insert(0, "if(document.getElementById('cat1').
    options[document.getElementById('cat1').selectedIndex].value == " 
     + topCategory.getId() + ") {\n");
    buf.append("}\n");
    
    return buf.toString();
}


 %>


<%
//10 个最新商品
List<Product> latestProducts = ProductMgr.getInstance().getLatestProducts(10);

//拿到全部的类别    grade 为1 的就是根类别
List<Category> categories = CategoryMgr.getCategories();
List<Category> topCategories = new ArrayList<Category>();

//定义一个 String 放前面生成的代码
String str = "";
for(int i=0; i<categories.size(); i++) {
    Category c = categories.get(i);
    if(c.getGrade() == 1) {
        topCategories.add(c);
        str += getSecondCategoryStr(categories, c);
    }
}
 %>



<!-- 类别连动 搜索开始 -->    


<script type="text/javascript">
    <!--
    function changeCategory() {
    //可以在后台打印str 看看
            <%=str %>
    }
    -->
</script>

<table>
        <tr>
            <td>
            <select  onchange="changeCategory()" id="cat1">
                 <option value=0 >查询所有一级目录</option>
                 <%
                for(int i=0; i<topCategories.size(); i++) {
                    Category c = topCategories.get(i);
                    
                    %>
                    <option value=<%=c.getId() %> ><%=c.getName() %></option>
                    <%
                }                 
                  %>
            </select>     
            </td>
            
            <td>       
            <select id="cat2" >                <!-- 根据一级目录的变化而变化 -->
                 <option value=5 >查询有二级目录</option>
            </select>            
            </td>
            
            <td>    
            <input type="text"  />
            </td>
            
            <td align="center" >
            <input type="image" height=19 width=61  />
            </td>    
        </tr>  
</table> 



          
<!-- 类别连动 搜索结束 -->


★★★★★★★★★★★★★★
使用AJAX 生成二级连动菜单:反馈字符串
        changeCategory() 
1.    把选择后,第一级菜单的id 传到服务器,
2.    服务器从数据库里取出来第二级Category 的,id,name...
3.    传递到客户端,客户端拿到后,进行分析,(不一定用XML 传递,可以用字符串)
4.    分析完成后形成JavaScript 代码,
5.    最后显示出来

实现:照猫画虎,模仿register.jsp     AJAX 实现用户名是否存在
        反馈的不是XML 是字符串



★★★★★★★★★★★★★★
调试记录:
    调试,就是打印错误
    1.
    打印,sql 语句正确,打印,返回的list.size()->错
    装到list 的时候 while 写成了 if 只有装一条了
    2.
    javascript 中的for 语句
    for(var i=0; i<categories.length; i++)
    3.
    alert("id=" + id  ",name=" + name);    少一个加号,后面的不显示
    alert("id=" + id + ",name=" + name);    
    4.     选择的一级列表是空,二级列表还是上次选择的二级列表
        选空的时候,客户端没有接到任何反馈,后台报错
        经典调试疑难杂症:    商城视频_75_index_search_ajax.avi
        老师手段多的很,解决它
    5. 
        javascript 都写完了再调试那是相当的愚蠢的
    6.
        JSP 不能写中文:编码问题,要加头
        <%@ page contentType="text/html; charset=gb2312"%>

★★★★★★★★★★★★★★
使用AJAX 生成二级连动菜单:反馈XML
    1.
    JSP 生成XML 
    
    for(int i=0; i<childs.size(); i++) {
    Category c = childs.get(i);
    buf.append("<category><id>" + c.getId() + "</id><name>" + 
    c.getName() + "</name></category>");
    }
    //添加一个根节点,XML
    buf.insert(0, "<categories>");
    buf.append("</categories>");

    System.out.println(buf);
    
    XML 文件头:
        <?xml version="1.0" encoding="gb2312"?>
        <    >
            <    >
            <    />
        <    />
        加上XML 文件头,IE就可以显示了,说明生成的XML 没有问题


    2.
    客户端解析XML :
    req.responseXML 是一个object 对象
    req.responseText 拿到对象的信息
    可以使用XML 组件解析XML
    
    javascript 解析XML    ,对语法不确定,写几句就alert 一下
    javascript 都写完了再调试那是相当的愚蠢的
    视频_78  必看,不能错过 节点解析问题
    一级目录空,没有问题,

★★★★★★★★★★★★★★
完全抛弃XML 使用原始的一次性拿出全部二级目录,生成JS 代码,反馈给客户端

另一种写法:很多大公司都这么写,中小型项目
(可以让二级列表字符串 在服务器端生成,动态生成javascript 代码)
让传递过来的javascript 代码执行

callback() 中:eval(req.responseText());

视频_77        找不到JSP XML输出错误,拖延时间

这种写法很多:
    产品翻页的时候,只刷新某一个东西:在服务器端动态生成这些JS 代码
    客户端eval 执行,写起来就是麻烦一点

二级连动 4 种方法:
1. 原始一次拿出所有一级二级目录(所有从数据库里预先取出)
2. AJAX 反馈:字符串
3. AJAX 反馈:XML,麻烦,
4. AJAX 反馈:JSP 动态执行 JavaScript ,原理:原始,一次拿出所有一级二级目录
还有一种使用内桢,不太用了

★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
AJAX 总结:
    AJAX 很多东西都在发展之中,
    很简单    提交到服务器去,处理后传回来
    有人就根据这个做出各种框架帮助你使用:
        比如生成字符串很麻烦,就有人给你写专门的类库来帮你实现
        form 不完善,写类库,帮你实现相应的form 
    AJAX 框架无数,没有一统天下的
    
我们学的是底层,框架怎么变,都知道背后的原理,练习熟练掌握
不用框架也能写出东西,到时候用哪种学哪种
灰狐开源站点:http://docs.huihoo.com/    
框架汇总:http://docs.huihoo.com/web/ajax/ajax-frameworks.html

介绍一下哪些有名:BackBase, DOJO,Google AJAXSLT,Sarissa
JSON(Javascript Object Notation):不考虑XML:专门和JS 联系
AJAX_JSP_Tag_Library,
其他:DWR(Web Remoting) 远程方法调用....
框架:
有的是远程的方法调用,
有的是针对于XML来回传,
有的就是动态生成JS 代码
有的就是生成自定义的字符串(面向对象的字符串Jason)

posted on 2014-07-02 23:40  suyupei  阅读(672)  评论(0)    收藏  举报

导航