ajax学习第二天
ajax学习第二天
1.form表单
-  作用:采集数据到服务器 
-  属性 
| 属性 | 值 | 描述 | 
|---|---|---|
| action | URL地址 | 规定当提交表单时,向何处发送表单数据 | 
| method | get或post | 规定以何种方式把表单数据提交到action URL | 
| enctype | application/x-www-form-urlencoded | 规定在发送表单数据前如何将其编码 | 
| target | _blank, _self, _parent, _top | 规定在何处打开action URL | 
1.1target属性说明
- _blank:在新窗口打开
- _self:默认,在相同的框架中打开
- _parent,在父框架中打开(很少用)
- _top:在整个窗口打开:(很少用)
- framename:在指定的框架中打开
_blank 示例
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <form action="/login" target="_blank">
        <input type="text" name="user">
        <input type="password" name="psw">
        <input type="submit">
    </form>
</body>
</html>
- 效果图

1.2 method属性说明
- get适合提交少量的,简单的数据(默认)(提供uRL地址形式提交,不安全)
- post适合用于提交大量的,复杂的或包含文件上传的数据
get示例
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <form action="/login" target="_blank" method="GET">
        <input type="text" name="user">
        <input type="password" name="psw">
        <input type="submit">
    </form>
</body>
</html>
- 效果图

post 示例
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <form action="/login" target="_blank" method="post">
        <input type="text" name="user">
        <input type="password" name="psw">
        <input type="submit">
    </form>
</body>
</html>
- 效果图

1.3 enctype 属性说明
| 值 | 描述 | 
|---|---|
| application/x-www-form-urlencoded | 在发送前编码所有字符(默认) | 
| multipart/form-data | 不对字符编码,在使用包含文件上传控件的表单时,必须使用该值 | 
| text/plain | 空格转换为“+”加号,但不对特殊字符编码(很少用) | 
1.4 action属性说明
-  如果不指定action的属性值,则默认值为当前页面的URL地址 
-  示例 
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <form action="">
        <input type="text" name="user">
        <input type="password" name="psw">
        <input type="submit">
    </form>
</body>
</html>
- 效果图

- 指定action的示例
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <form action="/login">
        <input type="text" name="user">
        <input type="password" name="psw">
        <input type="submit">
    </form>
</body>
</html>
- 效果图

1.5 表单的同步提交
-  定义:点击submit按钮,实现表单提交,使页面跳转到action URL的行为 
-  缺点 - 页面会发生跳转
- 页面之前的状态和数据会丢失
 
-  解决方案 - 表单用于数据采集,ajax实现数据提交
 
2. ajax提交表单数据
2.1 监听表单提交
- 在jQuery中的监听表单提交事件
$("#form1").submit(function(e){})
//第二种方式
$("#form2").on("submit",function(e){})
示例
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="./lib/jquery.js"></script>
</head>
<body>
    <form action="/login" target="_blank" method="post" class="form1">
        <input type="text" name="user">
        <input type="password" name="psw">
        <input type="submit">
    </form>
    <script>
        $(function() {
            $(".form1").on("submit", function(e) {
                console.log(e);
            })
        })
    </script>
</body>
</html>
- 效果图

2.2 阻止表单默认提交行为
e.preventDefault();
示例
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="./lib/jquery.js"></script>
</head>
<body>
    <form action="/login" target="_blank" method="post" class="form1">
        <input type="text" name="user">
        <input type="password" name="psw">
        <input type="submit">
    </form>
    <script>
        $(function() {
            $(".form1").on("submit", function(e) {
                alert("表单提交事件");
                console.log(e);
                // 阻止表单默认行为
                e.preventDefault();
            })
        })
    </script>
</body>
</html>
- 效果图

