JavaEE学习day-53:ajax技术

一、ajax技术

1.ajax介绍:

使用ajax实现网页的局部刷新;在保留当前页面信息的基础上显示新的信息。

2.ajax的访问原理:

通过ajax引擎对象对服务器发送请求,使用ajax引擎对象接收服务器响应请求,再进行页面展现。
原理图

3.创建ajax对象:

          //创建ajax引擎对象
            var ajax;
            if(window.XMLHttpRequest){//火狐,谷歌...
                ajax=new XMLHttpRequest();
            }else if(window.ActiveXObject){//IE
                ajax = new ActiveXObject("Msxm12.XMLHTTP");
            }

4.ajax的状态码:

0:表示ajax引擎对象创建。
1:表示请求创建但是未发送 ajax.open("get","my");
2:请求发送 ajax.send(null);
3:请求处理完毕,正在接收响应内容。
4:响应内容接收完毕(重要状态)。

5.ajax的相应状态码:

200:表示一切正常。
404:资源未找到。
500:服务器内部错误。

          //声明事件监听函数
            ajax.onreadystatechange=function(){
                //判断ajax的状态码
                if(ajax.readyState==4){
                    //判断状态响应码
                    if(ajax.status==200){
                    //处理响应
                    //获取响应内容
                        var data = ajax.responseText;
                        //使用eval方法将字符串数据转换为js对象
                        eval("var obj="+data);
                    //获取div对象
                    var div = document.getElementById("showdiv");
                    div.innerHTML = data;
                    
                    }else if(ajax.status==404){
                        //获取div对象
                        var div = document.getElementById("showdiv")
                        div.innerHTML = "请求资源不存在";
                    }else if(ajax.status=500){
                        //获取div对象
                        var div = document.getElementById("showdiv")
                        div.innerHTML = "服务器繁忙";
                    }else{
                        //获取div对象
                        var div = document.getElementById("showdiv")
                        div.innerHTML = "未知错误";
                    }
                }   
            }

6.创建和发送ajax的请求:

创建ajax请求(设置异步或者同步)
ajax.open(method,url,ansyc);
method:表示请求方式
url:请求地址
ansyc:设置异步或者同步请求,true表示异步,false,表示同步。默认是异步的。

  • 请求方式:

(1)get方式:请求数据以?隔开的形式拼接在url的后面。请求数据不能写在send方法中。
(2)post方式:post方式需要单独的进行请求数据的设置。使用ajax.setRequestHeader("Content-Type","application/x-www-form-urlencoded");设置请求数据为键值对数据。如果有请求数据则ajax.send("键值对数据&键值对数据..."),如果没有请求数据则ajax.send(null)。

  • 异步和同步:

异步:
当前js函数继续执行,无须等待ajax请求的响应以及响应的处理。
同步:
当前js函数会等待ajax请求以及响应,当ajax响应处理完毕后,继续执行函数的剩余代码。

//发送请求
                    //get请求方式
                         //创建请求
                            ajax.open("get","my?uname=张三&pwd=123",false);
                        //发送请求
                            ajax.send(null);
                    //post请求方式
                        //创建请求
                        ajax.open("post","my",false);
                        //设置请求参数为键值对方式
                        ajax.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
                        //发送请求
                        ajax.send("uname=张三&pwd=123");
                //异步同步
                    var div=document.getElementById("showdiv");
                    alert(div.innerHTML);
            }

7.ajax使用流程:

(1)创建ajax引擎对象
(2)声明监听函数
//判断ajax状态码
//判断响应状态码
//获取响应信息(普通字符串和json格式的字符串)
//处理响应
(4)创建并发送ajax请求:创建请求(设置请求方式,设置请求地址,设置异步或者同步)
发送请求
(5)其他处理

二、Json学习

1.json的介绍:

  • json的概念:

其实json就是js创建对象的一种格式。保证对象中数据的紧密性 和完整性。

  • 为什么需要使用json:

服务器响应给浏览器的数据应该是字符串类型;但是如果数据量比较大,我们就需要在服务器端将数据拼接成一个良好格式的字符串数据,响应给浏览器。浏览器根据格式进行数据的解析和使用。

  • json的格式:

var 对象名={
键名:值,
键名:值,
...
键名:值
}

2.json的使用:

在服务器端将要响应的数据拼接成json格式的字符串,这样客户端(浏览器端)在接收到响应数据后;可以使用eval方法将json格式的字符串数据直接转换为对应的js对象,便于数据的操作。

  • eval()方法:

作用将字符串转换为对象。

eval("var obj="+data);//eval("var obj={uid:18,uname:'王五',age:18,fav:'看电影'}")

