当前位置: 首页 > 参考手册>阅读正文

JavaScript通用函数与组件设计

2022.5.11 朱丰华 3135 次 留下评论 8655字

在前端开发中,虽然有很多框架和类库,但储备一些常用的函数仍然是有必要的。

从通用性考虑,这里举例一些常用函数或组件。

消息提醒

普通的alert函数样式太单调,且需要用户点击确认,不够友好。下面简单的设计一个消息提醒函数,它依赖于jquery

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8"/>
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Jquery消息提醒</title>
        <script src="https://www.52dixiaowo.com/tools/npm/jquery@3.6.0/dist/jquery.min.js"></script>
        <link rel="stylesheet" href="https://www.52dixiaowo.com/tools/npm/font-awesome@4.7.0/css/font-awesome.min.css">
        <script src="https://www.52dixiaowo.com/tools/npm/bootstrap@3.4.1/dist/js/bootstrap.min.js"></script>
        <link rel="stylesheet" href="https://www.52dixiaowo.com/tools/npm/bootstrap@3.4.1/dist/css/bootstrap.min.css">
    </head>
    <body>  
      <div class="container">
        <h2 class="text-left">Jquery消息提醒案例</h2>
        <div class="btn-group">
            <button id="default" class="btn btn-default" onclick="message('普通消息')">普通消息</button>
            <button id="info" class="btn btn-info" onclick="message('通知消息','info')">通知消息</button>
            <button id="success" class="btn btn-success" onclick="message('成功消息','success')">成功消息</button>
            <button id="warning" class="btn btn-warning" onclick="message('警告消息','warning')">警告消息</button>
            <button id="error" class="btn btn-danger" onclick="message('错误消息','error')">错误消息</button>
        </div>
    </div>
    <script>
        function message(text,type){
            let text_class = "";

            type = type || "default";

            switch(type){
            
            case "default":
                text_class = "fa fa-comments";
                break;
            case "info":
                text_class = "fa fa-info-circle text-info";
                break;
            case "success":
                text_class = "fa fa-check-square-o text-success";
                break;
            case "warning":
                text_class = "fa fa-warning text-warning";
                break;
            case "error":
                text_class = "fa fa-close text-danger";
                break;
            default:
                throw "消息type错误,请传递default(可缺省)/info/success/warning/error中的任一种";
                break;
            }
            let msgs = $(".message");
            let len = msgs.length; 
            let end = 0;
            let baseHeight = 0;
            if(len>0){
                baseHeight =msgs.first().innerHeight()+20;
                let start = msgs.first().attr('no');
                end = +start+len;
            }
            let height = 100+end*baseHeight+"px";
            $(`<div no='${end}' id='msg-${end}' class='message ${text_class}' style='top: ${height};position: fixed;left: 50%;border: 1px solid #ddd;
            background-color:#bbb;transform: translate(-50%, -50%);font-size: 1.2em;padding: 1rem;z-index: 999;border-radius: 0.5rem;'>${text}</div>`).appendTo("body");
            let rmScript = `$("#msg-${end}").remove();`;
            setTimeout(rmScript,1500);
        }
    </script>
    </body>
</html>

Query参数处理

通常,我们很难处理query参数,虽然浏览器内置了URLSearchParams函数但被支持的浏览器有限。

1.获取query参数,封装到JSON对象中。

<script>
    /** 
     * 获取url查询参数
     * base 是否使用原始格式,如果true则保留原格式,否则默认自动解码
     */
    function getQuery(base){
        let query = location.search.substring(1)
        let key_values = query.split("&")
        let obj = {}
        key_values.forEach(key_val => {
            let key_val_split = key_val.split("=")
            let obj_value;
            if(!base){
                obj_value = decodeURIComponent(key_val_split[1])
            }else{
                obj_value = key_val_split[1]
            }
            if(obj_value){  // 不为空时,尝试自动转number
                let number_value = Number(obj_value)
                if(!isNaN(number_value)){
                    obj_value = number_value
                }
            }
            obj[key_val_split[0]] = obj_value
        });
        return obj
    }
    
    let url = location.href+"?page=1&name=中文"
    history.pushState(null, "", url);
    document.write(JSON.stringify(getQuery(true)))
    document.write("<br>解码后<br>")
    document.write(JSON.stringify(getQuery()))


    </script>

取得的字符串,默认是解码后的,这样更实用。

2.生成查询字符串