2.3 通过serialize()函数获取表单所有数据
-  前提:必须为每一个form中的表单元素添加name属性 
-  收集交给表单,发送交给ajax 
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="./lib/jquery.js"></script>
</head>
<body>
    <form action="/login" target="_blank" method="post" class="form1">
        <input type="text" name="user">
        <input type="password" name="psw">
        <input type="submit">
    </form>
    <script>
        $(function() {
            $(".form1").on("submit", function(e) {
                // alert("表单提交事件");
                // console.log(e);
                // 阻止表单默认行为
                e.preventDefault();
                // 提交交给ajax
                var data = $(this).serialize();
                // 返回值为字符串
                console.log(data);
            })
        })
    </script>
</body>
</html>
- 效果图

3. 一个案例
3.1 bs3框架的一些知识点
单独的表单控件会被自动赋予一些全局样式。所有设置了
.form-control类的<input>、<textarea>和<select>元素都将被默认设置宽度属性为width: 100%;。
- 面板布局
bs3-panel
- 列表布局
bs3-list
一个发表评论案例
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="./lib/bootstrap.css">
    <style>
        body {
            padding: 15px;
        }
        
        .list-group-item .badge:nth-child(1) {
            background-color: orange !important;
        }
        
        .list-group-item .badge:nth-child(2) {
            background-color: skyblue !important;
        }
    </style>
    <script src="./lib/jquery.js"></script>
</head>
<body>
    <!-- vscode 快捷键 bs3-panel -->
    <div class="panel panel-primary">
        <div class="panel-heading">
            <h3 class="panel-title">发表评论</h3>
        </div>
        <form class="panel-body" id="addCmt">
            <p>评论人</p>
            <input type="text" class="form-control person" name="username">
            <p>评论内容</p>
            <!-- bs3-textarea -->
            <textarea id="input" class="form-control" rows="3" required="required" name="content"></textarea>
            <button type="submit" class="btn btn-primary" style="margin-top: 5px;">发表</button>
        </form>
    </div>
    <!-- bs3-list -->
    <ul class="list-group">
        <li class="list-group-item">
            <span class="badge">评论时间:</span>
            <span class="badge">评论人:</span> item
        </li>
    </ul>
    <script>
        var cmtlists = [];
        getCmt(cmtlists);
        // 从服务器获取评论列表
        function getCmt(cmtlists) {
            $.ajax({
                method: "GET",
                url: "http://www.liulongbin.top:3006/api/cmtlist",
                success: function(res) {
                    if (res.status === 200) {
                        cmtlists = res.data;
                        flesh(cmtlists);
                    } else {
                        alert("获取评论列表失败");
                    }
                }
            })
        }
        // 渲染页面
        function flesh(cmtlists) {
            $("ul.list-group").html("");
            for (var i = 0; i < cmtlists.length; i++) {
                var li = $('<li class="list-group-item"><span class="badge">评论时间:' + cmtlists[i].time + '</span><span class="badge">评论人:' + cmtlists[i].username + '</span> ' + cmtlists[i].content + '</li>');
                $("ul.list-group").append(li);
            }
        }
        // 写数据到服务器
        // $(".btn").on("click", function() {
        //     if ($("#input").val() !== '' && $(".person").val() !== '') {
        //         $.ajax({
        //             method: "POST",
        //             url: "http://www.liulongbin.top:3006/api/addcmt",
        //             data: {
        //                 username: $(".person").val(),
        //                 content: $("#input").val()
        //             },
        //             success: function(res) {
        //                 if (res.status === 201) {
        //                     alert("发布评论成功");
        //                     getCmt(cmtlists);
        //                 } else {
        //                     alert("发布评论失败");
        //                 }
        //             }
        //         })
        //     }
        // })
        // 监听表单事件
        $(function() {
            $("#addCmt").on("submit", function(e) {
                // 阻止默认行为
                e.preventDefault();
                // 发起post请求
                // 获取表单信息
                var adata = $(this).serialize();
                // $.ajax({
                //     method: "post",
                //     url: "http://www.liulongbin.top:3006/api/addcmt",
                //     adata,
                //     success: function(res) {
                //         if (res.status === 201) {
                //             getCmt(cmtlists);
                //             // 清空表单信息
                //             $("#addCmt")[0].reset();
                //         } else {
                //             alert("发表评论失败");
                //         }
                //     }
                // })
                $.post("http://www.liulongbin.top:3006/api/addcmt", adata, function(res) {
                    if (res.status === 201) {
                        getCmt(cmtlists);
                        // 清空表单信息
                        $("#addCmt")[0].reset();
                    } else {
                        alert("发表评论失败");
                    }
                })
            })
        })
    </script>
