初识Ajax

318 阅读3分钟

URL地址的概念

URL(全称是UniformResourceLocator)中文叫统一资源定位符,用于标识互联网上每个资源的唯一存放位置。浏览器只有通过URL地址,才能正确定位资源的存放位置,从而成功访问到对应的资源。

URL地址的组成部分

URL地址一般由三部组成:

  • 客户端与服务器之间的通信协议
  • 存有该资源的服务器名称
  • 资源在服务器上具体的存放位置

image.png

客户端与服务器的通信过程

image.png 注意:

  • 客户端与服务器之间的通信过程,分为 请求处理响应 三个步骤。
  • 网页中的每一个资源,都是通过 请求 – 处理 – 响应 的方式从服务器获取回来的。

如果要在网页中请求服务器上的数据资源,则需要用到 XMLHttpRequest 对象。

XMLHttpRequest(简称 xhr)是浏览器提供的 js 成员,通过它,可以请求服务器上的数据资源。 最简单的用法 var xhrObj = new XMLHttpRequest()

客户端请求服务器时,请求的方式有很多种,最常见的两种请求方式分别为 getpost 请求。

image.png

什么是Ajax

Ajax 的全称是 Asynchronous Javascript And XML(异步 JavaScript 和 XML)。

通俗的理解:在网页中利用 XMLHttpRequest 对象和服务器进行数据交互的方式,就是Ajax。

jQuery中的Ajax

浏览器中提供的 XMLHttpRequest 用法比较复杂,所以 jQuery 对 XMLHttpRequest 进行了封装,提供了一系列 Ajax 相关的函数,极大地降低了 Ajax 的使用难度。

jQuery 中发起 Ajax 请求最常用的三个方法如下:

  • $.get()
  • $.post()
  • $.ajax()

$.get()函数

jQuery 中 $.get() 函数的功能单一,专门用来发起 get 请求,从而将服务器上的资源请求到客户端来进行使用。

$.get(url, [data], [callback])

image.png

使用 $.get() 函数发起不带参数的请求时,直接提供请求的 URL 地址和请求成功之后的回调函数即可,示例代码如下:

$.get('http://www.liulongbin.top:3006/api/getbooks'function(res) {
    console.log(res) // 这里的 res 是服务器返回的数据
})

$.get()发起带参数的请求

$.get('http://www.liulongbin.top:3006/api/getbooks', { id: 1 }, function(res) {
    console.log(res)
})

$.post() 函数

jQuery 中 .post()函数的功能单一,专门用来发起post请求,从而向服务器提交数据。参数和.post() 函数的功能单一,专门用来发起 post 请求,从而向服务器提交数据。 参数和.get()一样。

image.png $.post()向服务器提交数据

$.post(
   'http://www.liulongbin.top:3006/api/addbook', // 请求的URL地址
   { bookname: '水浒传', author: '施耐庵', publisher: '上海图书出版社' }, // 提交的数据
   function(res) { // 回调函数
      console.log(res)
   }
)

$.ajax()函数的语法

相比于 .get().get() 和 .post() 函数,jQuery 中提供的 $.ajax() 函数,是一个功能比较综合的函数,它允许我们对 Ajax 请求进行更详细的配置。

$.ajax() 函数的基本语法如下:

$.ajax({
   type: '', // 请求的方式,例如 GET 或 POST
   url: '',  // 请求的 URL 地址
   data: { },// 这次请求要携带的数据
   success: function(res) { } // 请求成功之后的回调函数
})

练习:

// 使用ajax函数里面的get方式发送请求
$('.btnAjaxGet').on('click', function() {
    $.ajax({
        type: 'GET',
        url: 'http://www.liulongbin.top:3006/api/getbooks',
        data: {
            id: 1
        },
        success: function(res) {
            console.log(res);
        }
    });
});

// 使用ajax函数里面的post方式发送请求
$('.btnAjaxPost').on('click', function() {
    $.ajax({
        type: 'POST',
        url: 'http://www.liulongbin.top:3006/api/addbook',
        data: {
            bookname: '加油',
            author: '牛逼如我',
            publisher: '上海图书出版社'
        },
        success: function(res) {
            console.log(res);
        }
    });
});

form表单

<form>标签用来采集数据,<form>标签的属性则是用来规定如何把采集到的数据发送到服务器。

属性描述
actionURL地址规定当提交表单时,向何处发送表单数据
methodget或post规定以何种方式把表单数据提交到 action URL
enctypeapplication/x-www-form-urlencoded
multipart/form-data
text/plain
规定在发送表单数据之前如何对其进行编码
target_blank
_self
_parent
_top
framename
规定在何处打开 action URL