<script>

/* 生成query字符串 */
function makeQuery(obj,encode){
    let s = ''
    for(x in obj){
        if(encode){
            s += `${x}=${encodeURIComponent(obj[x])}&`
        }else{
            s += `${x}=${obj[x]}&`
        }
    }
    return s.substring(0,s.length-1)
}

let pageNum = 1;
let pageSize = 3;
let obj = {"pageNum":pageNum,"pageSize":pageSize,"s":"中文"}

document.write(makeQuery(obj,true));


</script>

返回顶部组件

对于长网页,提供一个返回顶部的按钮是有必要的,下面这个案例基于jquery

<!DOCTYPE html>
<html>
    <head>
        <title>jquery返回顶部案例</title>
        <script src="https://www.52dixiaowo.com/tools/npm/jquery@3.6.0/dist/jquery.min.js"></script>
        <link rel="stylesheet" href="https://www.52dixiaowo.com/tools/npm/font-awesome@4.7.0/css/font-awesome.min.css">
        <meta name="viewport" content="width=device-width, initial-scale=1"/>
        <style>
            html{
                height: 2000px;
            }
        </style>
    </head>
    <body>
        <p>尝试向下滚动</p>
        <div id="toup" style="position: fixed; right: 20px; bottom: 20px; display: block;">
            <a onclick="javascript:$('html,body').animate({scrollTop:0}, 1000)" title="返回顶部" id="back-to-top" 
            style="display: block; position: fixed; bottom: 10px; background-color: rgb(95, 99, 104); box-sizing: border-box; 
            cursor: pointer; text-align: center; border: 0px; right: 20px;"><i class="fa fa-angle-up" 
            style="height:40px;width:40px;display:block;line-height:40px;color:#fff;"></i></a>
        </div>
        <script>
            // 初始时隐藏
            $("#toup").hide();
            // 向下滚动滚动后出现
            $(window).scroll(function(){
            let scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
            if(scrollTop>=100){
                $("#toup").show();
            }else{
                $("#toup").hide();
            }
            });

            // 移动端在左,PC端在右
            function fix(){
                if(document.body.clientWidth<901){
                    $("#back-to-top").css({"left":"20px","right":""});
                }else{
                    $("#back-to-top").css({"right":"20px","left":""});
                }
            }
            // 页面首次加载
            $(function(){
                fix();
            })
            // 窗口大小变化
            $(window).resize(function(){
                fix();
            })
        </script>
    </body>
</html>

分页组件

这里使用bootstrap样式做一个案例。分页一般只显示10页

第一个页时,显示后9页

前后都有时,前面有5页,后面有4页

最后一页时,显示前9页

