Ajax第二天笔记总结

Ajax第二天

今日目标
  • 能够说出form表单的常用属性
  • 能够知道如何阻止表单的默认提交行为
  • 能够知道如何使用jQuery快速获取表单数据
  • 能够知道如何安装和使用模板引擎
  • 能够知道模板引擎的实现原理

一、Form表单的基本使用
1、什么是表单

表单在网页中主要负责 数据采集功能 。HTML中<form>标签,就是用于采集用户输入的信息,并通过 <form> 标签的提交操作,把采集的信息提交到服务器端进行处理

在这里插入图片描述

2、表单的组成部分

在这里插入图片描述

表单由三个基本部分组成:

  • 表单标签
  • 表单域:包含了文本框,密码框,隐藏域,都行文本框,复选框,单选框,下拉选择框和文件上传框等等
  • 表单按钮:通过设置type属性为submit来触发form表单的提交
3、<form> 标签的属性

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

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

    action 属性用来规定当提交表单时,向何处发送表单数据

    action 属性的值应该是后端提供的一个URL地址,这个URL地址专门负责接收表单提交过来的数据。

    <form>表单在未指定 action 属性值的情况下,action的默认值为当前页面的 URL 地址

    注意: 当提交表单后,会立即跳转到 action 属性指定的 URL 地址

  • target

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

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

    _blank提交时在新的窗口打开
    _slef默认值,在本窗口打开
    _parent在父框架集中打开(很少用)
    _top在整个窗口中打开(很少用)
    framename在指定的框架中打开(很少用)
  • method

    method 属性用来规定 以何种方式 把表单数据提交到 action URL

    它的可选值有两个,分别是 getpost

    默认情况下,method的值为 get, 表示通过URL地址的形式,把表单数据提交到 action URL

    注意:

    • get 方式适合用来提交少量的简单的数据
    • post 方式适合用来提交大量的复杂的,或包含文件上传的数据
  • enctype

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

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

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

    注意:

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

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

4、表单的同步提交及缺点
  • 什么是表单的同步提交

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

  • 表单同步提交的缺点

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

    表单只负责采集数据,Ajax负责将数据提交到服务器

二、通过Ajax提交表单数据
1、监听表单提交事件

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

代码:

// 第一种方式
$('#f1').submit(function () {
  alert('监听到了表单的提交事件')
})

// 第二种方式
$('#f1').on('submit', function () {  
  alert('监听到了表单的提交事件2')
})
2、阻止表单默认提交行为

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

代码:

// 第一种方式
$('#f1').submit(function (e) {
  alert('监听到了表单的提交事件')
  e.preventDefault()
})

// 第二种方式
$('#f1').on('submit', function (e) {  
  alert('监听到了表单的提交事件2')
  e.preventDefault()
})
3、如何快速获取表单数据

为了简化表单中数据的获取操作,jQuery提供了 serialize() 函数

语法:

$(selector).serialize()

好处:可以一次性获取表单的数据

代码:

// html 结构
<form action="/login" id="f1">
  <input type="text" name="user_name" />
    <input type="password" name="password" />
      <button type="submit">提交</button>
</form>

// js
$(function () {
  $("#f1").submit(function (e) {
    e.preventDefault();
    let data = $(this).serialize();
    console.log(data);
  });
});

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