</body>
</html>
- 效果图

4. 模板引擎
- 定义:根据程序员指定的模板结构和数据,自动生成一个完整的HTML页面
- 图解

-  解决上文字符串反复拼接的问题 
-  优点 - 减少了字符串的拼接操作
- 代码结构清晰
- 利用阅读和维护
 
5.art-template模板引擎
5.1 有无引擎的对比
- 无引擎
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="./lib/jquery.js"></script>
</head>
<body>
    <!-- 1.首先创建HTML结构 -->
    <div id="title"></div>
    <div>姓名:<span id="name"></span></div>
    <div>年龄:<span id="age"></span></div>
    <div>是否会员:<span id="isVip"></span></div>
    <div>注册时间:<span id="regTime"></span></div>
    <div>
        <ul id="hobby">
        </ul>
    </div>
    <script>
        // 例如数据为
        var data = {
            title: '<h3>用户信息</h3>',
            name: 'zs',
            age: 20,
            isVIP: true,
            regTime: new Date(),
            hobby: ['吃饭', '睡觉', '打豆豆']
        }
        $("#title").html(data.title);
        $("#name").html(data.name);
        $("#age").html(data.age);
        $("#isVip").html(data.isVIP);
        $("#regTime").html(data.regTime);
        var temp = [];
        $.each(data.hobby, function(i, ele) {
            temp.push("<li>" + ele + "</li>");
        })
        $("#hobby").append(temp.join(' '));
    </script>
</body>
</html>
- 有引擎渲染
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="./lib/jquery.js"></script>
    <!-- 引入art-template-web 渲染js -->
    <script src="./lib/template-web.js"></script>
    <!-- 2.引入后,页面就会增加一个新的函数 template('模板的id',需要渲染的数据对象)-->
</head>
<body>
    <div class="con"></div>
    <!-- 3.定义模板  必须定义到script标签中,模板为html结构  加type="text/html"-->
    <script type="text/html" id="tep-user">
        <!-- 如果占位符的内容包括html结构标签,需要在前面加上@实现结构的渲染 -->
        <div id="title"> {{@title}} </div>
        <div>姓名:<span id="name">{{name}}</span></div>
        <div>年龄:<span id="age">{{age}}</span></div>
        <div>是否会员:<span id="isVip">{{isVIP}}</span></div>
        <div>注册时间:<span id="regTime">{{regTime}}</span></div>
        <div>
            <ul id="hobby">
                {{each hobby}}
                <li>{{$value}}</li>
                {{/each}}
            </ul>
        </div>
    </script>
    <!-- 4.定义数据 -->
    <script>
        var data = {
            title: '<h3 id="1">用户信息</h3>',
            name: 'zs',
            age: 20,
            isVIP: true,
            regTime: new Date(),
            hobby: ['吃饭', '睡觉', '打豆豆']
        }
        // 调用函数
        var htmlstr = template("tep-user", data);
        $(".con").html(htmlstr);
    </script>
</body>
</html>
- 效果图(一样的效果图),这里数据少,体现不出渲染引擎的优点