//使用eval方法将字符串数据转换为js对象
    eval("var obj="+data);
  • toJson()方法:

将java对象转换为对应的json字符串。

//创建对象
        User u = new User(01,"李四","1214",18);
        //json格式的字符串
        String str ="{18,'李四','1214',18}";
         //使用Gson对象
        String str = new Gson().toJson(u);
  • 代码示例:
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
    
    <title>json测试</title>
    <script type="text/javascript">
        function check(){
            var stu = {"name":"张三","age":18,"sex":'男'};
            alert(stu.name+"--"+stu.age+"--"+stu.sex);
        }
        function check2(){
            var wek=["day01","day02","day03","day04","day05","day06","day07"];
            for(var i=0;i<wek.length;i++){
                alert(wek[i]);
            }
        }
        function check3(){
            var arr = [{"name":"张三","age":18,"sex":'男'},{"name":"李四","age":20,"sex":'女'}]
            for(var i=0;i<arr.length;i++){
            alert(arr[i].name+"---"+arr[i].age+"--"+arr[i].sex);
            }
        }
    </script>


  </head>
  
  <body>
    <input type="button" value="测试json" onclick="check()"/>
    <input type="button" value="测试json2" onclick="check2()"/>
    <input type="button" value="测试json3" onclick="check3()"/>
  </body>
</html>

三、ajax实现用户名校验

1.实现思路:

(1)用户书写用户名信息,在失去焦点时进行用户校验
(2)失去焦点发送请求到服务器,服务器根据用户名信息去数据库中查询该用户名是否存在。
(3)将校验结果响应给客户端;
(4)在当前页面,也就用户名输入框后显示提示语。

2.CheckServlet

package com.zlw.servlet;

import java.io.IOException; 
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class CheckServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=utf-8");
        PrintWriter out = response.getWriter();
        //获取客户端提交的用户名
        String userName  = request.getParameter("userName");
        System.out.println(userName);
        //根据用户名查询数据库是否存在:select * from user where userName= ?;
        if ("dave".equals(userName)) {
            out.print("true");
        } else {
            out.print("false");

        }       
    }
}

3.index.jsp

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%
    String path = request.getContextPath();
    String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort()
            + path + "/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">

<title>用户名校验</title>
<script type="text/javascript">
    //创建XMLHttpRequest对象
    var ajax;
    function createXMLHttpRequest() {
        //根据不同的浏览器创建不同的XMLHttpReaquest对象
        if (window.XMLHttpRequest) {
            ajax = new XMLHttpRequest();
        } else if (window.ActiveXObject) {
            ajax = new ActiveXObject();
        }

    }

    //校验用户名是否存在
    function checkUserName() {
        //1.获取输入用户名
        var userName = document.getElementById("userName").value;
        //2.创建XMLHttpRequest对象
        createXMLHttpRequest();
        //3.打开连接:ajax.open(method, url,true|false)
        ajax.open("get", 'check?userName='+userName, true);
        //发送请求
        ajax.send(null);
        //注册回调函数
        ajax.onreadystatechange = callBack;
    }
    //回调函数:处理服务器端返回的结果
    function callBack() {
        if (ajax.readyState == 4 && ajax.status == 200) {
            var content = ajax.responseText;
            alert(content);
            if (content=='true') {
                document.getElementById("spanName").innerHTML = "<font color=red>用户名已存在</font>";
            } else {
                document.getElementById("spanName").innerHTML = "<font color=green>用户名可用</font>";
            }
        }
    }
</script>
</head>

<body>
    用户名:
    <input type="text" name="userName" id="userName"onblur="checkUserName()" />
    <span id="spanName"></span>
</body>
</html>
  • 用户名可用
    结果

4.封装ajax:

  • 为什么使用封装:

在使用ajax进行业务处理时,ajax的代码其实很多地方是相同的。这样造成编写代码时出现了重复编写,影响了开发的效率。

  • 封装的内容:

(1)请求方式:method ;
(2)请求地址:url;
(3)请求参数:data 请求参数的格式为键值对格式的字符串,不同的键值对使用&符号隔开.如果没有请求数据传入null。
(4)响应处理参数:deal200,该参数接收一个js的函数对象,函数对象中声明ajax响应数据的处理逻辑代码。
(5)异步同步设置:ansyc。

  • 代码示例:
//声明ajax函数
function myAjax(method,url,data,deal200,ansyc){
    //创建ajax引擎对象
    var ajax;
    if (window.XMLHttpRequest) {
        ajax = new XMLHttpRequest();
    } else if(window.ActiveXObject) {
        ajax= new ActiveXObject();
    }
    //声明监听函数
    ajax.onreadystatechange = function(){
        //判断ajax状态码
        if(ajax.readyState==4){
            alert("aaa");
            //判断响应状态码
            if(ajax.status==200){
                //获取响应数据
                var data = ajax.responseText;
                if(deal200){
                    deal200(data);
                }
            }
        }
    }
    //创建并发送请求
    if("get"==method.toLowerCase()){
        //创建请求
        ajax.open("get",url+(data==null?"":"?"+data),ansyc)
        //发送请求
        ajax.send(null);
    }else if("post"==method.toLowerCase()){
        //创建请求
        ajax.open("post",url+(data==null?"":"?"+data),ansyc);
        //发送请求
        ajax.send(data);
    }
}
  • 实现调用:
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
    <title>封装ajax</title>
<!-- 引入js文件 -->
     <script type="text/javascript" src="js/AjaxUtil.js"></script>
     <!-- 声明js代码域 -->
     <script type="text/javascript">
        //使用ajax进行处理
        myAjax("get","data","uname=张三",function(a){
        alert(a);
        })
     </script>
  </head>
  <body>
  <h4>ajax的封装</h4>
  </body>
</html>

四、jQuery中的ajax

1.jQuery的简介:

jquery是js的一个轻量型框架,已经将js创建的操作进行了封装,而ajax也是js的一部分,所以jQuery也已经将ajax进行了封装。

2.jQuery常用的ajax请求:

$.get(url,data,fn)

url:请求地址
data:请求参数,参数格式为json对象
fn:回调函数,注意函数要声明一个形参,用来接收响应数据。

$.post(url,data,fn)

url:请求地址
data:请求参数,参数格式为json对象
fn:回调函数,注意函数要声明一个形参,用来接收响应数据。

$.ajax({json格式参数}):参数说明参照api;

  • 常见事件:

beforeSend:函数---->发送请求前回调函数 .
complete:函数--->请求完成后回调函数 .
error:函数--->请求失败时回调函数.
success:函数---->请求成功后回调函数。

  • 常用的属性:

type:请求方式。
url:请求的服务端地址。
data:请求数据。

3.代码示例:

  • jQuery.jsp
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
    
    <title>校验用户名</title>
    <script type="text/javascript"src = "js/jquery-1.9.1.js"></script>
    <script type="text/javascript">
        $(function(){
            $(".userName").blur(function(){
                //获取文本框输入的用户名
                var userName = $(this).val();
                
                //使用jQuery中的$.ajax({参数})方法 发送ajax请求
                $.ajax({
                    type:'post',
                    url:'check',
                    data:'userName='+userName,
                    beforeSend:function(){//请求前展示加载图片
                    $("#unameSpan").html("<img src='' with='50px',height=50px/>")
                    },
                    success:function(data){//执行成功调用的回调函数
                    alert(data);
                    if(data=='true'){
                    $("#unameSpan").html("<font color=red>用户名已经被占用</font>");
                    }else{
                    $("#unameSpan").html("<font color=green>用户名可用</font>");
                    }
                    
                    }
                });
            });
        });
    </script>
  </head>
  <body>
    用户名:<input type="text" class="userName" value="" name="userName" id="userName" /><span id="unameSpan"></span>
  </body>
</html>
  • CheckServlet
package com.zlw.servlet;

import java.io.IOException; 
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class CheckServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=utf-8");
        PrintWriter out = response.getWriter();
        //获取客户端提交的用户名
        String userName  = request.getParameter("userName");
        System.out.println(userName);
        //根据用户名查询数据库是否存在:select * from user where userName= ?;
        if ("dave".equals(userName)) {
            out.print("true");
        } else {
            out.print("false");

        }       
    }
}
结果
结果

五、ajax实现三级联动案例

1.功能需求:

页面中有三个下拉框选项,分别为省下拉框,市下拉框,区/县下拉框选择省,则市下拉框中出现对应的该省下的市信息,选择市,则区/县下拉框中出现对应的该市下面的区/县信息

  • 使用技术:

ajax技术+jsp+servlet+jdbc;

2.需求分析:

(1)创建页面:页面中有三个下拉框,分别为省、市、区/县
(2)页面加载成功发起ajax请求,请求省的信息,并将响应结果
填充到省下拉框中
(3)选择省触发一个新的js函数 的执行,该函数中发起新的ajax请求
请求该省下的市信息,并将响应数据填充到市下拉框
(4)选择市信息触发一个新的js函数的执行,该函数中发起新的ajax请求
请求该市下的区/县信息,并将数据填充到区/县下拉框中

3.具体实现:

  • 数据库设计:
image.png