action

image.png

target

target 属性用来规定在何处打开 action URL。

它的可选值有5个,默认情况下,target 的值是 _self,表示在相同的框架中打开 action URL。

描述
_blank在新窗口中打开。
_self默认。在相同的框架中打开。
_parent在父框架集中打开。(很少用)
_top在整个窗口中打开。(很少用)
framename在指定的框架中打开。(很少用)

method

image.png

enctype

enctype 属性用来规定在发送表单数据之前如何对数据进行编码。

它的可选值有三个,默认情况下,enctype 的值为 application/x-www-form-urlencoded,表示在发送前编码所有的字符。

描述
application/x-www-form-urlencoded在发送前编码所有字符(默认)
multipart/form-data不对字符编码。在使用包含文件上传控件的表单时,必须使用该值。
text/plain空格转换为 “+” 加号,但不对特殊字符编码。(很少用)

注意:

在涉及到文件上传的操作时,必须将 enctype 的值设置为 multipart/form-data

如果表单的提交不涉及到文件上传操作,则直接将 enctype 的值设置为 application/x-www-form-urlencoded 即可!

表单的同步提交及缺点

通过点击 submit 按钮,触发表单提交的操作,从而使页面跳转到 action URL 的行为,叫做表单的同步提交

  1. <form>表单同步提交后,整个页面会发生跳转,跳转到 action URL 所指向的地址,用户体验很差。
  2. <form>表单同步提交后,页面之前的状态和数据会丢失。

如果使用表单提交数据,则会导致以下两个问题:

  • 页面会发生跳转
  • 页面之前的状态和数据会丢失

解决方案:表单只负责采集数据,Ajax 负责将数据提交到服务器。


通过Ajax提交表单数据

在jq中,可以使用如下两种方式,监听到表单的提交事件:

当监听到表单的提交事件以后,可以调用事件对象的 event.preventDefault() 函数,来阻止表单的提交和页面的跳转,示例代码如下:

$('#form1').submit(function(e) {
   // 阻止表单的提交和页面的跳转
   e.preventDefault()
})

$('#form1').on('submit', function(e) {
   // 阻止表单的提交和页面的跳转
   e.preventDefault()
})

快速获取表单中的数据 serialize()

为了简化表单中数据的获取操作,jQuery 提供了 serialize() 函数,其语法格式如下:

$('#form1').serialize()

serialize() 函数的好处:可以一次性获取到表单中的所有的数据。

<form id="form1">
    <input type="text" name="username" />
    <input type="password" name="password" />
    <button type="submit">提交</button>
</form>
<script>
$('#form1').serialize()
// 调用的结果:
// username=用户名的值&password=密码的值
</script>

注意:在使用 serialize() 函数快速获取表单数据时,必须为每个表单元素添加 name 属性

模板引擎

模板引擎,顾名思义,它可以根据程序员指定的模板结构和数据,自动生成一个完整的HTML页面。

image.png

  • 减少了字符串的拼接操作
  • 使代码结构更清晰
  • 使代码更易于阅读与维护

art-template模板引擎

art-template 是一个简约、超快的模板引擎。中文官网首页为 aui.github.io/art-templat…

art-template的使用步骤

  1. 导入 art-template
  2. 定义数据
  3. 定义模板
  4. 调用 template 函数
  5. 渲染HTML结构

art-template 提供了 {{ }} 这种语法格式,在 {{ }} 内可以进行变量输出,或循环数组等操作,这种 {{ }} 语法在 art-template 中被称为标准语法。

标准语法 - 输出

{{value}}
{{obj.key}}
{{obj['key']}}
{{a ? b : c}}
{{a || b}}
{{a + b}}

在 {{ }} 语法中,可以进行变量的输出、对象属性的输出、三元表达式输出、逻辑或输出、加减乘除等表达式输出。

标准语法 – 原文输出

{{@ value }}

如果要输出的 value 值中,包含了 HTML 标签结构,则需要使用原文输出语法,才能保证 HTML 标签被正常渲染。

标准语法 – 条件输出

如果要实现条件输出,则可以在 {{ }} 中使用 if … else if … /if 的方式,进行按需输出。

{{if value}} 按需输出的内容 {{/if}}

{{if v1}} 按需输出的内容 {{else if v2}} 按需输出的内容 {{/if}}