三、案例 - 评论列表
  • 效果图

    在这里插入图片描述

  • UI 结构搭建

    步骤

    • 评论面板结构
      • 创建panel (快捷键:bs3-panel:primary
      • 修改title里面的标题
      • 在body 里面 创建两个输入框,加上对应的文本提示
      • 最下面加上一个 button(快捷键:bs3-button:primary
    • 评论列表结构
      • 构建一个list列表(快捷键:bs3-list-group
      • 在第一个li里面放两个 span,写入 评论时间评论人

    代码:

    <!-- 评论面板 -->
    <div class="panel panel-primary">
      <div class="panel-heading">
        <h3 class="panel-title">发表评论</h3>
    	</div>
      <form class="panel-body" id="formAddCmt">
        <div>评论人:</div>
      <input type="text" class="form-control" name="username" />
        <div>评论内容:</div>
      <textarea class="form-control" name="content"></textarea>
    
      <button type="submit" class="btn btn-primary">发表评论</button>
      </form>
    </div>
    <!-- 评论列表 -->
    
    <ul class="list-group">
      <li class="list-group-item">
        <span class="badge" style="background: orange">评论时间:</span>
    		<span class="badge" style="background: skyblue">评论人:</span>
    		Item 1
    	</li>
    </ul>
    
  • 获取评论列表数据

    步骤:

    • 定义函数来获取评论列表数据 getCommentList()
    • 查阅接口文档,关注请求url,是否需要携带参数,请求方式
    • 利用 $.ajax() 来进行请求
    • success 回调函数中,判断请求数据是否成功,如果状态码不是200,提示用户

    代码:

    let baseUrl = `http://www.liulongbin.top:3006`;
    // 获取评论列表
    function getCommentList() {
      $.ajax({
        method: "GET",
        url: baseUrl + "/api/cmtlist",
        data: {},
        success: function (res) {
          if (res.status !== 200) {
            return alert("获取数据失败!");
          }
          console.log(res.data);
      });
    }
    
  • 渲染评论列表

    步骤:

    • 创建一个空数组(rows),用来存放每一个元素的html字符串结构
    • 遍历服务器返回的数据,每遍历一次,拼接一个对应的html字符串结构,然后放入到数组中
    • 找到list容器,先清空一下里面内容,然后利用 append 添加新的数据

    代码:

    // 获取评论列表
    function getCommentList() {
      $.ajax({
        method: "GET",
        url: baseUrl + "/api/cmtlist",
        data: {},
        success: function (res) {
          if (res.status !== 200) {
            return alert("获取数据失败!");
          }
          console.log(res.data);
          let arr = res.data.slice(0, 5);
          let rows = [];
          $.each(arr, function (i, item) {
            rows.push(
              `<li class="list-group-item">
                  <span class="badge" style="background: orange;">评论时间:${item.time}</span>
                  <span class="badge" style="background: skyblue;">评论人:${item.username}</span>
                  ${item.content}
                </li>`
            );
          });
          $(".list-group").empty().append(rows.join(""));
        },
      });
    }
    
  • 发表评论

    • 改造form表单

      步骤:

      • 把之前panel-body的标签改成 form 标签
      • 给每一个输入框设置 name 属性,name属性的值最好与接口文档定义的参数名称一致
      • 注册 sumbit 事件,阻止表单提交的默认行为
      • 获取用户输入内容(利用 serialize()

      代码:

      // 发布评论
      $("#formAddCmt").on("submit", function (e) {
        e.preventDefault();
        let data = $(this).serialize();
      });
      
    • 完成发表功能

      步骤:

      • 查阅接口文档
      • 利用 $.post() 发送请求,传入数据
      • 在成功回调函数里面判断 返回的 status 是否是201,如果是代表成功,失败进行提示
      • 刷新页面(调用 getCommentList()),清空表单内容($('#formAddCmt')[0].reset()

      代码:

      // 发布评论
      $("#formAddCmt").on("submit", function (e) {
        e.preventDefault();
        let data = $(this).serialize();
        $.ajax({
          method: "POST",
          url: baseUrl + "/api/addcmt",
          data,
          success: (res) => {
            if (res.status !== 201) {
              return alert("评论发布失败!");
            }
            getCommentList();
            console.log($(this));
            $(this)[0].reset();
          },
        });
      });
      
四、模板引擎的基本概念
1、渲染 UI 结构时遇到的问题

以前都是通过 拼接字符串 或是 模版字符串 的形式来渲染 UI 结构,这样操作是比较麻烦的,而且很容易出现问题

如果 UI 结构比较复杂,则拼接字符串的时候需要格外注意 引号之前的嵌套 。且一旦需求发生变化,修改起来也非常麻烦

2、什么是模板引擎

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

在这里插入图片描述

3、使用模板引擎的好处
  • 减少了字符串的拼接操作
  • 使代码结构更清晰
  • 使代码更易于阅读与维护
五、art-template模板引擎
1、art-template 简介

art-template 是一个简约,超快的模板引擎,中文官首页:http://aui.github.io/art-template/zh-cn/index.html

在这里插入图片描述

2、安装 art-template
  • 浏览器访问 http://aui.github.io/art-template/zh-cn/docs/installation.html
  • 找到 安装 导航栏,找到下载链接,右键下载即可

在这里插入图片描述

3、art-template 模板引擎基本使用
  • 导入 art-template

    • 在window全局,就多了一个函数,叫做 template(‘模板id’,需要渲染的数据对象)
    <script src="./lib/template-web.js"></script>
    
  • 定义数据

    const data = { name: 'zs', age: 20}
    
  • 定义模板

    • 模板的 HTML 结构,必须定义到 script 标签中,注意:需要把type属性改成 text/html
    • 给 模板 添加一个 id
    • 模板里面如果需要使用到传入的数据,利用 {{}} 来实现,例如:{{name}},那么就会去找 我们调用 template() 函数 第二个参数里面对应的name属性的值
    <script type="text/html" id="tpl-user">
        <h1>{{name}}    ------    {{age}}</h1>
    </script>
    
  • 调用 template 函数

    • 函数的返回值就是拼接好的模板字符串
    const htmlStr = template('tpl-user', data)
    
  • 渲染HTML结构

    • 最后我们需要把template返回的模板字符串设置到页面容器中
    $('#container').html(htmlStr)
    

4、art-template 标准语法

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 flag == 0 }}
    	当 flag 等于 0 时进行输出
    {{ else if flag == 1 }}
    	当 flag 等于 1 时进行输出
    {{ /if }}
    
  • 循环输出

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

    语法:

    {{ each arr }}
    	{{ $index }} {{ $value }}
    {{ /each }}
    
  • 过滤器

    在这里插入图片描述

    过滤器本质就是一个 function 函数

    语法:

    {{ value | filterName }}
    

    过滤器语法类似于 管道操作符,它的上一个输出作为下一个输入

    定义过滤器的基本语法如下:

    template.defaults.imports.filterName = function(value){ return 处理结果 }
    
  • 案例 - 格式化时间过滤器

    • 定义数据

      const data = { regTime: new Date() }
      
    • 定义过滤器函数

      template.defaults.imports.dateFormat = (date) => {
        const y = date.getFullYear();
        const m = date.getMonth() + 1;
        const d = date.getDate();
        return y + "-" + m + "-" + d;
      };
      
    • 在模板引擎中使用过滤器

      <div>注册时间为:{{ regTime | dateFormat }}</div>
      
六、案例 - 新闻列表
  • 效果

    在这里插入图片描述

  • 获取新闻列表数据

    • 定义函数,获取新闻列表数据 getNewsList()
    • 查阅接口文档,关注 请求url,请求方式,请求参数,响应数据
    • 利用 $.ajax() 发起请求
    • 在回调函数中,判断请求是否成功

    代码:

    // 获取新闻列表
    function getNewsList() {
      $.ajax({
        method: "GET",
        url: "http://www.liulongbin.top:3006/api/news",
        data: {},
        success: function (res) {
          if (res.status !== 200) {
            return alert("获取数据失败!");
          }
         console.log(res);
        },
      });
    }
    
  • 定义新闻列表 item 模板

    • 创建 script 标签,更改type属性值为 text/html,给模板定义id
    • 找到静态页面中 item 的结构,拷贝到模板里面

    代码:

     <script type="text/html" id="tpl-info">
          <div class="news-item">
            <img class="thumb" src="" alt="" />
            <div class="right-box">
              <h1 class="title">5G商用在即,三大运营商营收持续下降</h1>
              <div class="tags">
                <span>三大运营商</span>
                <span>中国移动</span>
                <span>5G商用</span>
              </div>
              <div class="footer">
                <div>
                  <span>胡润百富</span>&nbsp;&nbsp;
                  <span>2019-10-28 10:14:38</span>
                </div>
                <span>评论数:66</span>
              </div>
            </div>
          </div>
     </script>
    
  • 编译模板渲染结构

    • 在请求成功的回调里面,先对返回数据进行改造,里面返回的 tags 是一个字符串,我们需要分割成数组
    • 调用 template() 方法,传入id和返回的数据
    • 把函数的返回值添加到页面容器中
    • 在模板中利用 each 遍历列表
    • 利用 $value 能够拿到每一个item
    • 设置图片 img,**注意:**需要拼接请求根路径
    • 设置标题 title
    • 设置标签,注意:标签在之前改造成数组了,这里又需要进行遍历
    • 设置来源 source
    • 设置时间,注意:时间需要格式化,利用过滤器来实现
    • 设置评论数 cmtcount

    代码:

    <script type="text/html" id="tpl-info">
          {{ each data }}
          <div class="news-item">
            <img class="thumb" src="http://www.liulongbin.top:3006{{ $value.img }}" alt="" />
            <div class="right-box">
              <h1 class="title">{{$value.title}}</h1>
              <div class="tags">
                {{ each $value.tags }}
                  <span>{{ $value }}</span>
                {{ /each }}
              </div>
              <div class="footer">
                <div>
                  <span>{{$value.source}}</span>&nbsp;&nbsp;
                  <span>{{$value.time | dateFormat}}</span>
                </div>
                <span>评论数:{{$value.cmtcount}}</span>
              </div>
            </div>
          </div>
          {{ /each }}
      </script>
    
  • 定义格式化时间过滤器

    • 调用 template.defaults.imports 添加 dateFormat() 函数

    代码:

    // 定义格式化时间过滤器
    template.defaults.imports.dateFormat = (dateStr) => {
      const date = new Date(dateStr);
      const y = padZero(date.getFullYear());
      const m = padZero(date.getMonth() + 1);
      const d = padZero(date.getDate());
    
      const hh = padZero(date.getHours());
      const mm = padZero(date.getMinutes());
      const ss = padZero(date.getSeconds());
      return y + "-" + m + "-" + d + " " + hh + ":" + mm + ":" + ss;
    };
    
    // 定义补 0 函数
    function padZero(n) {
      if (n >= 10) return n;
      return "0" + n;
    }
    
七、模板引擎的实现原理
1、正则与字符串操作
  • exec 函数

    exec() 函数用于 检索字符串 中的正在表达式的匹配

    如果字符串中又匹配的值,则返回该匹配值,否则返回 null

    语法:

    RegExpObject.exec(string)
    

    代码:

    let str = "Hello";
    let pattern = /x/;
    let result = pattern.exec(s);
    console.log(result);
    
  • 分组

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

    var str = '<div>我是{{name}}</div>'
    var pattern = /{{([a-zA-Z]+)}}/
    var result = pattern.exec(str)
    console.log(result)
    
  • 字符串的 replace 函数

    replace() 函数用于在字符串中 用一些字符 替换 另一些字符的

    语法:

    var result = "123456".replace('123', 'abc') 
    console.log(result); // abnc456
    

    代码:

    let str = "<div>我是{{name}}</div>";
    const pattern = /{{([a-zA-Z]+)}}/;
    const patternResult = pattern.exec(str);
    const result = str.replace(patternResult[0], patternResult[1]);
    console.log(result); // <div>我是name</div>
    
  • 多次 replace

    代码:

    let str = "<div>我是{{ name }},今年{{ age }}岁。</div>";
    const pattern = /{{\s*([a-zA-Z]+)\s*}}/;
    
    // 第一次匹配
    const res1 = pattern.exec(str);
    str = str.replace(res1[0], res1[1]);
    
    // 第二次匹配
    const res2 = pattern.exec(str);
    str = str.replace(res2[0], res2[1]);
    console.log(str); // <div>我是name,今年age岁。</div>
    
    // 第三次匹配
    const res3 = pattern.exec(str);
    console.log(res3); // null
    
  • 使用循环来 replace

    代码:

    var str = "<div>我是{{ name }},今年{{ age }}岁。</div>";
    var pattern = /{{\s*([a-zA-Z]+)\s*}}/;
    let patternResult = null;
    while ((patternResult = pattern.exec(str))) {
      str = str.replace(patternResult[0], patternResult[1]);
    }
    console.log(str); // <div>我是name,今年age岁。</div>
    
  • 替换成真实内容

    代码:

    const data = { name: "章三", age: 20 };
    let str = "<div>我是{{name}},今年{{ age }}岁了。</div>";
    const pattern = /{{\s*([a-zA-Z]+)\s*}}/;
    let patternResult = null;
    while ((patternResult = pattern.exec(str))) {
      str = str.replace(patternResult[0], data[patternResult[1]]);
    }
    console.log(str); // <div>我是章三,今年20岁了。</div>
    
2、实现简易的模板引擎
  • 定义模板结构

    代码:

    <script type="text/html" id="tpl-user">
    		<div>姓名:{{name}}</div>
        <div>年龄:{{ age }}</div>
        <div>性别:{{ gender}}</div>
        <div>住址:{{address }}</div>
    </script>
    
  • 预调用模板引擎

    代码:

    <script>
      // 定义数据
      var data = { name: "章三", age: 28, gender: "男", address: "杭州江干4号大街" };
      // 调用模板引擎
      var htmlStr = template("tpl-user", data);
      // 渲染HTML结构
      document.getElementById("user-box").innerHTML = htmlStr;
    </script>
    
  • 封装 template 函数

    代码:

    function template(id, data) {
      var str = document.getElementById(id).innerHTML;
      var pattern = /{{\s*([a-zA-Z]+)\s*}}/;
    
      var pattResult = null;
      while ((pattResult = pattern.exec(str))) {
        str = str.replace(pattResult[0], data[pattResult[1]]);
      }
    
      return str;
    }
    
  • 导入并使用自定义的模板引擎

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

itpeilibo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值