跨域和模版引擎的使用

1,033 阅读2分钟

笔记来源:拉勾教育 - 大前端就业集训营

文章内容:学习过程中的笔记、感悟、和经验

跨域和模版引擎的使用

跨域问题和同源策略

同源策略

  • 是浏览器的一种安全机制,同源即域名、协议、端口完全相同
  • 在同源策略下,只有同源的地址才能相互通过AJAX方式交流
  • 同源指的是两个地址之间的关系,不同源的地址之间的请求称做跨域

http(协议)://www.baidu.com(域名):80(端口-默认80可不写)/index.html

浏览器不允许通过跨域获取数据,但是现代web应用中我们又需要获取不同源地址的资源,必须解决不同源问题,实现跨域请求数据

JSONP

JSON with Padding,借助script标签发送跨域请求的方法

基本原理:

  • 在客户端通过script标签请求服务端的一个地址
  • script返回的结果带一段全局函数调用的js脚本
  • 这个函数调用会调用我们本地js的一个函数
  • 而函数的实参就是我们想要的数据

jsonp只能发送get请求,jsonp和XHR没有任何关系

JQ中的jsonp

使用$.ajax()方法,只需要把dataType类型设置为jsonp

<body>
  <!-- 创建按钮 -->
  <input type="button" value="获取">
  <script>
    // 按钮添加点击事件
    $('input').click(function () {
      // 以jsonp的方式获取数据
      $.ajax({
        // 地址:这是一个百度搜索的时候提示文本的接口
        url: 'https://www.baidu.com/sugrec?pre=1&p=3&ie=utf-8&json=1&prod=pc&from=pc_web',
        // 方式使用get
        type: 'get',
        // 设置dataType为jsonp就可以以jsonp方式获取数据
        dataType: 'jsonp',
        //这里可以设置jsonp的回调函数的名字,如果不设置jq会自动生成一个名字
        jsonpCallback: 'abc',
        // 这里可以修改回调函数的参数名,默认callback,但如果接口强制要求了参数民,就需要我们手动设置和接口要求的一样
        jsonp: 'cd',
        // 要传入的数据
        data: {
          wd: 'ajax'
        },
        // 打印返回的数据
        success: function (data) {
          console.log(data)
        }
      })
    })
    // 大部分情况下不需要设置回调函数的名字和参数
  </script>
</body>

CORS跨域

Cross Origin Resource Share -- 跨域资源共享

无需在客户端做出任何变化,只需要在服务端响应的时候添加一个Access-Control-Allow-Origin的响应头即可,表示这个资源是否支持指定域请求

Access-Control-Allow-Origin的值

  • 为*表示任何源都可以跨域访问这个文件,不安全
  • 值为(一个域名+协议)例如:http://foo.com表示只允许指定的源访问

cors跨域现在较常使用

案例:百度搜索

模拟百度搜索时候的自动提示

  1. 在百度试一下,打开控制台network,查看文件response看到回调函数名为jQuery110202399796524493838_1611211395892(参数),说明是一个jsonp格式发送的
  2. 打开headers找到函数名cb=jQuery110202399796524493838_1611211395892&_=1611211395894,所以参数名为cd
  3. 实际接收参数的参数是wd:&wd=12(我搜索的就是12)
  4. 接口地址为https://www.baidu.com/sugrec?pre=1&p=3&ie=utf-8&json=1&prod=pc&from=pc_web
<!DOCTYPE html
  PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">

<head>
  <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
  <title>楼梯导航效果</title>
  <script src="./js/jquery.min.js"></script>
  <style>
    * {
      margin: 0;
      padding: 0;
    }

    ul {
      list-style: none;
    }

    .box {
      width: 500px;
      margin: 100px auto;
    }

    .box .l {
      float: left;
      width: 396px;
      border: 2px solid #4e6ef3;
      overflow: hidden;
    }

    .box .l input {
      width: 396px;
      height: 36px;
      border: 0;
      outline: none;
    }

    .box .r {
      float: right;
      width: 100px;
      height: 40px;
      border: 0;
      background-color: #4e6ef3;
      color: #fff;
    }
  </style>
</head>