标准语法 – 循环输出

如果要实现循环输出,则可以在 {{ }} 内,通过 each 语法循环数组,当前循环的索引使用 index进行访问,当前的循环项使用index 进行访问,当前的循环项使用 value 进行访问。

{{each arr}}
    {{$index}} {{$value}}
{{/each}}

标准语法 – 过滤器

image.png

过滤器的本质,就是一个 function 处理函数。

{{value | filterName}}

过滤器语法类似管道操作符,它的上一个输出作为下一个输入。 定义过滤器的基本语法如下:

template.defaults.imports.filterName = function(value){/*return处理的结果*/}

练习:

  <!-- // 1.导入 art-template -->
  <!-- 在 window 全局,多一个函数,叫做 template('模板的Id', 需要渲染的数据对象) -->
  <script src="./template-web.js"></script>
  <script src="./jquery.min.js"></script>
</head>

<body>
  <div class="container"></div>

  <!-- 3.定义模板 -->
  <!-- 3.1 模板的 HTML 结构,必须定义到 script 中 -->
  <script type="text/html" id="info">
    <h3>姓名:{{name}}</h3>
    <h4>年龄:{{age}}</h4>
    {{html_text}}

    <br>
    <!-- 原文输出语法 -->
    {{@ html_text}}

    <br>
    <!-- {{if v1}} 按需输出的内容 {{else if v2}} 按需输出的内容 {{/if}} -->
    {{if flag === true}} 我是真的 {{else if flag === false}}我是假的 {{/if}}

    <br>
    <!-- 通过 each 语法循环数组,当前循环的索引使用 $index 进行访问,当前的循环项使用 $value 进行访问。 -->
    {{each hobby}}
    <p> 索引号是:{{$index}}, 内容是:{{$value}} </p> {{/each}}

    <!-- 过滤器 template.defaults.imports -->
    <p>现在时间:{{regTime | dateFormat}}</p>
  </script>

  <script>
    // 2.定义数据
    var data = {
      name: 'hyq',
      age: 30,
      html_text: '<a href="#">百度</a>',
      flag: false,
      hobby: ['打游戏', '学习', '听音乐'],
      regTime: new Date()
    };

    //  过滤器
    template.defaults.imports.dateFormat = function(date) {
      var y = date.getFullYear();
      var m = date.getMonth() + 1;
      var d = date.getDate();

      return y + '-' + m + '-' + d;
    }

    // 4.调用 template 函数
    var htmlstr = template('info', data);
    console.log(htmlstr); // <h3>姓名:hyq</h3> <h4>年龄:30</h4>

    // 5.渲染HTML结构
    $('.container').html(htmlstr);
  </script>

实现简易的模板引擎

基于正则来匹配 {{}}里面的内容,并用replace()函数替换为data里面的数据。

exec() 函数用于检索字符串中的正则表达式的匹配。 如果字符串中有匹配的值,则返回该匹配值,否则返回 null。

正则表达式中 ( ) 包起来的内容表示一个分组,可以通过分组来提取自己想要的内容,示例代码如下:

var str = '<div>{{name}}今年{{ age }}岁了</div>'
var pattern = /{{\s*([a-zA-Z]+)\s*}}/

var patternResult = pattern.exec(str)
str = str.replace(patternResult[0], patternResult[1])
console.log(str) // 输出 <div>name今年{{ age }}岁了</div>

patternResult = pattern.exec(str)
str = str.replace(patternResult[0], patternResult[1])
console.log(str) // 输出 <div>name今年age岁了</div>

patternResult = pattern.exec(str)
console.log(patternResult) // 输出 null

实现:

  <div id="infoBox"></div>

  <script type="text/html" id="tpl-info">
    <h3>姓名:{{name}}</h3>
    <h3>年龄:{{ age }}</h3>
    <h3>性别:{{sex }}</h3>
    <h3>地址:{{ address}}</h3>
  </script>

  <script>
    var data = {
      name: 'hyq',
      age: 20,
      sex: '男',
      address: '江西南昌'
    }

    var htmlStr = template('tpl-info', data);
    document.querySelector('#infoBox').innerHTML = htmlStr;

    function template(id, data) {
      var str = document.getElementById(id).innerHTML;
      var pattern = /{{\s*([a-zA-Z]+)\s*}}/;

      var patternResult = null;
      while (patternResult = pattern.exec(str)) {
        str = str.replace(patternResult[0], data[patternResult[1]]);
        console.log(str);
      }
      return str;
    }
  </script>