5.2 渲染引擎的使用
- 导入art-template
- 定义数据
- 定义模板
- 调用template函数
- 渲染HTML结构
5.3 art-template的标准语法
-  {{}}语法:在{{}}中可以进行变量输出,循环数组等操作 
-  示例 
{{value}}   //变量输出
{{obj.key}} //对象属性的输出
{{obj['key']}}  //对象属性的输出
{{a ? b : c}}  //三元运算符的输出
{{a || b}}   //逻辑表达式输出
{{a + b}}    //加减乘除输出
5.3.1 原文输出
- 如果要输出的value值中包含HTML结构,则需要原文输出,才能使HTML结构被渲染
{{@value}}
5.3.2 条件输出
- 实现分支语句的输出
{{if value}} 满足条件输出的内容{{/if}}
//多分支输出
{{if value1}} 输出满足value1成立的内容{{else if v2}}
输出v2满足内容{{/if}}
5.3.3 循环输出
- 通过each语法循环数组, i n d e x 代 表 索 引 号 , index代表索引号, index代表索引号,value代表值
{{each arr}}
{{$index}} {{$value}}
{{/}}
5.3.4 过滤器
- 图解

- 定义过滤器
template.defaults.imports.filterName=function(value){/*return处理的结果*/}
- 使用过滤器
{{value|filterName}}
示例
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="./lib/jquery.js"></script>
    <!-- 引入art-template-web 渲染js -->
    <script src="./lib/template-web.js"></script>
    <!-- 2.引入后,页面就会增加一个新的函数 template('模板的id',需要渲染的数据对象)-->
</head>
<body>
    <div class="date"></div>
    <!-- 定义模板结构 -->
    <script type="text/html" id="temp">
        <h3>{{date | filterName}}</h3>
    </script>
    <script>
        // 定义一个过滤器
        template.defaults.imports.filterName = function(date) {
            var year = date.getFullYear();
            var month = date.getMonth() + 1;
            var day = date.getDate();
            return year + "-" + month + "-" + day;
        }
        // 定义数据
        var data = {
            date: new Date()
        }
        // 调用template函数
        var htmlStr = template("temp", data);
        $(".date").html(htmlStr);
    </script>
</body>
</html>
- 效果图

获取新闻案例
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Document</title>
    <link rel="stylesheet" href="./assets/news.css" />
    <script src="./lib/jquery.js"></script>
    <script src="./lib/template-web.js"></script>