<body>
  <div class="box">
    <div class="l">
      <input type="text">
      <ul>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
      </ul>
    </div>
    <input class="r" type="button" value="百度一下">
  </div>
  <script>
    // 获取元素
    const $lis = $('.box .l ul li'),
      $input = $('.box .l input')
    // 给输入框添加键盘抬起事件
    $input.keyup(function () {
      // 跨域请求
      $.ajax({
        url: 'https://www.baidu.com/sugrec?pre=1&p=3&ie=utf-8&json=1&prod=pc&from=pc_web',
        // jsonp方式
        dataType: 'jsonp',
        // 设置参数值为cb
        jsonp: 'cb',
        // 设置参数
        data: {
          wd: $(this).val()
        },
        // 使用返回的数据到ul上
        success: function (data) {
          if (data.g === undefined) {
            return
          }
          $lis.each(function (i) {
            $(this).text(data.g[i].q)
          })
        }
      })
    })
  </script>
</body>

</html>

模版引擎

  • 减少字符串拼接
  • 在模版里面解析json,然后跟html内容进行拼接,性能更好

artTemplate模版引擎(腾讯)

简约、超快的模版引擎

地址:github.com/aui/artTemp…

中文文档:aui.github.io/art-templat…

常用语法:

  • <% js代码 %>符号包裹起来的语句则为模版逻辑表达式
  • <%= 表达式 %>为输出表达式

使用

  1. 引入模版js文件
  2. 创建模版
  3. 数据模版绑定
  4. 编写解析数据
  5. 绑定数据和模版之后得到内容
  6. 数据书写到页面上
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>使用模版引擎</title>
  <!-- 引入jquery -->
  <script src="./js/jquery.min.js"></script>
  <!-- 引入模版引擎altTelplate -->
  <script src="./js/template-web.js"></script>
  <!-- 新建模版引擎,id属性是后面使用模版时候的第一个参数,type使用text/html -->
  <script id="tem" type="text/html">
    <!-- 使用模版js代码前后需要加 <% %>包裹起来 -->
  <!-- 如果想使用变量等表达式使用<%=  %>包裹 -->
  <% for(let i = 0; i < 5; i++){ %>
  <li> 我是模版内部创建的<%= i %></li>
  <%}%>
    <!-- 使用template的第二个参数,直接使用里面的属性名即可使用属性值 -->
  <li>我是数组中的数据<%= name%></li>
  </script>
</head>

<body>
  <div class="box">
    <ul class="list"></ul>
  </div>
  <script>
    // 创建一个数组
    const arr = [{
      name: 1
    }, {
      name: 2
    }, {
      name: 3
    }, {
      name: 4
    }, {
      name: 5
    }, {
      name: 6
    }, ]
    //循环遍历数组,把每一个数组中的对象都带入template方法
    for (const i of arr) {
      // template方法支持两个参数,第一个是要使用的模版的id值,第二个参数是要使用的对象类型的数据,模版可以直接使用对象中的属性名从而获取属性值
      // 循环给ul添加li
      $('.box .list').append(template('tem', i))
    }
  </script>
</body>

</html>

使用模版引擎改造百度案例

<!DOCTYPE html
  PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">

<head>
  <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
  <title>百度</title>
  <!-- 引入模版引擎 -->
  <script src="./js/template-web.js"></script>
  <!-- // 引入jq -->
  <script src="./js/jquery.min.js"></script>
  <!-- 创建模版 -->
  <script id="tem" type="text/html">
    <!-- 循环遍历g属性 -->
    <% for(let i = 0; i < g.length; i++){ %>
  <!-- 创建li,里的值为每一个g内容的q属性 -->
  <li><%= g[i].q %></li>
  <% } %>
  </script>
  <style>
    * {
      margin: 0;
      padding: 0;
    }

    ul {
      list-style: none;
    }

    .box {
      width: 500px;
      margin: 100px auto;
    }

    .box .l {
      float: left;
      width: 396px;
      border: 2px solid #4e6ef3;
      overflow: hidden;
    }

    .box .l input {
      width: 396px;
      height: 36px;
      border: 0;
      outline: none;
    }

    .box .r {
      float: right;
      width: 100px;
      height: 40px;
      border: 0;
      background-color: #4e6ef3;
      color: #fff;
    }
  </style>
</head>

