Ajax:表单 & 模板引擎

打印 上一主题 下一主题

主题 1830|帖子 1830|积分 5490


form 表单

在HTML中,可以通过<form>创建一个表单,收集用户信息。而收罗到的信息想要发送给后端,此时就要与Ajax进行配合。
form 属性

在原生HMTL表单中,包含四个根本属性:
属性功能值action向何处提交表单内的数据urlmethod提交表单的方式get、postenctype如何对表单数据编码target打开action url的为止_blank、_self

  • action
action的属性值通常是后端提供的一个url地址,这个地址接收并处理来自前端的数据。如果<form>没有指定该值,那么默认为当前页面的url。
示例:
  1. <form action="/login">
  2.   <input type="account" name="account" />
  3.   <input type="password" name="password" />
  4.   <button type="submit">提交</button>
  5. </form>
复制代码
这是一个表单,指定action="/login"。
输出效果:

可以看到,点击提交后,地址变成了/login?account=123456&password=54321,此中/login就是表单提交到的地址,而?后面是表单的参数。
这里有两个细节:

  • 目的地址默认是在当前页面打开
  • 表单的参数追加到了地址的末尾,说明默认是get请求


  • taget
taget指定在何处打开地址,刚刚打开地址是,是默认在当前页面打开,通过指定target就可以改变打开目的地址的方式。

  • _blank:在新窗口打开
  • _self:在当前窗口打开,默认值


  • method
刚刚发现,表单的提交方式默认为get,如果想要切换表单提交方式,可以通过method属性。

  • get:以get情势发送请求,默认值
  • post:以post情势发送请求
示例:
  1. <body>
  2.   <form action="/login" method="post" >
  3.     <input type="account" name="account" />
  4.     <input type="password" name="password" />
  5.     <button type="submit">提交</button>
  6.   </form>
  7. </body>
复制代码
此处把表单的提交方式改为post。
提交表单后,检察控制台:

这次提交数据后,地址就是/login,表单的数据不再以?的情势追加到地址末尾。而在Payload窗口,可以看到表单数据account和password已经放在了请求的内部。


  • enctype
enctype用于指定表单数据的编码方式,其有三个可选值:

  • application/x-www-form-urlencoded:在发送数据前编码所以的字符,默认值
  • multipart/form-data:不对字符编码,如果表单内上传文件时,必须使用该选项,防止错误编码
  • text/plain:空格转换为'+'字符,但是不对特别字符编码,几乎不用
原生的HTML表单有许多缺点:

  • 表单提交后,会发生页面跳转
  • 表单提交后,会清空表单原有数据
想要处理这些标题,那就要引入JavaScript和Ajax,JavaScript可以阻止默认行为,禁止页面进行跳转。但是如许也会阻止数据的提交,因此使用Ajax来进行表单数据提交,不再让表单自己提交数据。而且Ajax提交数据,不会清空表单的内容。

Ajax操控表单

事件监听

如果要在用户提交表单时,让Ajax立即响应,代替表单的提交使命,此时就要对表单进行提交事件的事件监听。
只需要调用原先的jQuery接口即可:
  1. $('form').submit(function(){})
  2. $('form').on('submit', function(){})
复制代码
以上两种方式,都可以实现对表单的提交事件的监听。

阻止默认行为

想要阻止默认提交行为,也很简单:
  1. $('form').on('submit', function (e) {  
  2.   e.preventDefault()
  3. })
复制代码
在回调函数中,添加是事件参数e,随后调用preventDefault方法阻止默认行为,这可以同时阻止提交行为和页面跳转。

收集表单数据

现在已经阻止了提交行为,接下来就要通过Ajax代替原先的提交行为了。在提交数据之前,就要先获取到表单的数据,这里jQuery封装了接口,可以一次性获取全部表单内容。
语法:
  1. $('form').serialize()
复制代码
注意:使用这个方法时,要确保表单的每个栏目都有name属性,否则无法获取到对应的栏目。
示例:
  1. <form action="/login" id="f1">
  2.   <input type="account" name="account" />
  3.   <input type="password" name="password" />
  4.   <button type="submit">提交</button>
  5. </form>
  6. <script>
  7.   $(function () {
  8.     $('#f1').on('submit', function (e) {
  9.       e.preventDefault()
  10.       var data = $(this).serialize()
  11.       console.log(data)
  12.     })
  13.   })
  14. </script>
复制代码
输出效果:

此时data就已经拿到了表单的内容,最后就可以通过Ajax进行发送了。

模板引擎

当从表单中拿到了大量的数据,此时可能就需要把这些数据重新渲染到页面上,如果对于原生的JavaScript或者jQuery,处理这个都是比力麻烦的,需要进行字符串拼接等操纵,把数据拼接到标签的内部。
假设现在要渲染以下内容:
  1. var data = {
  2.   title: '<h3>用户信息</h3>',
  3.   name: '张三',
  4.   age: 18,
  5.   isVIP: true,
  6.   regTime: new Date(),
  7.   hobby: ['HTML', 'HTTP', 'Linux']
  8. }
复制代码
渲染为如下结构:

如果只使用html和jQuery,那么就要从对象提取信息,然后一个一个通过.html方法把信息添加到页面中,对于最后一个hobby数组,还需要通过.each方法进行遍历,追加到页面中。
art-template

这很麻烦,模板引擎可以办理这个标题,以模板的情势,快速渲染大量的信息到网页。此处选用art-template模板引擎,可以到以下网址下载:
  1. http://aui.github.io/art-template/zh-cn/docs/installation.html
复制代码
只需要把template-web.js(gzip: 6kb)这个文件下载下来,并通过JavaScript的情势引入即可使用。
  1. <script src="./template-web.js"></script>
复制代码
导入art-template后,全局就会多出一个template方法,这就是模板引擎的核心方法。
示例:
首先,模板引擎的内容要界说在<script>标签内部:
  1. <script type="text/html" id="tpl">
  2.   <p>姓名: {{name}}</p>
  3.   <p>年龄: {{age}}</p>
  4. </script>
复制代码
此处要制定type属性和id属性,默认情况下type="text/JavaScript",表现以JavaScript情势解析<script>内部的内容,此处改为text/html,表现以html情势解析内容。
随后就可以在内部编写html的代码了,在编写代码时,可以使用{变量名}}的情势来引入外部变量,这个变量会直接取对象中的值进行填入。
模板语法:
  1. template('id', 对象)
复制代码
此处的id是刚才<script>内部的属性id="tpl",而对象是要添补的对象,最后会返回格式化后的html字符串。
示例:
  1. <script>
  2.   var data = { name: '张三', age: 20}
  3.   var htmlStr = template('tpl-user', data)
  4.   $('#container').html(htmlStr)
  5. </script>