</head>
<body>
    <div id="news-list">
    </div>
    <!-- 定义一个模板 -->
    <script type="text/html" id="model">
        <!-- 遍历data数组 -->
        {{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>  
                        <span>{{$value.time|timeFilter}}</span>
                    </div>
                    <span>评论数:{{$value.cmtcount}}</span>
                </div>
            </div>
        </div>
        {{/each}}
    </script>
    <script>
        // 定义一个tags的过滤器
        // 日期格式化过滤器
        template.defaults.imports.timeFilter = function(time) {
            // 根据默认格式创建一个日期对象,在格式化
            var time1 = new Date(time);
            var year = time1.getFullYear();
            var month = time1.getMonth() + 1;
            var date = time1.getDate();
            var h = parseInt(time1.getHours());
            h = h < 10 ? '0' + h : h;
            var m = parseInt(time1.getMinutes());
            m = m < 10 ? '0' + m : m;
            var s = parseInt(time1.getSeconds());
            s = s < 10 ? '0' + s : s;
            return year + '-' + month + '-' + date + ' ' + h + ':' + m + ':' + s;
        }
        // 获取服务器的数据
        getDate();
        var data = [];
        function getDate() {
            $.get("http://www.liulongbin.top:3006/api/news", function(res) {
                if (res.status === 200) {
                    // alert("获取新闻列表成功");
                    // 对res的date数组中对象中的tags转换成字符串数组
                    for (var i = 0; i < res.data.length; i++) {
                        res.data[i].tags = res.data[i].tags.split(',');
                    }
                    var htmlstr = template("model", res);
                    console.log(htmlstr);
                    // 返回值内容放入列表
                    $("#news-list").html(htmlstr);
                } else {
                    alert("获取新闻列表失败");
                }
            })
        }
    </script>
</body>
</html>
- 效果图

6.正则表达式(模板引擎原理刨析)
6.1 基本语法
- exec()函数用于检索字符中的正则表达式的匹配
RegExpObject.exec(string)
- 如果字符串中有表达式的值,则返回该匹配值,否则返回null
示例
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script>
        var str = 'hello';
        // 检索
        var pattern = /o/;
        var pattern2 = /m/;
        console.log(pattern.exec(str));
        console.log(pattern2.exec(str));
    </script>
</body>
</html>
- 效果图

6.2 分组
-  正则表达式中()包起来的内容表示一个分组,可以通过分组来提取自己想要的内容 
-  返回值一个数组,包含正则匹配到的字符串,也包含分组里面的字符串 
示例
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script>
        var str = "<div>我是{{name}}</div>";
        // 正则获取分组
        // [a-zA-Z]表示获取a-z和A-Z的字符+(出现多次)
        // ()包起来的内容表示分组
        var pattern = /{{([a-zA-Z]+)}}/;
        console.log(pattern.exec(str));
    </script>
</body>
</html>
- 效果图

6.3 replace函数将{{(分组内容)}}替换成分组内容
- 示例
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script>
        var str = "<div>我是{{name}}</div>";
        // 正则获取分组
        // [a-zA-Z]表示获取a-z和A-Z的字符+(出现多次)
        // ()包起来的内容表示分组
        var pattern = /{{([a-zA-Z]+)}}/;
        console.log(pattern.exec(str));
        var result = pattern.exec(str);
        str = str.replace(result[0], result[1]);
        console.log(str);
    </script>
</body>
</html>
- 效果图

6.3.1 多次replace
-  进行正则表达式的匹配是从左到右的,一次获取第一个匹配到的,多次正则直到返回值为null,就把所有的匹配的给替换了 
-  示例 
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script>
        var str = "<div>我是{{name}}年龄{{ age }}</div>";
        // 正则获取分组
        // [a-zA-Z]表示获取a-z和A-Z的字符+(出现多次)
        // ()包起来的内容表示分组
        // \s*内容\s* 允许匹配内容两侧有多个空白字符
        var pattern = /{{\s*([a-zA-Z]+)\s*}}/;
        var result;
        // 多次replace直到返回null
        while ((result = pattern.exec(str)) !== null) {
            console.log(result);
            str = str.replace(result[0], result[1]);
        }
        console.log(str);
    </script>
</body>
</html>
- 效果图

6.4 通过正则实现模板引擎的效果
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script>
        var data = {
            name: '张三',
            age: 18
        }
        // 模板字符串
        var str = '<div>姓名:{{ name }}年龄:{{ age }}</div>';
        // 正则
        var pattern = /{{\s*([a-zA-Z]+)\s*}}/;
        // 开始替换
        var result;
        while (result = pattern.exec(str)) {
            str = str.replace(result[0], data[result[1]]);
        }
        console.log(str);
    </script>
</body>
</html>
- 效果图

6.5 自定义一个模板引擎
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <!-- 定义一个容器 -->
    <div id="box">
    </div>
    <!-- 定义模板结构 -->
    <script type="text/html" id="my-tep">
        <div>姓名:{{name }}</div>
        <div>年龄:{{ age }}</div>
        <div>性别:{{sex }}</div>
        <div>住址:{{ address}}</div>
    </script>
    <script>
        // 1.定义模板引擎
        function template(id, data) {
            var tep = document.getElementById(id);
            // 原先的内容
            var str = tep.innerHTML;
            // 正则
            var pattern = /{{\s*([a-zA-Z]+)\s*}}/;
            var result;
            while (result = pattern.exec(str)) {
                str = str.replace(result[0], data[result[1]]);
            }
            return str;
        }
        // 定义数据
        var data = {
            name: '张三',
            age: 18,
            sex: '男',
            address: '北京'
        }
        // 调用模板引擎
        var htmlstr = template("my-tep", data);
        var box = document.getElementById("box");
        box.innerHTML = htmlstr;
    </script>
</body>
</html>
- 效果图
 ![在这里插入图片描述]() 
 
                    
                
 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号