<body>
  <div class="box">
    <div class="l">
      <input type="text">
      <ul>
        <!-- 模版引擎生成的结构添加到这里 -->
      </ul>
    </div>
    <input class="r" type="button" value="百度一下">
  </div>
  <script>
    // 获取元素
    const $ul = $('.box .l ul'),
      $input = $('.box .l input')
    // 给输入框添加键盘抬起事件
    $input.keyup(function () {
      // 跨域请求
      $.ajax({
        url: 'https://www.baidu.com/sugrec?pre=1&p=3&ie=utf-8&json=1&prod=pc&from=pc_web',
        // jsonp方式
        dataType: 'jsonp',
        // 设置参数值为cb
        jsonp: 'cb',
        // 设置参数
        data: {
          wd: $(this).val()
        },
        // 使用返回的数据到ul上
        success: function (data) {
          // 判断数据是否存在
          if (data.g === undefined) {
            return
          }
          // 调用模版引擎,把生成的结果添加到ul上
          $ul.html(template('tem', data))
        }
      })
    })
  </script>
</body>

</html>

案例:留言板

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <!-- 引入css样式文件 -->
  <link rel="stylesheet" href="css/index.css">
  <!-- 引入模版引擎文件 -->
  <script src="./js/template-native.js"></script>
  <!-- 引用jq文件 -->
  <script src="js/jquery-1.12.4.min.js"></script>
  <!-- 创建模版 -->
  <script id="tem" type="text/html">
    <!-- 循环遍历输入进来的数据,传进来的data对象里面有一个comments属性的数组,遍历数组下面的所有数据 -->
    <% for(let i = 0; i < comments.length; i++){ %>
  <!-- 书写结构,并调用数据中的值 -->
  <!-- 在li上面新建一个自定义属性,标记自己在数据库中的位置,后面删除需要这个属性 -->
  <li uid="<%= comments[i].id%>">
    <p class="floor"><%= comments[i].id%>楼<a href="javascript:;" class="delete">删除</a></p>
    <p class="author">层主:<%= comments[i].username%><span class="name"></span></p>
    <p class="content"><%= comments[i].content%></p>
  </li>
  <% } %>
  </script>
</head>

<body>
  <!-- 结构 -->
  <div class="main">
    <div class="post">
      <h2>新年快乐</h2>
      <p class="author">楼主:行痴</p>
      <p class="txt">新的一年,祝大家新年快乐,身体健康,升职加薪!</p>
    </div>
    <div class="reply">
      <h4>发表回复</h4>
      <p>用户名:<input type="text" class="reply"></p>
      <textarea class="editor"></textarea>
      <input type="button" value="发表" class="btn">
    </div>
    <div class="cmts">
      <ul class="list">
        <!-- 留言添加到这 -->
      </ul>
    </div>
  </div>
  <script>
    // 获取元素
    const $list = $('.main .cmts .list'),
      $user = $('.reply input:text'),
      $textarea = $('.reply textarea'),
      $btn = $('.reply .btn')
    // 初始化,使用get获取数据,调用模版引擎修改留言板列表
    $.get('http://localhost:3000/db', function (data) {
      $list.html(template('tem', data))
      // 调用函数给每个删除按钮添加删除功能
      del()
    })
    // 发表按钮点击事件
    $btn.click(function () {
      // 先判断是否为空,如果为空提示用户
      if ($user.val() === '' || $textarea.val() === '') {
        alert('输入不正确')
        return
      }
      // 如果不为空执行下面的代码
      // 使用pose方法向数据库添加数据
      $.post('http://localhost:3000/comments', {
        username: $user.val(),
        content: $textarea.val()
      }, function (data) {
        // 返回的数据代入模版,但是模版需要是一个对象并且对象需要有一个comments属性的数组,所有手动模拟对象
        $list.append(template('tem', {
          comments: [data]
        }))
        // 新添加的删除按钮没有删除功能,我们在这里给全部删除按钮调用函数重新添加删除功能
        del()
      })
    })
    // 删除按钮啊添加删除功能函数
    function del() {
      // 给每一个按钮添加点击事件
      $('.delete').click(function () {
        // 从数据库里面删除数据,找到删除按钮的祖先li标签,根据li标签的自定义属性值删除元素
        $.ajax({
          url: `http://localhost:3000/comments/${$(this).parents('li').attr('uid')}`,
          type: 'delete'
        })
        // 找到删除按钮的祖先的li标签,删除它
        $(this).parents('li').remove()
      })
    }
  </script>
</body>

</html>
{
  "comments": [
    {
      "id": 4,
      "username": "江江",
      "content": "给楼主打call~ +10000"
    },
    {
      "username": "西毒",
      "content": "楼主一般",
      "id": 6
    },
    {
      "username": "东邪",
      "content": "哈哈哈哈",
      "id": 7
    }
  ]
}