复制代码
在对象data中,包含name和age两个属性,这刚好和之前指定的{{name}}和{{age}}相匹配。随后调用template('tpl, data),表现用data这个对象值,去添补模板tpl的内容,此时就会返回一个html格式的字符串,直接把字符串填入目的容器即可。
  1. <div id="container"></div><script type="text/html" id="tpl-user">  <p>姓名: {{name}}</p>  <p>年龄: {{age}}</p></script><script>
  2.   var data = { name: '张三', age: 20}
  3.   var htmlStr = template('tpl-user', data)
  4.   $('#container').html(htmlStr)
  5. </script>
复制代码
输出效果:

如许就实现了快速渲染对象的内容到html中。

{{}}语法

刚才已经见过{{}}的根本功能了,其实就是把对象中命名相匹配的内容,直接添补到html中,其实它还支持许多种语法格式:
  1. {{value}}
  2. {{obj.key}}    // 获取对象值
  3. {{obj['key']}} // 获取对象值
  4. {{a ? b : c}}  // 三元表达式
  5. {{a || b}}     // 逻辑判断
  6. {{a + b}}      // 算数运算
复制代码

原文输出

如果输出的内容是一个字符串,并且字符串中包含html标签,如果希望这个标签被渲染,需要使用原文输出:
  1. {{@ value}}
复制代码
在值前面加一个@符号即可。
示例:
  1. <div id="container"></div>
  2. <script type="text/html" id="tpl">
  3.   <p>姓名: {{@ name}}</p>
  4.   <p>年龄: {{age}}</p>
  5. </script>
  6. <script>
  7.   var data = { name: '<li>张三</li>', age: 20}
  8.   var htmlStr = template('tpl', data)
  9.   $('#container').html(htmlStr)
  10. </script>
复制代码
输出效果:

通过{{@ name}},<li>标签就被正常解析了。

条件输出

有时候,可能需要在输出时进行条件判断,比如说如果某个用户是VIP,要额外输出VIP的剩余时间。而如果他不是VIP,这个内容就不用输出。对于这种情况,可以使用条件输出来完成。
语法:
  1. {{if value}} 输出内容 {{/if}}
  2. {{if value}} 输出内容1 {{else}} 输出内容2 {{/if}}
  3. {{if value1}} 输出内容1 {{else if value2}} 输出内容2 {{/if}}
复制代码
示例:
  1. <script type="text/html" id="tpl">
  2.   <p>姓名: {{name}}</p>
  3.   <p>年龄: {{age}}</p>
  4.   {{if isVip}}
  5.     <p> VIP剩余时间: {{time}} </p>
  6.   {{else}}
  7.     <p> 不是VIP </p>
  8.   {{/if}}
  9.   <hr>
  10. </script>
复制代码
在模板中,通过{{if isVip}}来判断该用户是不是VIP,并选择差别的输出效果。
填入以下两个对象:
  1. <script>
  2.   var zs = {
  3.     name: '张三',
  4.     age: 20,
  5.     isVip: true,
  6.     time: 100
  7.   }
  8.   var ls = {
  9.     name: '李四',
  10.     age: 25,
  11.     isVip: false,
  12.     time: null
  13.   }
  14.   var htmlStr1 = template('tpl', zs)
  15.   var htmlStr2 = template('tpl', ls)
  16.   $('#container').html(htmlStr1 + htmlStr2)
  17. </script>
复制代码
示例中,张三是VIP,而李四不是,最后这两者渲染出来的效果就不一样:


循环输出

如果输出的目的是一个数组,可以通过循环输出来遍历全部的数组元素。
语法:
  1. {{each arr}}
  2.         {{$index}} {{$value}}
  3. {{/each}}
复制代码
此中arr是被遍历的数组,而$index是下标,$value是元素值。
示例:
  1. <script type="text/html" id="tpl">
  2.   <p>姓名: {{name}}</p>
  3.   <p>年龄: {{age}}</p>
  4.   <ul>
  5.     {{each hobby}}
  6.       <li> {{$value}} </li>
  7.     {{/each}}
  8.   </ul>
  9. </script>
复制代码
在<ul>内部,通过循环遍历全部的hobby,并通过{{$value}}拿到元素值,渲染到li中。
给张三加上hobby属性:
  1. <script>
  2.   var zs = {
  3.     name: '张三',
  4.     age: 20,
  5.     hobby: ['HTML', 'HTTP', 'Linux']
  6.   }
  7.   var htmlStr = template('tpl', zs)
  8.   $('#container').html(htmlStr)
  9. </script>
复制代码
输出效果:

如许就可以快速遍历全部的数组成员了。

过滤器

如果说,对象中的元素并不是直接填写到页面中的,而是要经过一定的处理之后在填入。比如说商品代价,可能要乘以某个值后,以打折的代价表现在页面中,这就需要引入过滤器。
  1. {{value | filterName }}
复制代码
此中value是要处理的值,这个值会交给filterName 函数处理,函数返回值会最为终极效果填入模板。
过滤器函数并不是直接就可以调用原生的函数,而是要导入到模板中:
  1. template.defaults.imports.filterName = function(value){ 函数体 }
复制代码
现在张三对象内容如下:
  1. var zs = {
  2.   name: '张三',
  3.   age: 20,
  4.   hobby: ['HTML', 'HTTP', 'Linux'],
  5.   startYear: 2023
  6. }
复制代码
此处的startYear表现入学年份,终极渲染到页面中时,希望输出学年: 入学年份 ~ 毕业年份,此时可以交给一个过滤器处理:
  1. template.defaults.imports.graduate = function(value){
  2.    return value + " ~ " + (value + 4)  
  3.   }
复制代码
过滤器graduate 会进行一个字符串拼接,虽然value是数字类型,但是中间的" ~ "是一个字符串,终极整个返回值就是一个字符串,毕业年份是入学年份的四年后。
在模板中,把startYear 输入到过滤器:
  1. <script type="text/html" id="tpl">
  2.   <p>姓名: {{name}}</p>
  3.   <p>年龄: {{age}}</p>
  4.   <ul>
  5.     {{each hobby}}
  6.       <li> {{$value}} </li>
  7.     {{/each}}
  8.   </ul>
  9.   <p>
  10.     学年: {{ startYear | graduate }}
  11.   </p>
  12. </script>
复制代码
此处{{ startYear | graduate }}就是在处理数据。
输出效果:


原理

其实模板引擎的原理非常简单,就是正则表达式匹配,随后替换元素值即可。
以art-template为例,其全部占位符格式都是{{}},那么正则就可以写为:
  1. let pattern = /{{([a-zA-Z]+)}}/
复制代码
首先通过最外层的{{}}进行占位符得到匹配,内层一个()进行分组匹配,提取出具体的信息,[a-zA-Z]+表现提取任意多个字母。
比如对于字符串<div>{{name}}</div>,通过以上正则就可以得到name这个值。
  1. var str = '<div>{{name}}</div>'
  2. var pattern = /{{([a-zA-Z]+)}}/
  3. var result = pattern.exec(str)
  4. console.log(result)
复制代码
输出效果:

可以看到,最后正则返回一个数组,第一个元素是匹配成功的字符串,第二个元素是提取出来的分组值。
当提取到变量名后,就要去对象中拿到对于的变量,并替换原先的占位符,替换通过replace方法完成:
  1. 'string'.replace('子串', '替换值')
复制代码
比如说"helloworld".replace("world", "linux"),就会返回字符串"hellolinux"。
  1. let obj = {
  2.   name: "张三"
  3. }
  4. var str = '<div>{{name}}</div>'
  5. var pattern = /{{([a-zA-Z]+)}}/
  6. var patternResult = pattern.exec(str)
  7. str = str.replace(patternResult[0], obj[patternResult[1]])
  8. console.log(str)
复制代码
patternResult[0]是被匹配的字符串,也就是{{name}},patternResult[1]是提取到的分组,也就是name。只需要把原字符串str的{{name}}替换为obj['name']即可,也就是str.replace(patternResult[0], obj[patternResult[1]])。
输出效果:

如许就完成了元素的替换。
当整个字符串中有多个{{xxx}},可以使用一个循环进行匹配:
  1. let patternResult = null;
  2. while (patternResult = pattern.exec(str)) {
  3.         str = str.replace(patternResult[0], obj[patternResult[1]])
  4. }
复制代码
当pattern.exec匹配不到{{}}时,就会返回一个null,循环就会结束,整个模板字符串被完全替换为对象的值,最后得到一个可以直接渲染的html字符串。


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

愛在花開的季節

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表