<!DOCTYPE html>
<html>
    <head>
        <title>bootstrap分页案例</title>
        <script src="https://www.52dixiaowo.com/tools/npm/jquery@3.6.0/dist/jquery.min.js"></script>
        <link rel="stylesheet" href="https://www.52dixiaowo.com/tools/npm/font-awesome@4.7.0/css/font-awesome.min.css">
        <meta name="viewport" content="width=device-width, initial-scale=1"/>
        <script src="https://www.52dixiaowo.com/tools/npm/bootstrap@3.4.1/dist/js/bootstrap.min.js"></script>
        <link rel="stylesheet" href="https://www.52dixiaowo.com/tools/npm/bootstrap@3.4.1/dist/css/bootstrap.min.css">
    </head>
    <body>
        <p>bootstrap分页样式</p>
        <nav class="text-center">
            <ul id="navigation-page" class="pagination">
                <!-- <li class="disabled"><a id='prevPage'>&laquo;</a></li>
                <li><a>1</a></li>
                <li class="active"><a>2</a></li>
                <li><a>3</a></li>
                <li class='disabled'><a id="nextPage">&raquo;</a></li> -->
            </ul>
        </nav>

        <script>

            $(function(){
               
                // 模拟分页数据,这里总共16页。

                // 模拟分页数据:第1页
                // let pageInfo = {"total":31,"pages":16,"hasPrePage":false,"size":2,"hasNextPage":true,"prePage":0,"nextPage":2,"isLastPage":false,"pageSize":2,"isFirstPage":true,"pageNum":1}
                // 模拟分页数据:第二页
                // let pageInfo = {"total":31,"pages":16,"hasPrePage":true,"size":2,"hasNextPage":true,"prePage":1,"nextPage":3,"isLastPage":false,"pageSize":2,"isFirstPage":false,"pageNum":2}
                // 模拟分页数据:第7页
                // let pageInfo = {"total":31,"pages":16,"hasPrePage":true,"size":2,"hasNextPage":true,"prePage":6,"nextPage":8,"isLastPage":false,"pageSize":2,"isFirstPage":false,"pageNum":7}
                // 模拟分页数据:第8页
                let pageInfo = {"total":31,"pages":16,"hasPrePage":true,"size":2,"hasNextPage":true,"prePage":7,"nextPage":9,"isLastPage":false,"pageSize":2,"isFirstPage":false,"pageNum":8}
                // 模拟分页数据:第15页
                // let pageInfo = {"total":31,"pages":16,"hasPrePage":true,"size":2,"hasNextPage":true,"prePage":14,"nextPage":16,"isLastPage":false,"pageSize":2,"isFirstPage":false,"pageNum":15}
                // 模拟分页数据:第16页
                // let pageInfo = {"total":31,"pages":16,"hasPrePage":true,"size":1,"hasNextPage":false,"prePage":15,"nextPage":17,"isLastPage":true,"pageSize":2,"isFirstPage":false,"pageNum":16}
                navigationPage(pageInfo)
            })

            function navigationPage(pageInfo){
                // 1.清空分页
                let nav_page = $("#navigation-page")
                nav_page.empty()
                let str = ""
                let base_url = location.pathname
                // 2.是否展示分页
                if(pageInfo.pageNum==1 && !pageInfo.hasNextPage){
                    return ;  // 第一页,且没有下一页,不显示分页
                }
                // 3.是否有前一页
                if(pageInfo.hasPrePage){
                    str += `<li><a href="${base_url}?pageNum=${Number(pageInfo.pageNum)-1}&pageSize=${pageInfo.pageSize}">&laquo;</a></li>`
                }
                // 4.中间最多展示10分页,此数据可修改
                let nav_nums = 10
                // 4.1计算起始下标,前面起始标号一般是占一半页数,如果后面不足(一半-1)页,可考虑动态加上其剩余页值 
                let before_num = Math.floor(nav_nums/2)

                let after_num = pageInfo.pages-pageInfo.pageNum
                if(after_num<before_num-1) before_num += before_num-1-after_num
                
                let page_start = pageInfo.pageNum-before_num;
                if(page_start<1)  page_start = 1;
                // 4.2计算终止下标
                let page_end = page_start+nav_nums-1;
                if(page_end>pageInfo.pages) page_end = pageInfo.pages;


                // 4.3生成下标
                for(let i=page_start; i<=page_end; i++){
                    if(i===pageInfo.pageNum){
                        str += `<li class="active"><a href="${base_url}?pageNum=${i}&pageSize=${pageInfo.pageSize}">${i}</a></li>`
                    }else{
                        str += `<li><a href="${base_url}?pageNum=${i}&pageSize=${pageInfo.pageSize}">${i}</a></li>`
                    }
                }
                // 5.是否有下一页
                if(pageInfo.hasNextPage){
                    str += `<li><a href="${base_url}?pageNum=${Number(pageInfo.pageNum)+1}&pageSize=${pageInfo.pageSize}">&raquo;</a></li>`
                }
                // 6.添加到dom中
                nav_page.append(str)
            }

        </script>
    </body>
</html>

日期与格式化处理

html页脚自动更新年份

<span><script>document.write(new Date().getFullYear())</script></span>

对日期进行格式化

Date.prototype.format = function (fmt) {
  var o = {
    "M+": this.getMonth() + 1,                   //月份
    "d+": this.getDate(),                        //日
    "h+": this.getHours(),                       //小时
    "m+": this.getMinutes(),                     //分
    "s+": this.getSeconds(),                     //秒
    "q+": Math.floor((this.getMonth() + 3) / 3), //季度
    "S": this.getMilliseconds()                  //毫秒
  };

  //  获取年份 
  if (/(y+)/i.test(fmt)) {
    fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
  }

  for (var k in o) {
    if (new RegExp("(" + k + ")", "i").test(fmt)) {
      fmt = fmt.replace(
        RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
    }
  }
  return fmt;
}

var now = new Date();
var nowStr = now.format("YYYY-MM-DD"); // 2021-11-13

console.log(nowStr);

本篇完,还有疑问?留下评论吧

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注