4.代码示例:

  • 操作数据库JDBC:
package com.zlw.dao.impl;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import com.zlw.dao.AreaDao;
import com.zlw.pojo.Area;
import com.zlw.util.DBUtil;

public class AreaDaoImpl implements AreaDao {
    /**
     * 根据parentid查询省份信息
     */
    @Override
    public List<Area> getAreaInfoService(int parentid) {
        List<Area> list = new ArrayList<Area>();
        Connection conn= null;
        String sql = "select * from area where parentid=?";
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            conn = DBUtil.getConnection();
            ps = conn.prepareStatement(sql);
            ps.setInt(1, parentid);
            rs = ps.executeQuery();
            while(rs.next()){
                Area area = new Area();
                area.setAreaid(rs.getInt("areaid"));
                area.setAreaname(rs.getString("areaname"));
                area.setParentid(rs.getInt("parentid"));
                area.setArealevel(rs.getInt("arealevel"));
                area.setStatus(rs.getInt("status"));
                list.add(area);
            }
            
        } catch (SQLException e) {
            e.printStackTrace();
        }finally{
            DBUtil.closeAll(rs, ps, conn);
        }
        
        return list;
    }
}
  • Servlet
package com.zlw.serlvet;

import java.io.IOException;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.google.gson.Gson;
import com.zlw.pojo.Area;
import com.zlw.service.AreaService;
import com.zlw.service.impl.AreaServiceImpl;

public class AreaServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=utf-8");
        
        //获取请求信息
        String str = request.getParameter("parentid");
        int parentid = Integer.parseInt(str);
        //处理请求信息
            //获取业务层对象
            AreaService as = new AreaServiceImpl();
            List<Area> list = as.getAreaInfoService(parentid);
        //响应处理结果
            response.getWriter().write(new Gson().toJson(list));
    }
}
  • jsp界面实现:
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
    
    <title>三级下拉框</title>
   <script type="text/javascript" src="js/jquery-1.9.1.js"></script>
   <script type="text/javascript">
    function parent(){
    
    $.get("area","parentid=0",function(data){
        var areas = eval(data);
        var sel = $("#parent");
        //清空原有内容
        sel.empty();
        //遍历
        for(var i=0;i<areas.length;i++){
            sel.append("<option value='"+areas[i].areaid+"'>"+areas[i].areaname+"</option>")
        }
    })
    
    }
    function city(value){
    var areaid = value;
        $.post("area","parentid="+areaid,function(data){
            var areas = eval(data);
        var sel = $("#city");
        //清空原有内容
        sel.empty();
        //遍历
        for(var i=0;i<areas.length;i++){
            sel.append("<option value='"+areas[i].areaid+"'>"+areas[i].areaname+"</option>")
        }
        })
    }
    function town(value){
    var areaid = value;
    $.post("area","parentid="+areaid,function(data){
            var areas = eval(data);
        var sel = $("#town");
        //清空原有内容
        sel.empty();
        //遍历
        for(var i=0;i<areas.length;i++){
            sel.append("<option value='"+areas[i].areaid+"'>"+areas[i].areaname+"</option>")
        }
        })
    }
    
   </script>
  </head>
  
  <body style="background-color: gray; color: green;" onload="parent()">
  <div style="margin: auto;width: 750px;margin-top: 250px  ">
    省:<select name="parent" id="parent" style="width: 100px;height:30px;"  onchange="city(this.value)"></select>
    市:<select name="city" id="city" style="width: 100px;height:30px;" onchange="town(this.value)"></select>
    区/县:<select name="town" id="town" style="width: 100px;height:30px;"></select>
   </div>
  </body>
</html>

  • 实现效果:
结果
结果
结果
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,826评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,968评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,234评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,562评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,611评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,482评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,271评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,166评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,608评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,814评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,926评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,644评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,249评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,866评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,991评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,063评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,871评论 2 354

推荐阅读更多精彩内容

  • 概要 64学时 3.5学分 章节安排 电子商务网站概况 HTML5+CSS3 JavaScript Node 电子...
    阿啊阿吖丁阅读 9,197评论 0 3
  • AJAX 原生js操作ajax 1.创建XMLHttpRequest对象 var xhr = new XMLHtt...
    碧玉含香阅读 3,201评论 0 7
  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,101评论 1 32
  •   2005 年,Jesse James Garrett 发表了一篇在线文章,题为“Ajax: A new App...
    霜天晓阅读 890评论 0 1
  • 一、简历准备 1、个人技能 (1)自定义控件、UI设计、常用动画特效 自定义控件 ①为什么要自定义控件? Andr...
    lucas777阅读 5,202评论 2 54