精华内容
下载资源
问答
  • Visio:为什么按下方向键,选中的目标不动,绘图区(页面)却在移动
    千次阅读
    2018-12-12 23:15:00

    造冰箱的大熊猫,本文适用于Microsoft Visio 2007@cnblogs 2018/12/12

     

    检查下键盘的“Scroll Lock”键是不是被激活了(键盘上对应的指示灯被点亮)。Scroll Lock键被激活时,按下方向键等同于用鼠标拖动绘图区右侧或下方的滚动条。

     

    实际上,这(Scroll Lock激活后按下方向键滚动页面)是Scroll Lock键本身的功能,而非Visio的特殊功能。IBM(国际商用机器公司)设计IBM PC时,显示器只能提供二十几行×80个字符/行的显示能力。如果要在文本编辑软件中浏览一个较长的文档,使用方向键在文本前后大范围移动显然是件耗时且痛苦的事情。因此,IBM在键盘上设计了Scroll Lock键和对应的指示灯。当Scroll Lock键禁止时,用户按下方向键可移动光标。当Scroll Lock键激活时,用户按下方向键则文档翻页。随着时间的推移,这个键被用到的越来越少,但Microsoft的Visio、Excel以及LibreOffice Calc等软件上仍使用该按键。

    转载于:https://www.cnblogs.com/pandabang/p/10111645.html

    更多相关内容
  • 主要介绍了通过Java实现对PDF页面的详细设置,下面的示例将介绍通过Java编程来对PDF页面进行个性化设置的方法,包括设置页面大小、页边距、纸张方向页面旋转等,需要的朋友可以参考下
  • word单页怎么改变纸张方向

    千次阅读 2021-02-05 01:21:37
    word改变单页纸张方向的方法:1、将插入点移动到需要修改的单页的开头;2、在“布局”菜单中“分隔符”下选择“下一页”;3、点击“纸张方向”,选择“横向”;...在word的布局选项中纸张方向可以修改页面为横板...

    word改变单页纸张方向的方法:1、将插入点移动到需要修改的单页的开头;2、在“布局”菜单中“分隔符”下选择“下一页”;3、点击“纸张方向”,选择“横向”;4、将插入点移动到下一页的开头,再点击“分隔符”的“下一页”,再点击“纵向”即可。

    936bfcb5ca0f4e6015afb711b1e1a37f.png

    本教程操作环境:Windows7系统,Microsoft Office word2010版本,Dell G3电脑。

    在word的布局选项中纸张方向可以修改页面为横板还是竖版,但是选择之后发现整个文档所有纸张都会变成选择的方向,如果想要更改某一页的纸张方向应该如何操作呢?

    1. 例如,现在想要将下图的第二页转换为横板

    741ce77039226ba2654d44a2370d1282.png

    2. 首先将插入点移动到第二页的开头

    32bcf4673180b562f2972e8bd51f3544.png

    3. 在“布局”菜单中“分隔符”下选择“下一页”,插入后并看不出变化,但是实际上此分隔符将文档分割成了两部分

    ea3b22b25fdff738507221828932033c.png

    4. 这时选择横板纸张

    cb662dbf9afc2dd2a6c1550afe2e359a.png

    5. 可以看到第二页起之后的纸张都变为横板

    e43768ce3f195e1f104d7315e1d99cbd.png

    6. 如果仅想要第二页修改方向,那么在第三页重复之前的步骤,将第三页之后变更为竖版

    cb6c06f4273f0adb8cbf449b97de6695.png

    想要查阅更多相关文章,请访问PHP中文网!!

    展开全文
  • EASY spa单页面文档

    千次阅读 2020-07-01 14:32:59
    页面模板语法 在子页面首行增加标签即可开启模板引擎: {{# if(d.search.id==1){ }} aaa {{# }else{ }} bbb {{# } }} 用法与laytpl一致,边界符可以在setter.js中修改,d表示的是当前路由信息,例如访问 #/system...

    1.1.导入项目

    1. 下载项目后进行解压
    2. 使用IDEA、WebStorm、HBuilder等前端开发工具打开
    3. 打开index.html点击右上角浏览器图标运行:

    运行教程

    注意: 必须以http://的形式访问,而不是file://的形式访问。

    1.2.项目结构

    |-assets
    |     |-images            // 图片
    |     |-js
    |         |-main.js       // 入口js
    |     |-libs              // 第三方库,echarts(图表)、layui
    |     |-module            // layui扩展模块,版本更新只用替换此目录
    |         |-img               // 框架用到的图片
    |         |-admin.css         // 框架核心样式
    |         |-admin.js          // admin模块
    |         |-index.js          // index模块
    |         |-********          // 其他扩展模块,不一一列举
    |-components              // html子页面
    |-json              // 模拟数据
    |-index.html        // 主页面

    main.js为入口js,上手使用项目前最好先看看它的说明。

    1.3.index.html结构说明

    <html>
    <head>
        <link rel="stylesheet" href="assets/libs/layui/css/layui.css"/>
        <link rel="stylesheet" href="assets/module/admin.css"/>
    </head>
    <body class="layui-layout-body">
        <div class="layui-layout layui-layout-admin">
            <!-- 头部 -->
            <div class="layui-header">...</div>
            <!-- 侧边栏 -->
            <div class="layui-side">...</div>
            <!-- 主体部分 -->
            <div class="layui-body">...</div>
            <!-- 底部 -->
            <div class="layui-footer">...</div>
        </div>
    
        <script type="text/javascript" src="assets/libs/layui/layui.js"></script>
        <script type="text/javascript" src="assets/js/main.js"></script>
    </body>
    </html>

    index.html就是这样固定的结构,一般不需要修改,只用在components下写子页面即可。

     

    1.4.添加一个菜单

    1. 打开json/menus.json,在合适的位置添加一个菜单:
      {"name": "xx管理", "url": "#/xxx"}
    2. 在components下面新建一个xxx.html页面
    3. 运行index.html,查看效果

    3.1.6版本开始菜单支持更丰富的写法:

    [{
        "name": "xx管理",
        "url": "#/xxx"
        "show": false
    }, {
        "name": "百度",
        "url": "#/baidu",
        "iframe": "https://baidu.com"
    }, {
        "name": "layui",
        "url": "https://layui.com",
        "target": "_blank"
    }]
    • show    false表示只注册路由,不显示在侧边栏
    • iframe   表示用iframe打开一个标签
    • target   表示当url不受路由控制时在新窗口打开链接

    注意: url以"#/"开头才会受路由控制,实现局部加载。

     

    1.5.main.js说明

    layui.config({
        version: true,          // 版本号配置为true可解决页面缓存问题
        base: 'assets/module/'  // 配置layui扩展模块目录
    }).extend({  // 配置每个模块分别所在的目录
        notice: 'notice/notice',
        steps: 'steps/steps'
    }).use(['index', 'admin'], function () {
        var $ = layui.jquery;
        var index = layui.index;
        var admin = layui.admin;
    
        // 加载侧边栏
        admin.req('menus.json', function (res) {
            index.regRouter(res);  // 注册路由
            index.renderSide(res);  // 渲染侧边栏
            // 加载主页
            index.loadHome({
                url: '#/console/console',
                name: '<i class="layui-icon layui-icon-home"></i>'
            });
        });
    
    });
    • layui.config是告诉layui扩展模块所在目录
    • layui.extend是配置每个模块具体位置,像admin.js、index.js这些没有子目录的不用配置
    • version:true可解决模块js、html页面缓存的问题,也可以配置一个固定的版本号

    main.js的业务流程为先通过ajax加载菜单json,然后注册路由、渲染侧边栏、加载主页,至此框架即成功运行了。

    如果不是前后端分离的项目,base怎么配置加载模块都是404,建议这样配置:

    layui.config({
        base: getProjectUrl() + 'assets/module/'
    })
    
    /* 获取项目根路径 */
    function getProjectUrl() {
        var layuiDir = layui.cache.dir;
        if (!layuiDir) {
            var js = document.scripts, last = js.length - 1, src;
            for (var i = last; i > 0; i--) {
                if (js[i].readyState === 'interactive') {
                    src = js[i].src;
                    break;
                }
            }
            var jsPath = src || js[last].src;
            layuiDir = jsPath.substring(0, jsPath.lastIndexOf('/') + 1);
        }
        return layuiDir.substring(0, layuiDir.indexOf('assets'));
    }

    getProjectUrl()方法原理是获取layui.js的全路径,并截取assets之前的路径,所以layui需要在assets目录下面, assets上一层需要是项目根路径,或者根据你的目录结构合理修改getProjectUrl方法,比如assets改成static。

     

    1.6.setter模块

    setter模块主要是用于给index模块和admin模块提供配置,可根据自己需要进行更改。

    参数:

    配置名默认说明
    baseServer'json/'接口地址,admin.req方法会自动加
    tableName'easyweb-spa'前端缓存用的存储表名
    pageTabsfalse是否开启多标签
    cacheTabtrue是否记忆Tab
    openTabCtxMenutrue是否开启Tab右键菜单
    maxTabNum20最多打开多少个tab
    viewPath'components'视图位置
    viewSuffix'.html'视图后缀
    defaultTheme 默认主题
    reqPutToPosttruereq请求put方法变成post,delete变get,并自动加_method
    apiNoCachetrue配置为true后ajax请求json数据不会加版本号
    navArrow 侧边栏导航箭头,可选''(layui默认)、'arrow2'(箭头)、'arrow3'(加减号)
    closeFooterfalse是否关闭页脚
    tplOpen'{{'模板引擎边界符
    tplClose'}}'模板引擎边界符
    tabAutoRefreshfalse是否切换Tab自动刷新页面
    defaultLoading1默认的加载动画(只控制admin.showLoading的默认)

    方法:

    配置名默认
    getToken()获取token
    putToken(token)缓存token
    removeToken()清除token
    getUser()获取当前登录的用户信息
    putUser(user)缓存当前登录的用户信息
    getUserAuths()获取用户所有权限
    getAjaxHeaders(requestUrl)ajax请求的统一header
    ajaxSuccessBefore(res, requestUrl)ajax请求结束后的统一预处理
    routerNotFound(r)路由不存在处理

    setter模块里面的配置都是默认配置,如果在主题界面修改了配置会以主题界面操作的为主,主题界面的操作保存在本地缓存中, 清除浏览器缓存就会以setter模块里面配置的为主。

    table需要在setter.js最下面用table.set实现自动传递header和预处理:

    layui.define(['table'], function (exports) {
        var setter = {
        };
        /* table全局设置 */
        var token = setter.getToken();
        if (token && token.access_token) {
            layui.table.set({
                headers: {'Authorization': 'Bearer ' + token.access_token},
                parseData: function(res) {  // 利用parseData实现预处理
                    if(res.code == 401) {
                        setter.removeToken();
                        layui.layer.msg('登录过期', {icon: 2, anim: 6, time: 1500}, function () {
                            location.replace('components/template/login/login.html');
                        });
                    }
                    return res;
                }
            });
        }
        exports('setter', setter);
    });

    dataGrid和treeTable组件是支持参数配置使用admin.ajax的发送请求的。

    或者使用$.ajaxSetup统一处理:

    $.ajaxSetup({
        complete: function (xhr) {
            try {
                var res = JSON.parse(xhr.responseText);
                if (1131 === res.code || 1122 === res.code || 1120 === res.code) {  // 登录过期
                    setter.removeToken();
                    layui.layer.msg('登录过期', {icon: 2, anim: 6, time: 1500}, function () {
                        location.replace('components/template/login/login.html');
                    });
                }
            } catch (e) {
            }
        }
    });

    注意: layui更新到2.5.6后模块名不能使用config,所以config.js现在改成了setter.js,请注意修改

    // 老版本只用把前面两行的config改成setter就可以了
    layui.use(['setter'], function(){
        var config = layui.setter;  
    });
    /*
    layui.use(['config'], function(){
        var config = layui.config;  
    });
    */

     

    1.7.ID命名规范

    SPA单页面应用如果有重复的ID会出现问题,所有的页面都不能有重复的ID,因为是jQuery系的框架,id还是很常用的, 为了避免ID出现重复,强烈建议按照一定规范来命名。

    总体命名规则xxxXxxXxx

    • 第一个xxx   模块名,比如用户模块user
    • 第二个Xxx   功能描述,比如添加Add
    • 第三个Xxx   元素类型,比如按钮Btn

    例如页面是user.html,它的各个元素命名如下:

    按钮的命名

    <!-- 命名规则:xxxXxxBtn -->
    <button id="userAddBtn" class="layui-btn">添加</button>
    <button id="userEditBtn" class="layui-btn">修改</button>
    <button id="userDelBtn" class="layui-btn">删除</button>

    表格的命名

    <!-- 命名规则:xxxTable -->
    <table id="userTable" lay-filter=""userTable"></table>
    
    <!-- 表格上方搜索表单,命名规则:xxxTbSearchForm,id和lay-filter是非必须的 -->
    <form class="layui-form" id="userTbSearchForm" lay-filter="userTbSearchForm">
        <!-- 输入框部分省略... -->
        <!-- 搜索提交按钮命名规则:xxxTbSearch -->
        <button class="layui-btn" lay-filter="userTbSearch" lay-submit>搜索</button>
    </form>
    
    <!-- 表格操作列,命名规则:xxxTbBar -->
    <script type="text/html" id="userTbBar">
        <a class="layui-btn" lay-event="edit">修改</a>
        <a class="layui-btn" lay-event="del">删除</a>
    </script>
    
    <!-- 表格其他复杂列,例如switch状态开关等,命名规则:xxxTbXxx -->
    <script type="text/html" id="userTbState">
        <input type="checkbox" lay-filter="userTbStateCk" value="{{d.userId}}" lay-skin="switch"
               lay-text="正常|锁定" {{d.state==0?'checked':''}}/>
    </script>

    一个页面有多个表格的命名

    <!-- 命名规则:xxxXxxTable -->
    <!-- 例如这是一个用户订单记录表 -->
    <table id="userOrderTable" lay-filter=""userOrderTable"></table>
    
    <!-- 表格操作列,命名规则:xxxXxxTbBar -->
    <script type="text/html" id="userOrderTbBar">
        <a class="layui-btn" lay-event="edit">修改</a>
        <a class="layui-btn" lay-event="del">删除</a>
    </script>

    表单弹窗的命名

    <!-- 页面层弹窗命名规则:xxxEditDialog,非页面层可以忽略script -->
    <script type="text/html" id="userEditDialog">
        <!-- 表单命名规则:xxxEditForm -->
        <form id="userEditForm" lay-filter="userEditForm" class="layui-form model-form">
            <!-- 输入框部分省略... -->
            <!-- 提交按钮命名规则:xxxEditSubmit -->
            <button class="layui-btn" lay-filter="userEditSubmit" lay-submit>保存</button>
        </form>
    </script>

    页面其他弹窗的命名

    <!-- 例如这是一个查看详情弹窗 -->
    <!-- 页面层弹窗命名规则:xxxXxxDialog,非页面层可以忽略script -->
    <script type="text/html" id="userInfoDialog">
        <!-- 表单命名规则:xxxXxxForm -->
        <form id="userInfoForm" lay-filter="userInfoForm" class="layui-form model-form">
            <!-- 输入框部分省略... -->
            <!-- 提交按钮命名规则:xxxXxxSubmit -->
            <button class="layui-btn" lay-filter="userInfoSubmit" lay-submit>保存</button>
        </form>
    </script>

    表单里面的input建议少用id,只用name,取input的值通过监听表单提交来取,用input通过$('#xxxForm [name="xxx"]')来写。

    其他元素ID命名

    <!-- 命名规则:xxxXxxXxx,第一个xxx是模块名,第二个Xxx是功能描述,第三个Xxx是元素类型 -->
    
    <!-- 例如角色选择的下拉框 -->
    <select id="userRoleSel"></select>
    
    <!-- 例如备注的输入框 -->
    <input id="userCommentsEdt" />

    元素类型简写

    元素简写描述
    按钮类Btn<button>.layui-btn
    输入类的EdtEditText的简写,inputtextarea
    选择类的Sel下拉框、多选下拉框等
    表格Tableid="userTable"id="userOrderTable"
    表格附加组件Tbid="userTbBar"id="userOrderTbBar"
    弹窗Dialogid="userEditDialogid="userInfoDialog"
    表单Formid="userEditFormid="userInfoForm"
    表单提交按钮Submitid="userEditSubmit"id="userInfoSubmit"

    页面的命名

    <!-- 命名格式:xxxApp -->
    <div class="layui-fluid" id="userApp">
        <!-- 省略页面内容...... -->
    </div>

    以上规则只是规范,非必须要求

     

    1.8.子页面模板语法

    在子页面首行增加<tpl/>标签即可开启模板引擎:

    <tpl/>
    <style>
    </style>
    <div class="layui-fluid">
        {{# if(d.search.id==1){ }}
        <span>aaa</span>
        {{# }else{ }}
        <span>bbb</span>
        {{# } }}
    </div>
    <script>
    </script>

    用法与laytpl一致,边界符可以在setter.js中修改,d表示的是当前路由信息,例如访问 #/system/user/id=1/sex=男 它的路由信息为:

    {
        path: ["system", "user"],
        search: {id: 1, sex: "男"},
        href: "/system/user/id=1/sex=男",
        refresh: false
    }
    • path    路径数组
    • search   参数列表
    • refresh   如果是刷新触发的值为true

    也不一定只有d能用,比如获取layui版本号:{{layui.v}}

     

    2.1.批量注册路由

    index.regRouter([{
        name: '用户管理',
        url: '#/system/user'  // 路由关键字,必须要有#号
    }]);
    
    // 嵌入iframe网页形式
    index.regRouter([{
        name: '百度一下',
        url: '#/baidu',
        iframe: 'https://baidu.com'
    }]);
    
    // 格式化数据,可以处理后端返回的menu.json格式
    index.regRouter(res.data, function (d) {
        d.name = d.menuName;
        d.url = d.path;
        d.iframe = d.component;
        d.icon = d.menuIcon;
        d.show = !d.hide;
        d.subMenus = d.children;
        return d;
    });

    参数是一个数组,当你访问#/system/user时,就会打开一个“用户管理”标签页,“url”是路由关键字, 对应的页面地址是“components/system/user.html”,“components”和“.html”可以在setter模块中配置。

     

    2.2.加载默认主页

    index.loadHome({
        url: '#/console/console1',
        name: '<i class="layui-icon layui-icon-home"></i>',
        loadSetting: true
    });
    • url         必填,主页路径,必须要有#号
    • name       必填,Tab标题
    • iframe      非必填,嵌入iframe网页形式
    • loadSetting   非必填,是否恢复记忆的Tab

    只有调用了loadHome方法,路由模块才会真正开始工作。

     

    2.3.打开一个选项卡

    index.openNewTab({
        name: '用户管理', 
        url: '#/system/user'
    });
    
    // 也可以加参数
    index.openNewTab({
        name: '用户管理', 
        url: '#/system/user/id=1'
    });
    
    // 打开一个iframe标签
    index.openNewTab({
        name: '百度一下', 
        url: '#/baidu',
        iframe: 'https://baidu.com'
    });
    • name   选项卡的标题
    • url     路由关键字,必须要有#号
    • iframe  可选参数,打开一个iframe标签

    也可以使用<a href="#/system/user">XX</a>,这种写法必须保证“#/system/user”已经注册了路由,而“openNewTab()”会自动注册。

    注意:openNewTab方法只是注册临时路由,如果刷新页面,路由就会不存在了,

    如果想刷新页面也能使用,需要提前在main.js中的index.loadHome()方法之前注册路由, 或者在menus.json中配置,并且可以加show: false不在侧边栏中显示。

     

    2.4.关闭指定选项卡

    index.closeTab('#/system/user');
    index.closeTab('/system/user');
    index.closeTab('system/user');

    #/可写可不写,关闭当前tab可以用admin.closeThisTabs()或者ew-event="closeThisTabs"

     

    2.5.跳到指定选项卡

    index.go('#/system/user');
    index.go('/system/user');
    index.go('system/user');

    前面#/可写可不写。

     

    2.6.修改Tab标题

    index.setTabTitle('Hello');  // 修改当前Tab标题文字,也支持单标签模式
    
    index.setTabTitle('Hello', tabId);  // 修改指定Tab标题文字
    
    index.setTabTitleHtml('<span>Hello</span>');  // 修改整个标题栏的html,此方法只在单标签模式有效
    
    index.setTabTitle();  // 单标签模式隐藏标题栏

    关闭多标签会自动生成一个标题栏,可用此方法修改标题栏,参数为undefined为隐藏标题栏。

     

    2.7.获取hash路径

    index.getHashPath('#/system/user');
    
    index.getHashPath('#/system/user/id=1/name=aa');

    这两种hash最后返回的都是system/user,后面属于参数传递,不属于视图的路径。

     

    2.8.侧边栏手风琴折叠

    在layui-nav-tree上面增加lay-shrink="_all"配置即可展开菜单时收缩兄弟节点:

    <!-- 侧边栏 -->
    <div class="layui-side">
        <div class="layui-side-scroll">
            <ul class="layui-nav layui-nav-tree" lay-shrink="all">
                ......省略其他部分
            </ul>
        </div>
    </div>

    注意:是_all而不是all,在3.1.6版本之前是lay-accordion="true"。

     

    2.9.切换Tab自动刷新

    setter.js里面配置tabAutoRefresh: true即可开启。

     

    2.10.渲染侧边栏

    3.1.6版本开始在index模块封装了渲染侧边栏方法,不用自己写laytpl渲染:

    admin.req('menus.json', {}, function (res) {
        index.renderSide(res);  // 渲染侧边栏
    }, 'get');

    该方法还提供了灵活自定义操作,比如多系统模式,自定义要怎么插入渲染完的html:

    index.renderSide(res, $('#sideNav').html(), function(html, obj){
        // html 是渲染后的内容
        // obj.data 可获取处理后的数据,比如移除了show: false的数据
        // obj.side 是侧边栏的dom,例如$(obj.side + '>.layui-nav').html(html)
        // obj.render() 可更新nav的渲染
    }, '{{', '}}');
    • 参数一   必填,数据
    • 参数二   非必填,html模板
    • 参数三   非必填,hyml渲染完的自定义处理
    • 参数四   非必填,模板引擎边界符
    • 参数五   非必填,模板引擎边界符

    index.renderSide一般写在index.regRouter之后,index.regRouter还可以格式化数据 

     

    3.1.全部方法

    方法参数描述
    flexible(expand)true和false折叠/展开侧导航
    activeNav(url)a标签的href无#号设置侧导航栏选中
    refresh(url)url,可为空刷新指定Tab或当前Tab
    closeAllTabs()关闭所有选项卡
    closeOtherTabs(url)url关闭除url外所有选项卡
    closeThisTabs(url)url,可为空关闭url或当前选项卡
    rollPage(d)left、right、auto滚动选项卡tab
    changeTheme(theme,win,noCache,noChild) 切换主题
    lockScreen(url)见单独锁屏
    unlockScreen(isRemove)见单独解除锁屏
       
    iframeAuto()让当前的iframe弹层自适应高度
    closeThisDialog()关闭当前iframe弹窗
    closeDialog(elem)dom选择器关闭elem元素所在的页面层弹窗
    open(option)同layer打开弹窗
    popupRight(option)同layer打开右侧弹窗
    getLayerData(index,key)见弹窗专题获取弹窗传递数据
    putLayerData(key,value,index)见弹窗专题弹窗传递数据
    reloadLayer(index,url,success)见弹窗专题刷新url方式弹窗
    alert(content,options,yes)同layer封装layer.alert
    confirm(content,options,yes,cancel)同layer封装layer.confirm
    prompt(options,yes)同layer封装layer.prompt
    tips(options)见admin模块高级增强layer.tips
    modelForm(layero,btnFilter,formFilter)见弹窗专题把弹窗自带按钮跟表单绑定一起
    getLayerIndex('#elem')jq选择器获取页面层弹窗index
       
    req(url,data,success,method,option)见单独封装ajax
    ajax(option)同$.ajax封装ajax
       
    showLoading(elem,type,opacity,size)见单独显示加载动画
    removeLoading(elem,fade,del)见单独移除加载动画
    btnLoading(elem,text,loading)见单独设置按钮为加载状态
       
    putTempData(key,value,local)见单独缓存数据
    getTempData(key,local)见单独获取缓存数据
    putSetting(key,value) 修改配置信息
    recoverState() 恢复配置信息
    getPageHeight()获取浏览器高度
    getPageWidth()获取浏览器宽度
    chooseLocation(option)见admin模块高级地图选择位置
    cropImg(option)见admin模块高级裁剪图片
       
    strToWin(str) 字符的parent.parent转对象
    openSideAutoExpand()开启鼠标移入侧边栏自动展开
    openCellAutoExpand()开启鼠标移入单元格超出自动展开
       
    util.Convert_BD09_To_GCJ02(point)见admin模块高级百度地图坐标转高德地图坐标
    util.Convert_GCJ02_To_BD09(point)见admin模块高级高德地图坐标转百度地图坐标
    util.animateNum(elem,isThd,delay,grain)见admin模块高级动态数字
    util.deepClone(obj)见admin模块高级深度克隆对象
    util.fullTextIsEmpty(text)见admin模块高级判断富文本是否为空
    util.removeStyle(elem,options)见admin模块高级移除元素的style
    util.scrollTop(elem)见admin模块高级滚动到顶部
    util.tpl(html,data,openCode,closeCode)见admin模块高级模板解析
       
    hasPerm(auth)权限判断当前登录的用户是否有权限
    renderPerm()移除没有权限的dom元素

    使用示例:

    layui.use(['admin'], function () {
        var admin = layui.admin;
    
        var pageHeight = admin.getPageHeight();    // 获取浏览器高度
    });

     

    3.2.弹窗相关方法

    open和popupRight方法:

    // 打开弹窗
    admin.open({
        type: 2,
        content: 'tpl-theme.html'
    });
    
    // 打开右侧面板
    admin.popupRight({
        type: 2,
        content: 'tpl-theme.html'
    });

    这两个方法只是对layer.open进行了一层封装,参数和layer一样,查看layer文档

    新增参数url:

    admin.open({ 
        title: 'Hello',
        url: 'tpl-theme.html'
    });
    
    admin.popupRight({ 
        url: 'tpl-theme.html' 
    });

    type:2, content:xxx这种是iframe类型的弹窗,使用url会通过ajax加载页面到弹窗中,而不是iframe嵌入。 当使用url方式的时候,弹窗页面应该是代码片段,而不是完整的html,如下所示:

    <style>
    * { color: red; }
    </style>
    <div class="layui-form model-form">
        <button class="layui-btn" ew-event="closeDialog">关闭我</button>
    </div>
    <script>
        layui.use(['layer', 'form'], function () {
            var $ = layui.jquery;
        });
    </script>

    页面不需要html、body这些东西,并且可以直接用<script>标签来写事件。

    admin.iframeAuto()方法:

    针对type:2的弹窗自适应弹窗高度,写在弹窗的子页面中,此方法是调用一次做一次高度自适应, 如果你用js动态修改了弹窗子页面的高度,需要再调用一次。

    admin.closeThisDialog():

    关闭当前iframe类型弹窗,针对type:2的弹窗,在弹窗的子页面调用即可关闭当前的iframe弹窗。

    admin.closeDialog('#xxx'):

    关闭非iframe类型的弹窗,调用需要传递弹窗页面里面任意一个的元素。

    关闭弹窗还可以使用ew-event操作:

    <!-- 关闭弹窗(智能) -->
    <button ew-event="closeDialog"></button>
    <!-- 关闭iframe类型的弹窗 -->
    <button ew-event="closeIframeDialog"></button>
    <!-- 关闭页面层的弹窗 -->
    <button ew-event="closePageDialog"></button>

    使用url方式更符合单页面,admin模块还封装了弹窗参数传递等更多方法,请到弹窗专题查看。

     

    3.3.加载层loading

    按钮loading:

    admin.btnLoading('#btn1');   // 设置按钮为loading状态
    admin.btnLoading('#btn1', false);  // 移除按钮的loading状态
    
    admin.btnLoading('#btn1', '&nbsp;保存...');   // 设置按钮为loading状态,同时修改按钮文字

    页面加载层:

    admin.showLoading('#xxx');  // 在id为xxx的元素中显示加载层
    admin.showLoading('#xxx', 1, '.8');  // 显示type为1、透明度为0.8的遮罩层
    
    // 尺寸控制,提供有两种尺寸,默认是sm小型尺寸,还可以选md大型尺寸
    admin.showLoading({
        elem: '#xxx',
        type: 1,
        size: 'sm'
    });
    • 参数一 elem  非必填 元素选择器,不填为body
    • 参数二 type  非必填 动画类型(1 小球,2 魔方,3信号,4简约),默认1
    • 参数三 opacity非必填 透明度(0 - 1),默认不透明
    • 参数四 size  非必填  尺寸,默认sm

    移除加载动画:

    admin.removeLoading('#xxx');
    admin.removeLoading('#xxx', true, true);
    • 参数一  非必填 元素选择器,不填为body
    • 参数二  非必填 true是淡出效果,false直接隐藏,默认是true
    • 参数三  非必填 true是删除,false是隐藏不删除,默认是false

    页面载入的加载动画:

    <body class="page-no-scroll"> <!-- page-no-scroll这个不要忘了 -->
        <!-- 小球样式 -->
        <div class="page-loading">
            <div class="ball-loader">
                <span></span><span></span><span></span><span></span>
            </div>
        </div>
    
        <!-- 魔方样式 -->
        <div class="page-loading">
            <div class="rubik-loader"></div>
        </div>
    
        <!-- 信号样式 -->
        <div class="page-loading">
            <div class="signal-loader">
                <span></span><span></span><span></span><span></span>
            </div>
        </div>
    
        <!-- 简约样式 -->
        <div class="page-loading">
            <div class="layui-loader">
                <i class="layui-icon layui-icon-loading layui-anim layui-anim-rotate layui-anim-loop"></i>
            </div>
        </div>
    
        <!-- 加sm是小型尺寸 -->
        <div class="page-loading">
            <div class="signal-loader sm">
                <span></span><span></span><span></span><span></span>
            </div>
        </div>
    </body>

    写在页面中需要在js中调用admin.removeLoading()移除加载动画。

     

    3.4.ajax封装

    req方法:

    admin.req('url', {
        username: 'admin',
        password: '123456'
    }, function(res){
        alert(res.code + '-' + res.msg);
    }, 'get', { headers: {} });
    • 参数一   请求的url,前面会自动加setter.baseServer
    • 参数二   非必填,请求参数
    • 参数三   请求回调(网络错误也进此回调,404、403等)
    • 参数四   非必填,请求方式,get、post、put、delete等,默认get
    • 参数五   非必填,ajax的更多参数,如headers、dataType等

    req的这五个参数是自动像左补齐的,可以简写:

    // 无参数,get请求
    admin.req('url', function(res){
        console.log(res);
    });
    
    // post提交
    admin.req('url', function(res){
        console.log(res);
    }, 'post');
    
    admin.req('url', {
        username: 'xxx',
        password: '123456'
    }, function(res){
        console.log(res);
    }, 'post');
    
    // 参数使用JSON.stringify()会自动增加contentType为json
    admin.req('url', JSON.stringify(obj), function(res){
        console.log(res);
    }, 'post');
    
    // 相当于
    admin.req('url', JSON.stringify(obj), function(res){
        console.log(res);
    }, 'post', {
        contentType: 'application/json'
    });
    
    // 参数使用表单序列化
    admin.req('url', $('#demoForm').serialize(), function (res) {
        console.log(res);
    }, 'post', {
        contentType: 'application/x-www-form-urlencoded'
    });

    ajax方法,参数同$.ajax:

    admin.ajax({
        url: 'url',
        data: {},
        headers: {},
        type: 'post',
        dataType: 'json',
        success: function(res){
            alert(res.code + '-' + res.msg);
        }
    });

    自动传递header和预处理:

    module/setter.js(原config.js)中通过下面两个方法操作:

    var setter = {
        // 自动传递header
        getAjaxHeaders: function (url) {
            var headers = [];
            headers.push({name: 'token', value: 'xxxxx'});
            return headers;
        },
        // 请求完成后预处理
        ajaxSuccessBefore: function (res, url, obj) {
            if(res.code == 401) {
                alert('登录超时,请重新登录');
                // obj.reload();   // 重新发起请求
                // obj.update({});  // 修改res数据
                // obj.xhr  // ajax原始的xhr对象
                return false;  // 返回false阻止代码执行
            }
            return true;
        }
    };

    req和ajax都实现了自动传递header、预处理、网络错误也回调到success(404、500等错误)。

     

    3.5.缓存操作putTempData

    admin.putTempData('key', 'value');  // sessionStorage存储
    admin.putTempData('key');           // 不写value是删除
    admin.putTempData('key', 'value', true);  // localStorage存储
    admin.putTempData('key', true);           // 不写value是删除
    
    admin.getTempData('key');  // 获取sessionStorage存储的key
    admin.getTempData('key', true);  // 获取localStorage存储key
    
    admin.getTempData();  // 获取sessionStorage存储的全部数据
    admin.getTempData(true);  // 获取localStorage存储的全部数据

     

    3.6.锁屏功能

    admin.lockScreen(url);  // 锁屏,url是锁屏页面地址,不填为默认地址
    
    admin.unlockScreen();   // 解除锁屏(隐藏锁屏页面)
    
    admin.unlockScreen(true);   // 移除锁屏页面,下次锁屏需要重新加载页面

    如果是自定义锁屏页面,页面不要包含head、body这些东西,只是代码片段,参考默认的锁屏页面。

     

    3.7.ew-event事件绑定

    使用示例:

    <a ew-event="fullScreen">全屏</a>
    <a ew-event="flexible">折叠导航</a>
    事件描述
    flexible折叠侧导航
    refresh刷新主体部分
    closeThisTabs关闭当前选项卡
    closeOtherTabs关闭其他选项卡
    closeAllTabs关闭全部选项卡
    leftPage左滚动选项卡
    rightPage右滚动选项卡
      
    closeDialog关闭当前弹窗(智能)
    closeIframeDialog关闭当前iframe层弹窗
    closePageDialog关闭当前页面层弹窗
      
    theme打开主题设置弹窗
    note打开便签弹窗
    message打开消息弹窗
    psw打开修改密码弹窗
    logout退出登录
      
    fullScreen全屏切换
    back浏览器后退
    lockScreen锁屏
      
    open打开弹窗
    popupRight打开右侧弹窗

    ew-event属性可用于任何元素,不仅仅是a标签,theme、note等可以通过data-url属性配置对应的url, 还可以通过data-window="top"属性配置在父页面处理事件。

    <a ew-event="theme" data-url="xxx.html" data-window="parent">主题</a>

    自定义事件,添加下面代码即可,建议放在main.js中:

    admin.events.xxx = function(){
       layer.msg($(this).text());
    }
    <a ew-event="xxx">测试</a>

     

    3.8.open弹窗事件

    open和popupRight这两个事件是用来支持非js方式打开弹窗:

    <button ew-event="open" data-type="2" data-content="http://baidu.com">iframe弹窗</button>
    
    <button ew-event="open" data-type="1" data-url="form.html">页面弹窗</button>
    
    <button ew-event="open" data-type="1" data-content="#userForm">页面弹窗</button>
    <form id="userForm">......省略</form>
    
    <!-- 设置area和offset -->
    <button ew-event="open" data-type="1" data-content="Hello" data-area="80px,60px" data-offset="10px,10px">页面弹窗</button>
    
    <!-- popupRight一样的用法 -->
    <button ew-event="popupRight" data-type="2" data-url="http://baidu.com" data-title="百度一下,你就知道">右侧弹窗</button>
    
    <!-- function类型参数写法,success、end等 -->
    <button ew-event="open" data-type="1" data-content="Hello" data-success="onDialogSuccess">页面弹窗</button>
    <script>
        layui.use(['layer'], function(){
            var layer = layui.layer;
    
            // 方法需要加window
            window.onDialogSuccess = function(){
                layer.msg('弹窗被成功打开了');    
            };
        });
    </script>
    
    <!-- 加data-window="top"相当于top.layui.admin.open -->
    <button ew-event="open" data-type="2" data-content="http://baidu.com" data-window="top">iframe弹窗</button>

    layer支持的参数大部分都可以通过data属性来设置,数组类型用逗号分隔,function类型需要把作用域放在window对象下, 也可以直接写js比如data-success="layer.msg('打开了弹窗')"

     

    3.9.logout事件

    <a ew-event="logout" 
        data-url="login.html" 
        data-ajax="api/logout"
        data-method="post"
        data-code="200"
        data-parse-data="return {code: res.status, msg: res.message}"
        data-confirm="false">退出登录</a>
    • data-url        必填 退出登录后跳转的页面地址
    • data-ajax     非必填 退出登录需要请求的ajax接口
    • data-method      非必填 ajax请求方式,默认是delete
    • data-code     非必填 ajax返回成功的状态码,默认是0
    • data-parse-data  非必填 处理接口返回的数据
    • data-confirm    非必填 是否显示询问框,false表示直接退出不询问,默认true

     

    3.10.判断权限hasPerm

    通过admin.hasPerm(auth)可以控制按钮级别的权限隐藏:

    if(!admin.hasPerm('user:add')) {
        $('#btnUserAdd').remove();
    }
    • hasPerm方法需要通过setter.getUserAuths方法来获取全部权限
    • setter.getUserAuths是通过setter.getUser方法从用户信息中获取权限的
    • setter.getUser是从本地缓存中获取用户信息的,setter.putUser把用户信息放入缓存中

    在main.js中有获取用户信息并通过setter.putUser放入缓存中的写法。

    还可以通过加属性的方式来隐藏:

    <button perm-show="user:add">添加</button>

    perm-show可以用于任意元素,对于动态添加的元素调用admin.renderPerm()来更新渲染,比如表格应该写在done回调里面:

    table.render({
        elem: '#userTable',
        url: '../../json/user.json',
        toolbar: ['<div>',
            '<button perm-show="user:add" lay-event="add" class="layui-btn">添加</button>',
            '<button perm-show="user:del" lay-event="del" class="layui-btn">删除</button>',
            '</div>'].join(''),
        cols: [[
            {type: 'numbers'},
            {field: 'username', title: '账号', sort: true},
            {field: 'nickName', title: '用户名', sort: true},
            {title: '操作', toolbar: '#userTbBar', align: 'center', minWidth: 200}
        ]],
        done: function() {
            admin.renderPerm();
        }
    });

     

    4.1.文字提示

    鼠标滑过弹出tips,使用示例:

    <button lay-tips="大家好!">按钮</button>
    
    <button lay-tips="大家好!" lay-direction="2" lay-bg="#009788">按钮</button>
    
    <button lay-tips="大家好!" lay-offset="10px" lay-bgImg="linear-gradient(to right,#8510FF,#D025C2,#FF8B2D,#F64E2C)">按钮</button>
    
    <button lay-tips="大家好!" lay-offset="-10px,-10px" lay-padding="5px">按钮</button>
    • lay-direction: 设置位置,1上面(默认)、2右边、3下面、4左边
    • lay-bg: 设置背景颜色(包含箭头颜色,下面的背景图片不包含箭头)
    • lay-offset: 设置偏移距离,(上,左)
    • lay-padding:内间距
    • lay-color:文字颜色
    • lay-bgImg:背景图片,例如lay-bgImg="url(assets/images/head.jpg)"
    • lay-fontSize:字体大小

    除了elem和text其他都是可选参数,还可以使用admin.tips()直接调用:

    admin.tips({
        elem: '#btn', text: 'Hello', direction: 3, bg: '#803ed9',
        offset: '-10px,-10px', padding: '15px', color: '#eee',
        bgImg: 'linear-gradient(to right,#8510FF,#D025C2,#FF8B2D,#F64E2C)',
        fontSize: '18px', tipsMore: true, time: -1
    });

     

    4.2.地图选择位置

    admin.chooseLocation({
        needCity: true,
        onSelect: function (res) {
            layer.msg(JSON.stringify(res), {icon: 1});
        }
    });
    参数默认描述
    title"选择位置"弹窗标题
    needCityfalse是否返回行政区,省市区默认不返回
    center定位当前城市地图默认的中心点
    defaultZoom11地图默认缩放级别
    pointZoom17选中时地图的缩放级别
    keywordspoi检索关键字,例如:建筑、写字楼
    pageSize30poi检索最大数量
    onSelect选择回调
    mapJsUrl内置高德地图js的url
    • 地图默认中心点参考值:[116.397428, 39.90923],经度,纬度
    • 地图url参考值:https://webapi.amap.com/maps?v=1.4.14&key=xxxxxxx
    • 返回结果说明:
      • res.name; // 地点名称
      • res.address; // 详细地址
      • res.lat; // 纬度
      • res.lng; // 经度
      • res.city; // 城市,是一个对象
      • res.city.province; // 省
      • res.city.city; // 市
      • res.city.district; // 区
      • res.city.citycode; // 城市代码

    地图相关参数的详细介绍请前往高德地图API查看。

     

    4.3.裁剪图片

    admin.cropImg({
        aspectRatio: 1/1,
        imgSrc: '../../assets/images/15367146917869444.jpg',
        onCrop: function (res) {
            // 返回的res是base64编码的裁剪后的图片
            layer.msg('<img src="' + res + '" width="220px" height="220px"/>');
        }
    });
    参数默认描述
    title"裁剪图片"弹窗标题
    aspectRatio1/1裁剪比例,例如:16/9
    imgSrc要裁剪的图片,无则先弹出选择图片
    imgType'image/jpeg'裁剪的图片类型,非必填
    onCrop裁剪完成回调
    limitSize不限制限制选择的图片大小
    acceptMime'image/*'限制选择的图片类型
    exts不限制限制选择的图片后缀
    • acceptMime参考值:'image/jpg, image/png'(只显示 jpg 和 png 文件)
    • exts参考值:jpg|png|gif|bmp|jpeg

    后面三个参数配置可参考upload模块, 如果想单独在页面中使用图片裁剪功能请参考Cropper插件文档

     

    4.2.动画数字

    <h2 id="demoAnimNum1">12345</h2>
    <h2 id="demoAnimNum2">¥2373467.342353</h2>
    <h2 id="demoAnimNum3">上浮99.98%</h2>
    
    <script>
    layui.use(['admin'], function () {
        var $ = layui.jquery;
        var admin = layui.admin;
    
        admin.util.animateNum('#demoAnimNum1');
        admin.util.animateNum('#demoAnimNum2');
        admin.util.animateNum('#demoAnimNum3', true, 500, 100);
    });
    </script>
    • 参数一   需要动画的元素
    • 参数二   是否开启千分位,开启后每进千加逗号分隔
    • 参数三   动画间隔,默认500
    • 参数四   动画粒度,默认100

    此方法会智能过滤除数字外的字符,如果动态了修改了数字应该加$('#xx').data('num', '');重置一下。

     

    4.3.经纬度转换

    快速使用:

    // GCJ02转BD09
    var point = admin.util.Convert_GCJ02_To_BD09({lat: 30.505674, lng: 114.40043});
    console.log(point.lng + ',' + point.lat);
    
    // BD09转GCJ02
    var point = admin.util.Convert_BD09_To_GCJ02({lat: 30.512004, lng: 114.405701});
    console.log(point.lng + ',' + point.lat);
    • 高德地图、腾讯地图以及谷歌中国区地图使用的是GCJ-02坐标系
    • 百度地图使用的是BD-09坐标系

    不同的坐标系之间会有几十到几百米的偏移,所以在开发基于地图的产品时,可以通过此方法修正不同坐标系之间的偏差, 详细了解国内各坐标系

     

    4.4.深度克隆对象

    var o1 = {name: 'xxx', role: ['admin', 'user']};
    
    var o2 = admin.util.deepClone(o1);

    对象型在参数传递时通常是引用传递,有时需要把对象克隆一份再传递,避免传递的参数被修改导致第二次传递出现问题。

     

    4.5.判断富文本是否为空

    admin.util.fullTextIsEmpty('<p><span>哈哈</span><img src="xxx.jpg"/>');

    判断规则,有文字,有img、audio、video、iframe等标签都属于不为空。

     

    4.6.移除指定style

    <div style="color: red;background-color: green;">Hello</div>

    像上面这样有多个内联样式style,如何只移除其中一个或多个呢:

    admin.util.removeStyle('background-color');
    
    admin.util.removeStyle(['background-color', 'color']);

     

    4.7.模板引擎

    var html = admin.util.tpl('<p>{{d.name}}</p>', {name: 'xxx'}, '{{', '}}');
    • 参数一   模板内容
    • 参数二   填充数据
    • 参数三   非必填,边界符,默认{{
    • 参数四   非必填,边界符,默认}}

    它与laytpl使用方式一致,并且解决了laytpl对js注释支持不友好,laytpl模板中有js注释会导致最后渲染的内容有问题。

    加载独立页面:

    <div id="demo1"></div>
    <script>
        layui.use(['layer', 'admin'], function () {
            var $ = layui.jquery;
            var admin = layui.admin;
    
            admin.ajax({
                url: 'xxx.html', dataType: 'html', success: function (html) {
                    $('#demo1').html(admin.util.tpl(html, {name: 'xxx'}));
                }
            });
    
        });
    </script>

    独立页面xxx.html

    <div>{{name}}</div>
    <script>
        layui.use(['layer'], function () {
            // 我可以加注释哦,laytpl不可以哦
            layui.layer.msg('Hello 我被加载了');
        });
    </script>

     

    4.8.滚动到顶部

    admin.util.scrollTop();  // 主体部分滚动到顶部
    
    admin.util.scrollTop('html,body');  // 自定义元素滚动到顶部
    
    admin.util.scrollTop('#xxDiv');  // 自定义元素滚动到顶部

    由于spa版本多标签和单标签的滚动条所在元素都不一样,而且也不在body上, 所以封装了scrollTop方法可自动判断主体部分滚动条所在的元素。

     

    4.9.事件监听

    监听侧边栏折叠/展开:

    admin.on('flexible', function (d) {
        setTimeout(function () {
            myCharts1.resize();
        }, 360);
    });

    一般用于更新echarts尺寸等,要延迟360毫秒再更新,因为折叠展开有个过渡效果。

    监听页面被卸载:

    admin.on('destroy(plugin/other/editor)', function () {
        tinymce.get('demoEditor').destroy(false);
    });

    括号里面是页面的路径地址,没有#号,可用于销毁定时器、组件等。

    监听页面进入前台:

    layui.admin.on('show(console/console)', function () {
        myCharts1.resize();
    });

    括号里面是页面的路径地址,没有#号,一般用于更新echarts尺寸等,比如打开了两个标签页, 缩放屏幕大小再进入另一个标签页,echarts尺寸不会自动变化,可以监听页面进入前台并更新尺寸。

    其他事件监听:

    /* 监听tab切换事件 */
    admin.on('tab', function (d) {
        // d.layId表示当前tab的url
    });
    
    // 监听tab关闭事件
    admin.on('tabDelete', function (d) {
        // d.layId表示当前tab的url
    });
    
    /* 监听多系统切换事件 */
    admin.on('nav', function (d) {
        // d.navId表示当前多系统的navId
    });

    实现刷新页面记忆折叠状态,在main.js增加:

    admin.on('flexible', function (d) {
        admin.putTempData('nav-expand', d.expand);
    });
    
    var expand = admin.getTempData('nav-expand');
    if (expand !== undefined) admin.flexible(expand);

     

    4.10.动态模板

    直接赋值数据:

    <script type="text/html" ew-tpl="['a','b','c']" data-done="layui.form.render()">
        <div>
        {{# layui.each(d,function(i,item){ }}
        <div>{{item}}</div>
        {{# }); }}
        </div>
    </script>
    <!-- 也可以引用变量 -->
    <script id="userListTpl" type="text/html" ew-tpl="userList">
        <div>
        {{# if(d){ }} <!-- 这里判断以下因为可能值还没定义 -->
            {{# layui.each(d,function(i,item){ }}
            <div>{{item}}</div>
            {{# }); }}
        {{# } }}
        </div>
    </script>
    <script>
        layui.use(['admin'], function() {
            window.userList = ['a', 'b', 'c'];
            // admin模块一加载会自动渲染,但userList还未定义,所以定义完要重新渲染
            admin.renderTpl('#userListTpl');
        });
    </script>

    使用远程数据,注意要加引号'user.json'

    <script type="text/html" ew-tpl="'user.json'" data-method="post" 
        data-where="{sex:'女'}" data-headers="{token: 'xxx'}">
        <div>
        {{# layui.each(d.data,function(i,item){ }}
        <div>{{item.username}}</div>
        {{# }); }}
        </div>
    </script>

    通过ew-tpl来表示这是一个动态模板以及设置数据源,通过data-xxx配置其他参数:

    • done   渲染完成后的回调
    • url   远程数据的url
    • method   远程数据的请求方式
    • where   远程数据的请求条件,也可以data-where="JSON.stringify({})"
    • headers   远程数据的请求header
    • content-type   如data-content-type="application/json;charset=UTF-8"

    注意远程数据url一定要加引号,加引号的好处你还可以这样使用:

    ew-tpl=" layui.setter.baseServer + '/user.json' "

    动态模板会在页面加载后自动渲染,如果要重新渲染:

    admin.renderTpl('#userListTpl');  // 参数为模板的jquery选择器

    使用例子,比如用户管理的搜索里面的性别下拉换成动态的:

    <!-- 表格工具栏 -->
    <form class="layui-form toolbar">
        <div class="layui-form-item">
            <div class="layui-inline">
                <label class="layui-form-label">性&emsp;别:</label>
                <script type="text/html" ew-tpl="'../../json/sex.json'" data-done="layui.form.render('select');">
                                    <div class="layui-input-inline">
                                           <select name="sex">
                                                 <option value="">选择性别</option>
                                                 {{# layui.each(d.data,function(i,item){ }}
                                                 <option value="{{item.value}}">{{item.name}}</option>
                                                 {{# }); }}
                                           </select>
                                    </div>
                              </script>
            </div>
        </div>
    </form>
    <!-- 数据表格 -->
    <table id="userTable" lay-filter="userTable"></table>

    sex.json数据:

    {"code": 200, "data": [{"name": "男", "value": 0}, {"name": "女", "value": 1}]}

    注意这里有个小细节,select上面还有一个div,对于select的动态模板,建议select外面最好多一层,因为select会被layui美化, 外面不加一层当重新渲染模板的时候不能把layui美化的旧的select移除,另外ew-tpl="'sex.json'"这里先是双引号再是单引号,不要漏掉了。

     

     

    5.1.公共类

    类名(class)说明
    pull-left左浮动
    pull-right右浮动
    text-left内容居左
    text-center内容居中
    text-right内容居右
    inline-block设置display为inline-block
    bg-white设置背景为白色
    layui-link设置a标签颜色为主题色
    layui-text.layui-text下面的a标签为蓝色
      
    text-muted文字颜色为灰色
    text-success文字颜色为绿色,成功色
    text-warning文字颜色为黄色警告色
    text-danger文字颜色为红色危险色
    text-info文字颜色为蓝色信息色
    text-primary文字颜色为主题色

    以上是easyweb增加的公共类,当然也可以使用Layui公共类

     

    5.2.组件样式

    类名(class)说明
    icon-btn带图标的按钮,会缩小边距
    icon-date在元素的右边加入日期的图标
    icon-search在元素的右边加入搜索的图标
    btn-circle圆形按钮,参见便签界面
      
    arrow2设置侧边栏小三角为箭头图标,加在layui-nav上
    arrow3设置侧边栏小三角为加减号图标,加在layui-nav上
      
    close-footer关闭页脚,加在body上
    hide-body-title全局隐藏单标签模式标题栏,加在body上
      
    table-tool-mini数据表格工具栏mini样式,加在table父元素上
    full-table针对full-xxx的table的工具栏mini样式
      
    mini-bar如果有滚动条,使用细的风格
    layui-form-select-top控制下拉框上弹出,加载select父元素上
    ew-tb-cell-ck数据表格里面checkbox
    ew-field-groupeasyweb的字段集辅助类
    <!-- 图标按钮 -->
    <button class="layui-btn icon-btn"><i class="layui-icon">&#xe615;</i>搜索</button>
    
    <!-- 日期图标 -->
    <input class="layui-input icon-date" type="text"/>
    <!-- 搜索图标 -->
    <input class="layui-input icon-search" type="text"/>
    
    <!-- 圆形按钮 -->
    <div class="btn-circle">
        <i class="layui-icon layui-icon-add-1"></i>
    </div>
    
    <!-- 下拉框上弹出 -->
    <div class="layui-form-select-top">
        <select>....</select>
    </div>
    
    <!-- 关闭页脚 -->
    <body class="layui-layout-body close-footer">
    
    <!-- 表格工具栏mini样式 -->
    <div class="table-tool-mini full-table">
        <table id="xxTable" lay-filter="xxTable"></table>
    </div>
    
    <!-- 字段集嵌套数据表格 -->
    <div class="ew-field-group">
        <fieldset class="layui-elem-field">
            <legend>我是标题</legend>
        </fieldset>
        <div class="ew-field-box">
            <table id="demoFieldTb" lay-filter="demoFieldTb"></table>
        </div>
    </div>

      

     

    5.3.表单弹窗

    类名(class)说明
    model-form调整弹窗内的表单的间距使之更好看
    model-form-body表单内容部分,高度自适应,超过屏幕高度显示滚动条
    model-form-footer表单底部按钮部分,用于固定底部按钮
    layui-form-required表单必填项加红色星号

    表单弹窗示例:

    <script type="text/html" id="modelUser">
        <form id="modelUserForm" lay-filter="modelUserForm" class="layui-form model-form">
            <input name="userId" type="hidden"/>
            <div class="layui-form-item">
                <label class="layui-form-label layui-form-required">账号</label>
                <div class="layui-input-block">
                    <input name="username" placeholder="请输入账号" class="layui-input"/>
                </div>
            </div>
            <div class="layui-form-item text-right">
                <button class="layui-btn layui-btn-primary" type="button" ew-event="closePageDialog">取消</button>
                <button class="layui-btn" lay-filter="modelSubmitUser" lay-submit>保存</button>
            </div>
        </form>
    </script>
    <script>
        layui.use(['admin'],function(){
            var admin = layui.admin;
    
            admin.open({
                type: 1,
                title: '添加用户',
                content: $('#modelUser').html(),
                success: function (layero, dIndex) {
                    // 表单的操作,事件绑定等都写在success回调里面
                }
            });
        });
    </script>

    固定底部操作按钮示例:

    <script type="text/html" id="modelUser">
        <form class="layui-form model-form no-padding" id="modelUserForm" lay-filter="modelUserForm">
            <div class="model-form-body" style="max-height: 320px;"> <!-- 如果要超出屏幕才固定底部,不要写max-height -->
                <div class="layui-form-item">
                    <label class="layui-form-label">实习公司</label>
                    <div class="layui-input-block">
                        <input name="companyName" class="layui-input"/>
                    </div>
                </div>
                <!-- ......省略 -->
            </div>
            <div class="layui-form-item text-right model-form-footer">
                <button class="layui-btn layui-btn-primary" type="button" ew-event="closePageDialog">取消</button>
                <button class="layui-btn" lay-filter="modelSubmitUser" lay-submit>保存</button>
            </div>
        </form>
    </script>

    固定底部按钮需要model-form-body和model-form-footer,普通表单弹窗只需要model-form

     

    5.4.表格工具栏

    类名(class)说明
    toolbar调整表格上面的表单间距使之更好看
    w-auto设置width:auto,用于重置一些有固定宽度表单元素
    mr0设置margin-right:0,用于重置一些表单元素的样式
      
    form-search-show-expand点击了展开才显示出来
    form-search-expand表格搜索栏展开\折叠按钮默认样式
    <!-- 表格顶部工具栏区域 -->
    <div class="layui-form toolbar">
        <div class="layui-form-item">
            <div class="layui-inline">
                <label class="layui-form-label w-auto">账&emsp;号:</label>
                <div class="layui-input-inline mr0">
                    <input name="username" class="layui-input" type="text" placeholder="输入账号"/>
                </div>
            </div>
            <!-- 加了form-search-show-expand类在展开的时候才显示 -->
            <div class="layui-inline form-search-show-expand">
                <label class="layui-form-label w-auto">用户名:</label>
                <div class="layui-input-inline mr0">
                    <input name="nickName" class="layui-input" type="text" placeholder="输入用户名"/>
                </div>
            </div>
            <div class="layui-inline">
                <button class="layui-btn icon-btn" lay-filter="formSubSearchUser" lay-submit>
                    <i class="layui-icon">&#xe615;</i>搜索
                </button>
                <!-- 添加这个按钮可展开/折叠表单 -->
                <a class="layui-btn form-search-expand" search-expand>
                    展开 <i class="layui-icon layui-icon-down"></i>
                </a>
            </div>
        </div>
    </div>
    
    <!-- 表格 -->
    <table id="tableUser" lay-filter="tableUser"></table>

    移动端自动适配效果:

    表格搜索折叠/展开事件监听:

    <!-- 直接写js -->
    <a class="layui-btn" search-expand="d.expand?layer.msg('展开了'):layer.msg('折叠了')">
        展开 <i class="layui-icon layui-icon-down"></i>
    </a>
    
    <!-- 调用方法 -->
    <a class="layui-btn" search-expand="onExpandChange(d)"></a>
    <script>
        layui.use(['layer'], function () {
           window.onExpandChange = function(d){
               console.log(d);  // d包含d.expand,d.elem
           }
        });
    </script>

     

    5.5.垂直选项卡

    只需要在layui-tab的基础上多加一个layui-tab-vertical类即可实现:

    <div class="layui-tab layui-tab-vertical">
        <ul class="layui-tab-title">
            <li class="layui-this">系统管理</li>
            <li>用户管理</li>
            <li>权限分配</li>
        </ul>
        <div class="layui-tab-content">
            <div class="layui-tab-item layui-show">内容1</div>
            <div class="layui-tab-item">内容2</div>
            <div class="layui-tab-item">内容3</div>
        </div>
    </div>

    如果要修改选项卡标题的宽度:

    <!-- title和content两处地方都需要修改 -->
    <div class="layui-tab layui-tab-vertical">
        <ul class="layui-tab-title" style="width: 200px;">......省略</ul>
        <div class="layui-tab-content" style="margin-left: 200px;">......省略</div>
    </div>

    如果要选项卡的标题在右侧,再多加一个layui-tab-vertical-right类即可:

    <div class="layui-tab layui-tab-vertical layui-tab-vertical-right">
        <ul class="layui-tab-title" style="width: 200px;">......省略</ul>
        <div class="layui-tab-content" style="margin-right: 200px;">......省略</div>
    </div>

    选项卡的灰色分隔线的高度是标题区域的高度,如果当内容高度高于标题区域高度时想要分隔线的高度最大:

    <!-- 多加一个`layui-tab-vertical-full`类就可以了 -->
    <div class="layui-tab layui-tab-vertical layui-tab-vertical-full">
        <ul class="layui-tab-title">......省略</ul>
        <div class="layui-tab-content">......省略</div>
    </div>

    垂直选项卡中使用栅格布局样式错位,在layui-row上加一些样式:

    <div class="layui-tab layui-tab-vertical">
        <ul class="layui-tab-title">
            <li class="layui-this">系统管理</li>
            <li>用户管理</li>
        </ul>
        <div class="layui-tab-content">
            <div class="layui-tab-item layui-show">内容1</div>
            <div class="layui-tab-item">
                <div class="layui-row" style="float: left;width: 100%;">
                    <div class="layui-col-md6">
                        内容2
                    </div>
                    <div class="layui-col-md6">
                        内容使用栅格
                    </div>
                </div>
            </div>
        </div>
    </div>

     

    5.6.徽章扩展

    <span class="layui-badge layui-badge-green">绿色</span>
    <span class="layui-badge layui-badge-blue">蓝色</span>
    <span class="layui-badge layui-badge-red">红色</span>
    <span class="layui-badge layui-badge-yellow">黄色</span>
    <span class="layui-badge layui-badge-gray">灰色</span>

    layui-badge-list包裹,会有更好的间距和尺寸:

    <div class="layui-badge-list">
        <span class="layui-badge layui-badge-gray">很有想法的</span>
        <span class="layui-badge layui-badge-gray">专注设计</span>
        <span class="layui-badge layui-badge-gray">辣~</span>
        <span class="layui-badge layui-badge-gray">大长腿</span>
        <span class="layui-badge layui-badge-gray">川妹子</span>
        <span class="layui-badge layui-badge-gray">海纳百川</span>
    </div>

     

    5.7.下拉树单选

    <div id="demoSel" class="ew-xmselect-tree"></div>

    xmSelect下拉单选树增加一个ew-xmselect-tree可以有更好的样式。

     

    5.8.fixed方式select

    只需要在select的父元素上面增加class ew-select-fixed 即可:

    <div style="height: 80px;overflow: auto;" onscroll="layui.admin.hideFixedEl();">
        <div class="ew-select-fixed">
            <select name="ptTypeId">
                <option value="">请选择</option>
                <option value="1">选项一</option>
                <option value="2">选项二</option>
            </select>
        </div>
    </div>

    fixed定位的select用在数据表格中不需要对表格做任何修改就可以显示出来,还可以用在带有滚动表的容器中,比如一个很长的表单弹窗, 一定高度后显示滚动条,里面select是无法越出滚动条容器显示的,使用fixed方式的select即可超出容器的滚动条显示, 使用了fixed定位后外层容器滚动select不会跟随滚动,可在容器上添加滚动时收起select。

     

    6.1.1.快速使用

    <!-- click模式触发 -->
    <div class="dropdown-menu">
        <button class="layui-btn icon-btn">&nbsp;Click me <i class="layui-icon layui-icon-drop"></i>
        </button>
        <ul class="dropdown-menu-nav">
            <li><a>1st menu item</a></li>
            <li><a>2nd menu item</a></li>
            <li><a>3rd menu item</a></li>
        </ul>
    </div>
    <!-- hover模式触发,增加dropdown-hover即可 -->
    <div class="dropdown-menu dropdown-hover">
        <button class="layui-btn icon-btn">&nbsp;Hover me <i class="layui-icon layui-icon-drop"></i></button>
        <ul class="dropdown-menu-nav">
            <li><a>1st menu item</a></li>
            <li><a>2nd menu item</a></li>
            <li><a>3rd menu item</a></li>
        </ul>
    </div>
    <script>
        layui.use(['dropdown'], function () {
            var dropdown = layui.dropdown;  // 加载模块
        });
    </script>

     

    6.1.2.更多样式

    <!-- 标题及禁用样式 -->
    <div class="dropdown-menu dropdown-hover">
        <button class="layui-btn icon-btn">&nbsp;更多样式 <i class="layui-icon layui-icon-drop"></i></button>
        <ul class="dropdown-menu-nav">
            <li class="title">HEADER</li>
            <li><a><i class="layui-icon layui-icon-star-fill"></i>1st menu item</a></li>
            <li class="disabled"><a><i class="layui-icon layui-icon-template-1"></i>2nd menu item</a></li>
            <hr>
            <li class="title">HEADER</li>
            <li><a><i class="layui-icon layui-icon-set-fill"></i>3rd menu item</a></li>
        </ul>
    </div>
    
    <!-- 带小三角样式 -->
    <div class="dropdown-menu dropdown-hover">
        <button class="layui-btn icon-btn">&nbsp;带小三角 <i class="layui-icon layui-icon-drop"></i>
        </button>
        <ul class="dropdown-menu-nav">
            <div class="dropdown-anchor"></div><!-- 多加一个这个即可 -->
            <li><a>1st menu item</a></li>
            <li><a>2nd menu item</a></li>
            <li><a>3rd menu item</a></li>
        </ul>
    </div>
    
    <!-- 暗色主题 -->
    <div class="dropdown-menu">
        <button class="layui-btn layui-btn-normal icon-btn">&nbsp;暗色主题 <i class="layui-icon layui-icon-drop"></i></button>
        <ul class="dropdown-menu-nav dark"><!-- 加一个dark即可 -->
            <div class="dropdown-anchor"></div>
            <li class="title">HEADER</li>
            <li><a><i class="layui-icon layui-icon-star-fill"></i>1st menu item</a></li>
            <li class="disabled"><a><i class="layui-icon layui-icon-template-1"></i>2nd menu item</a></li>
            <hr>
            <li class="title">HEADER</li>
            <li><a><i class="layui-icon layui-icon-set-fill"></i>3rd menu item</a></li>
        </ul>
    </div>

     

    6.1.3.对任意元素使用

    <div class="dropdown-menu dropdown-hover">
        <input type="text" placeholder="一个会跳舞的输入框" class="layui-input"/>
        <ul class="dropdown-menu-nav">
            <li class="title">是不是在找</li>
            <li><a>另一个会跳舞的下拉框</a></li>
            <li><a>一杯忧郁的可乐</a></li>
        </ul>
    </div>

     

    6.1.4.带遮罩层

    遮罩层是分离式的绑定,通过data-dropdown绑定:

    <button class="layui-btn layui-btn-normal icon-btn" data-dropdown="#dropdown1">
       带遮罩层 <i class="layui-icon layui-icon-drop"></i>
    </button>
    
    <!-- 下拉菜单 -->
    <ul class="dropdown-menu-nav dropdown-bottom-right layui-hide" id="dropdown1">
        <div class="dropdown-anchor"></div>
        <li class="title">HEADER</li>
        <li><a><i class="layui-icon layui-icon-star-fill"></i>1st menu item</a></li>
        <li class="disabled"><a><i class="layui-icon layui-icon-template-1"></i>2nd menu item</a></li>
        <hr>
        <li class="title">HEADER</li>
        <li><a><i class="layui-icon layui-icon-set-fill"></i>3rd menu item</a></li>
    </ul>

     

    6.1.5.自定义下拉内容

    <div class="dropdown-menu">
        <button class="layui-btn layui-btn-normal icon-btn">&nbsp;克隆/下载 <i class="layui-icon layui-icon-drop"></i></button>
        <div class="dropdown-menu-nav dropdown-bottom-right" style="width: 280px;padding: 0 10px 10px 10px;">
            <div class="dropdown-anchor"></div>
            <!-- 下面是自定义内容 -->
            <div class="layui-tab layui-tab-brief">
                <ul class="layui-tab-title">
                    <li class="layui-this">HTTPS</li>
                    <li>SSH</li>
                </ul>
                <div class="layui-tab-content" style="padding: 10px 0 10px 0;">
                    <div class="layui-tab-item layui-show">
                        <input class="layui-input" value="https://gitee.com/whvse/easyweb-jwt.git"/>
                    </div>
                    <div class="layui-tab-item">
                        <input class="layui-input" value="git@gitee.com:whvse/easyweb-jwt.git"/>
                    </div>
                </div>
            </div>
            <button class="layui-btn layui-btn-sm layui-btn-fluid" style="margin-bottom: 10px;">Download ZIP</button>
            <img src="http://p1.music.126.net/voV3yPduAhNATICMRJza1A==/109951164017919367.jpg" width="100%">
            <!-- //end.自定义内容结束 -->
        </div>
    </div>

     

    6.1.6.控制显示方向

    在dropdown-menu-nav上加下面的class可控制位置:

    类名位置
    dropdown-bottom-left下左弹出
    dropdown-bottom-center下中弹出
    dropdown-bottom-right下右弹出
      
    dropdown-top-left上左弹出
    dropdown-top-center上中弹出
    dropdown-top-right上右弹出
      
    dropdown-left-top左上弹出
    dropdown-left-center左中弹出
    dropdown-left-bottom左下弹出
      
    dropdown-right-top右上弹出
    dropdown-right-center右中弹出
    dropdown-right-bottom右下弹出
    <!-- Bottom Center -->
    <div class="dropdown-menu dropdown-hover">
        <button class="layui-btn layui-btn-primary icon-btn">Bottom <i class="layui-icon layui-icon-drop"></i> Center
        </button>
        <ul class="dropdown-menu-nav dropdown-bottom-center"><!-- 这里加控制方向的类 -->
            <div class="dropdown-anchor"></div>
            <li><a>1st menu item</a></li>
            <li><a>2nd menu item</a></li>
            <li><a>3rd menu item</a></li>
        </ul>
    </div>
    
    <!-- Bottom Right -->
    <div class="dropdown-menu dropdown-hover">
        <button class="layui-btn layui-btn-primary icon-btn">Bottom Right <i class="layui-icon layui-icon-drop"></i>
        </button>
        <ul class="dropdown-menu-nav dropdown-bottom-right"><!-- 这里加控制方向的类 -->
            <div class="dropdown-anchor"></div>
            <li><a>1st menu item</a></li>
            <li><a>2nd menu item</a></li>
            <li><a>3rd menu item</a></li>
        </ul>
    </div>

     

    6.1.7.在数据表格中使用

    数据表格中使用分离式的绑定,并且加no-shade="true"去掉遮罩层:

    <!-- 表格操作列 -->
    <script type="text/html" id="tableBar">
        <a class="layui-btn layui-btn-primary layui-btn-xs" lay-event="edit">修改</a>
        <a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del">删除</a>
        <!-- 下拉菜单 -->
        <a class="layui-btn layui-btn-xs" data-dropdown="#dropUser{{d.LAY_INDEX}}" no-shade="true">
            更多<i class="layui-icon layui-icon-drop" style="font-size: 12px;margin-right: 0;"></i></a>
        <ul class="dropdown-menu-nav dropdown-bottom-right layui-hide" id="dropUser{{d.LAY_INDEX}}">
            <div class="dropdown-anchor"></div>
            <li><a lay-event="edit2"><i class="layui-icon layui-icon-edit"></i>修改用户</a></li>
            <li><a lay-event="del2"><i class="layui-icon layui-icon-delete"></i>删除用户</a></li>
            <li><a lay-event="lock2"><i class="layui-icon layui-icon-password"></i>锁定用户</a></li>
        </ul>
    </script>
    <script>
     layui.use(['table', 'dropdown'], function () {
         var table = layui.table;
         table.render({
             cols: [[
                 {field: 'username', title: '账号'},
                 {toolbar: '#tableBar', title: '操作'}
             ]]
         });
     });
     </script>

     

    6.1.8.气泡确认框

    <!-- 下弹出 -->
    <div class="dropdown-menu">
        <button class="layui-btn layui-btn-primary icon-btn">&nbsp;气泡确认框 <i class="layui-icon layui-icon-drop"></i></button>
        <div class="dropdown-menu-nav dropdown-popconfirm">
            <div class="dropdown-anchor"></div>
            <div class="dropdown-popconfirm-title">
                <i class="layui-icon layui-icon-help"></i>这是一段内容确定删除吗?
            </div>
            <div class="dropdown-popconfirm-btn">
                <button class="layui-btn" btn-cancel>取消</button>
                <button class="layui-btn layui-btn-normal">确定</button>
            </div>
        </div>
    </div>
    <!-- 上弹出 -->
    <div class="dropdown-menu">
        <button class="layui-btn layui-btn-primary icon-btn">&nbsp;气泡确认框 <i class="layui-icon layui-icon-drop"></i></button>
        <div class="dropdown-menu-nav dropdown-popconfirm dropdown-top-right">
            <div class="dropdown-anchor"></div>
            <div class="dropdown-popconfirm-title">
                <i class="layui-icon layui-icon-about"></i>这是一段内容确定删除吗?
            </div>
            <div class="dropdown-popconfirm-btn">
                <button class="layui-btn" btn-cancel>取消</button>
                <button class="layui-btn layui-btn-normal">确定</button>
            </div>
        </div>
    </div>

     

    6.2.1.快速使用

    layui.use(['notice'], function(){
        var notice = layui.notice;
    
        // 消息通知
        notice.success({
            title: '消息通知',
            message: '你有新的消息,请注意查收!'
        });
    
        // 提示框,1成功、2失败、3警告、4加载、5信息(蓝色图标)
        notice.msg('Hello', {icon: 1});
    });

     

    6.2.2.全部方法

    方法参数说明
    success(object)见下方成功消息(绿色)
    warning(object)见下方警告消息(黄色)
    error(object)见下方错误消息(红色)
    info(object)见下方通知消息(蓝色)
    show(object)见下方自定义样式
       
    msg(string, object)文本,其他参数提示框
       
    destroy()关闭全部
    hide(object, toast, closedBy)见下方关闭指定的通知
    settings(object)见下方统一设置默认值

    统一设置默认值:

    notice.settings({
        timeout: 1500,
        transitionIn: 'flipInX',
        onOpened: function(){
            console.log('notice opend!');
        }
    });   

    关闭指定的通知:

    notice.hide({}, document.querySelector('.toast')); 
    • 参数一   重写一些参数,比如关闭动画等
    • 参数二   根据自定义的className选择关闭的对象

     

    6.2.3.参数列表

    参数说明默认值可选值
    title标题string类型
    message内容string类型
    position显示位置topRight见下方
    transitionIn进入动画fadeInLeft见下方
    transitionOut退出动画fadeOutRight见下方
    timeout消失时间5000单位毫秒,false永不消失
    progressBar进度条truetrue显示、false不显示
    balloon气泡效果falsetrue开启、false关闭
    close关闭按钮truetrue显示,false不显示
    pauseOnHover鼠标滑过暂停消失时间truetrue、false
    resetOnHover鼠标滑过重置消失时间falsetrue、false
    animateInside文字动画效果falsetrue开启、false关闭
    className自定义class多个用空格分隔
    theme主题lightlight、dark
    audio音效1,2,3,4,5,6
        
    image显示图片图片地址
    imageWidth图片宽度60数字
    buttons显示按钮[][ [ 'btn1', function(){} ], ['btn2', function(){} ] ]
    overlay遮罩层falsetrue显示,false不显示
    drag滑动关闭truetrue开启,false关闭
    layout布局类型21标题和内容并排,2两排显示
    rtl布局方向falsefalse内容居左,true居右
    displayMode显示模式00无限制,1同类型存在不显示,2同类型存在先移除
    targetFirst插入方式自动true从上插入,false下插入
    onOpened打开后回调函数function
    onClosed关闭后回调函数function
        
    titleColor标题颜色默认颜色单位
    titleSize标题大小默认尺寸单位
    messageColor文字颜色默认颜色单位
    messageSize文字大小默认尺寸单位
    backgroundColor背景颜色默认颜色单位
    progressBarColor进度条颜色默认颜色单位
    maxWidth最大宽度尺寸单位

    参数position显示位置可选值:

    属性说明
    bottomRight右下角
    bottomLeft左下角
    topRight右上角
    topLeft左上角
    topCenter顶部中间
    bottomCenter底部中间
    center正中间

    参数transitionIn进入动画可选值:

    属性说明
    bounceInLeft向左反弹
    bounceInRight向右反弹
    bounceInUp向上反弹
    bounceInDown向下反弹
    fadeIn淡入
    fadeInDown向下淡入
    fadeInUp向上淡入
    fadeInLeft向左淡入
    fadeInRight向右淡入
    flipInX翻转进入

    参数transitionOut退出动画可选值:

    属性说明
    fadeOut淡出
    fadeOutUp向上淡出
    fadeOutDown向下淡出
    fadeOutLeft向左淡出
    fadeOutRight向右淡出
    flipOutX翻转退出

     

    6.2.4.解决弹窗遮挡

    <!-- 页面加入样式 -->
    <style>
        body .iziToast-overlay {
            z-index: 19892001;
        }
    
        body .iziToast-wrapper {
            z-index: 19892002;
        }
    </style>

     


     

    6.3.1.快速使用

    <input id="demoCascader1" placeholder="请选择" class="layui-hide"/>
    
    <script>
    layui.use(['cascader'], function () {
        var $ = layui.jquery;
        var cascader = layui.cascader;
    
        cascader.render({
            elem: '#demoCascader1',
            data: [{
                  value: 'beijing',
                  label: '北京',
                  children: [{
                      value: 'gugong',
                      label: '故宫'
                  },{
                      value: 'tiantan',
                      label: '天坛'
                  },{
                      value: 'wangfujing',
                      label: '王府井'
                  }]
              }]
        });
    
        // 请求远程数据
        cascader.render({
            elem: '#demoCascader1',
            reqData: function (values, callback, data) {
                $.get('xxxx.json', function(res){
                    callback(res.data);  // 数据请求完成通过callback回调
                },'json');
            }
        });
    
        // 处理数据格式,如果你的数据没有value、label字段可以前端处理
        cascader.render({
            elem: '#demoCascader1',
            reqData: function (values, callback, data) {
                $.get('xxxx.json', function(res){
                    function each(data) {
                        for (var i = 0; i < data.length; i++) {
                            data[i].value = data[i].id;
                            data[i].label = data[i].name;
                            if (data[i].children) {
                                each(data[i].children);
                            }
                        }
                    }
                    each(res.data);
                    callback(res.data);
                },'json');
            }
        });
    
        // 如果你的数据不是children形式,可以前端转换
        cascader.render({
            elem: '#demoCascader1',
            reqData: function (values, callback, data) {
                $.get('xxxx.json', function(res){
                    callback(pidToChildren(res.data, 'id', 'pid', 0));
                },'json');
            }
        });
    
        /* pid转children形式 */
        function pidToChildren(data, idName, pidName, childName, pId) {
            if (!childName) childName = 'children';
            var newList = [];
            for (var i = 0; i < data.length; i++) {
                if (data[i][idName] == data[i][pidName]) return;
                if (pId === undefined) pId = 0;
                if (data[i][pidName] == pId) {
                    var children = pidToChildren(data, idName, pidName, childName, data[i][idName]);
                    if (children.length > 0) data[i][childName] = children;
                    newList.push(data[i]);
                }
            }
            return newList;
        }
    
    });
    </script>

     

    6.3.2.异步加载

    <input id="demoCascader1" placeholder="请选择" class="layui-hide"/>
    
    <script>
    layui.use(['cascader'], function () {
        var $ = layui.jquery;
        var cascader = layui.cascader;
    
        cascader.render({
            elem: '#demoCascader1',
            reqData: function (values, callback, data) {
                // values是当前所有选中的值,data是当前选中的对象
                $.get('xxxx.json', { id: data.value }, function(res){
                    callback(res.data);  // 数据请求完成通过callback回调
                },'json');
            }
        });
    });
    </script>

    异步加载的数据格式为:

    [
        {value: 'beijing', label: '北京', haveChildren: true},
        {value: 'jiangsu', label: '江苏', haveChildren: true}
    ]

    通过haveChildren字段来标识是否还有子节点,如果你的后台数据格式不是这样,可以在callback之前格式化:

    cascader.render({
        elem: '#demoCascader1',
        reqData: function (values, callback, data) {
            // values是当前所有选中的值,data是当前选中的对象
            $.get('xxxx.json', { id: data.value }, function(res){
                var newList = [];
                for(var i=0;i<res.data.length;i++){
                      var item = res.data[i];
                      newList.push({
                           value: item.id,
                           label: item.name,
                           haveChildren: item.haveChildren
                      });
                }
                callback(newList);  // 数据请求完成通过callback回调
            },'json');
        }
    });

     

    6.3.3.自定义分隔符

    <input id="demoCascader1" placeholder="请选择" class="layui-hide"/>
    
    <script>
    layui.use(['cascader'], function () {
        var $ = layui.jquery;
        var cascader = layui.cascader;
    
        cascader.render({
            elem: '#demoCascader1',
            data: [],
            renderFormat: function (labels, values) {
                return labels.join(' / ');  // 默认是用斜杠分割,可以自定义
            }
        });
    });
    </script>

     

    <input id="demoCascader1" placeholder="请选择" class="layui-hide"/>
    
    <script>
    layui.use(['cascader'], function () {
        var $ = layui.jquery;
        var cascader = layui.cascader;
    
        cascader.render({
            elem: '#demoCascader1',
            data: [],
            filterable: true   // 这个参数是开启搜索功能
        });
    
        // 自定义搜索
        cascader.render({
            elem: '#demoCascader1',
            data: [],
            filterable: true,
            reqSearch: function (keyword, callback, dataList) {
                // keyword是搜索的关键字,dataList是当前的全部数据集合
                $.get('xxx.json', { keyword: keyword }, function(res){
                    callback(res);
                },'json')
            }
        });
    });
    </script>

    搜索后端接口返回的数据格式为:

    [ 
      {"value": "1,2", "label": "北京 / 王府井"},
      {"value": "1,3", "label": "北京 / 故宫"}
    ]

    如果要标记关键字为红色:<span class=\"search-keyword\">北京</span> / 王府井

     

    6.3.5.省市区选择

    <input id="demoCascader1" placeholder="请选择" class="layui-hide"/>
    
    <script type="text/javascript" src="/assets/module/cascader/citys-data.js"></script>
    <script>
    layui.use(['cascader'], function () {
        var $ = layui.jquery;
        var cascader = layui.cascader;
    
        cascader.render({
            elem: '#demoCascader1',
            data: citysData,
            itemHeight: '250px',
            filterable: true
        });
    });
    </script>

    省市区的数据已经封装好了,只需要引入数据的js即可,数据包含省市区,value是区号, 如果需要对数据进行处理,cascader封装了几种处理数据方法:

    // value也是中文而不是区号
    var data = cascader.getCityData(admin.util.deepClone(citysData));
    cascader.render({
        elem: '#demoCascader11',
        data: data
    });
    
    // 只显示省市,不要区域
    var data = cascader.getCity(admin.util.deepClone(citysData));
    
    // 只显示省份,不要市区
    var data = cascader.getProvince(admin.util.deepClone(citysData));
    
    // 只显示身份,并且value是中文,而不是区号
    var data = cascader.getCityData(cascader.getProvince(admin.util.deepClone(citysData)));

     

    6.3.6.全部方法

    <input id="demoCascader1" placeholder="请选择" class="layui-hide"/>
    
    <script>
    layui.use(['cascader'], function () {
        var $ = layui.jquery;
        var cascader = layui.cascader;
    
        var ins1 = cascader.render({
            elem: '#demoCascader1',
            data: []
        });
    
        ins1.data;  // 获取当前的数据
        ins1.open();  // 展开
        ins1.hide();  // 关闭
        ins1.removeLoading();  // 移除加载中的状态
        ins1.setDisabled(true);  // 禁用或取消禁用
        ins1.getValue();  // 获取选中的数据值
        ins1.getLabel();  // 选取选中的数据名称
        ins1.setValue('1,2');   // 设置值
    
    });
    </script>

     

    6.3.7.全部参数

    参数名称介绍默认值
    elem需要渲染的元素 
    data数据 
    clearable是否开启清除true
    clearAllActive清除时清除所有列选中false
    trigger次级菜单触发方式,可选'hover''click'
    disabled是否禁用false
    changeOnSelect是否点击每一项都改变值false
    filterable是否开启搜索功能false
    notFoundText搜索为空是提示文字'没有匹配数据'
    itemHeight下拉列表的高度'180px'
    reqData(values, callback, data)异步获取数据的方法 
    reqSearch(keyword, callback, dataList)自定义搜索的方法 
    renderFormat(labels, values)选择后用于展示的函数 
    onChange(values, data)数据选择改变的回调 
    onVisibleChange(isShow)展开和关闭的回调

     

     

    6.4.2.全部参数

    参数说明默认值
    defaultText提示文字+请输入
    skin样式风格 
    removeWithBackspace回退键可删除已添加的标签false
    focusWithClick点击已添加标签输入框获取焦点true
    autocomplete_url自动提示接口url 
    autocomplete接口配置 

    autocomplete参数:

    $('#demoTagsInput').tagsInput({
        autocomplete_url: '../../json/tagsInput.json',
        autocomplete: {
            type: 'post',
            data: {
                access_token: 'xxxxx'
            }
        }
    });

     type是请求方式,默认是get请求,data是额外参数,请求autocomplete_url会传递name参数(输入框的值)。

    更详细的使用文档可以参考jQuery-Tags-Input

    此插件基于 jQuery-Tags-Input 二次修改。

     

     

    6.5.1.快速使用

    <div class="split-group">
        <div class="split-item" id="demoSplit1">
            面板一
        </div>
        <div class="split-item" id="demoSplit2">
            面板二
        </div>
    </div>
    
    <script>
        layui.use(['Split'], function () {
            var $ = layui.jquery;
            var Split = layui.Split;
    
            // 水平分割,需要分割的元素(id)、默认大小(百分比)、最小值(单位px)
            Split(['#demoSplit1', '#demoSplit2'], {sizes: [25, 75], minSize: 100});
        });
    </script>

     

    6.5.2.垂直分割

    <div class="split-group-vertical">
        <div class="split-item" id="demoSplit3">
            面板一
        </div>
        <div class="split-item" id="demoSplit4">
            面板二
        </div>
    </div>
    
    <script>
        layui.use(['Split'], function () {
            var $ = layui.jquery;
            var Split = layui.Split;
    
            // 垂直分割
            Split(['#demoSplit3', '#demoSplit4'], {direction: 'vertical'});
        });
    </script>

     

    6.5.3.嵌套使用

    <div class="split-group" style="height: 600px;">
        <div class="split-item" id="demoSplit8">
            <div class="split-group-vertical">
                <div class="split-item" id="demoSplit10">
                    面板一
                </div>
                <div class="split-item" id="demoSplit11">
                    面板二
                </div>
            </div>
        </div>
        <div class="split-item" id="demoSplit9">
            面板三
        </div>
    </div>
    
    <script>
        layui.use([Split'], function () {
            var $ = layui.jquery;
            var Split = layui.Split;
    
            // 垂直水平分割
            Split(['#demoSplit8', '#demoSplit9'], {sizes: [25, 75], minSize: 100});
            Split(['#demoSplit10', '#demoSplit11'], {direction: 'vertical'});
        });
    </script>

     

     

    6.6.1.快速使用

    <div id="demoProgress1"></div>
    
    <script>
    layui.use(['CircleProgress'], function () {
        var CircleProgress = layui.CircleProgress;
    
        // 快速使用
        new CircleProgress('#demoProgress1', {
            max: 100,
            value: 20
        });
    });
    </script>

    6.6.2.全部参数

    参数名称说明默认值
    max最大值 
    value当前值 
    clockwise是否顺时针方向true
    startAngle起始角度0
    textFormat文字样式 

    文字样式:

    • vertical   垂直
    • percent   百分比
    • value   只显示值
    • valueOnCircle   值显示在进度条上
    • none   不显示文字

    自定义文字样式:

    new CircleProgress('#demoProgress9', {
        max: 12,
        value: 9,
        textFormat: function (value, max) {
            return value + ' dots';
        }
    });

     

    6.6.3.自定义样式

    使用css自定义样式:

    <div id="demoProgress1"></div>
    
    <script>
    layui.use(['CircleProgress'], function () {
        var CircleProgress = layui.CircleProgress;
    
        // 快速使用
        new CircleProgress('#demoProgress1', {
            max: 100,
            value: 20,
            textFormat: 'percent'
        });
    });
    </script>
    
    <style>
    /* 进度条选中的样式 */
    #demoProgress1 .circle-progress-value {
        stroke-width: 8px;  /* 粗度 */
        stroke: #3FDABA;  /* 颜色 */
    }
    
    /* 进度条未选中的样式 */
    #demoProgress1 .circle-progress-circle {
        stroke-width: 6px;
        stroke: #E0FAF1;
    }
    </style>

     

     

    此插件是使用svg实现的,想要实现更丰富的样式,可先了解下svg

     

     

    6.7.1.快速使用

    默认样式:

    <div class="layui-tab layui-steps">
        <ul class="layui-tab-title">
            <li>
                <i class="layui-icon layui-icon-ok">1</i>
                <span class="layui-steps-title">已完成</span>
                <span class="layui-steps-content">这里是该步骤的描述信息</span>
            </li>
            <li class="layui-this">
                <i class="layui-icon layui-icon-ok">2</i>
                <span class="layui-steps-title">进行中</span>
                <span class="layui-steps-content">这里是该步骤的描述信息</span>
            </li>
            <li>
                <i class="layui-icon layui-icon-ok">3</i>
                <span class="layui-steps-title">待进行</span>
                <span class="layui-steps-content">这里是该步骤的描述信息</span>
            </li>
        </ul>
        <div class="layui-tab-content">
            <div class="layui-tab-item">内容1</div>
            <div class="layui-tab-item layui-show">内容2</div>
            <div class="layui-tab-item">内容3</div>
        </div>
    </div>
    <script>
    layui.use(['steps'], function () {
        var steps = layui.steps;
    
    });
    </script>

    它的结构与layui的选项卡Tab一致,因为它就是在Tab的基础上增加的样式。

    6.7.2.风格选择

    迷你样式:

    <!-- 多加一个layui-steps-small即可 -->
    <div class="layui-tab layui-steps layui-steps-small">
        <!-- 省略...... -->
    </div>

    自定义图标:

    <div class="layui-tab layui-steps layui-steps-small">
        <ul class="layui-tab-title">
            <li class="layui-this">
                <!-- 这里的图标可以任意修改 -->
                <i class="layui-icon layui-icon-username"></i>
                <span class="layui-steps-title">账号注册</span>
            </li>
            <li>
                <i class="layui-icon layui-icon-camera"></i>
                <span class="layui-steps-title">上传头像</span>
            </li>
        </ul>
        <div class="layui-tab-content">
            <div class="layui-tab-item layui-show">内容1</div>
            <div class="layui-tab-item">内容2</div>
        </div>
    </div>

    垂直风格:

    <!-- 多加一个layui-steps-vertical即可 -->
    <div class="layui-tab layui-steps layui-steps-vertical">
        <!-- 省略...... -->
    </div>

    简洁风格:

    <!-- 多加一个layui-steps-simple -->
    <div class="layui-tab layui-steps layui-steps-simple">
        <ul class="layui-tab-title">
            <li>1.填写注册手机号</li>
            <li class="layui-this">2.获取短信验证码</li>
            <li>3.修改登录密码</li>
        </ul>
        <div class="layui-tab-content">
            <div class="layui-tab-item">内容1</div>
            <div class="layui-tab-item layui-show">内容2</div>
            <div class="layui-tab-item">内容3</div>
        </div>
    </div>

    注意 简洁风格只有标题,没有图标、描述等

    6.7.3.上一步下一步

    <div class="layui-tab layui-steps" lay-filter="demoSteps">
        <!-- 省略...... -->
    </div>
    <script>
    layui.use(['steps'], function () {
        var steps = layui.steps;
    
        steps.next('demoSteps');  // 下一步
    
        steps.prev('demoSteps');  // 上一步
    
        steps.go('demoSteps', 2);  // 指定跳转,索引从0开始
    });
    </script>

    也可以使用属性绑定:

    <div class="layui-tab layui-steps">
        <!-- 省略...... -->
        <a class="layui-btn" data-steps="prev">上一步</a>
        <a class="layui-btn" data-steps="next">下一步</a>
        <a class="layui-btn" data-steps="go" data-go="1">跳转第2步</a>
    </div>

     

    7.1.1.全部方法

    方法参数描述
    merges(tableId, indexs, fields)见单独说明合并单元格
    bindCtxMenu(tableId, items)见单独说明给表格行绑定鼠标右键
    exportData(object)见单独说明导出任意数据
    exportDataX(object)见单独说明导出任意数据(依赖社区excel模块)
    exportDataBack(object)见单独说明后端导出任意数据(支持post提交参数)
       
    render(object)同layui表格渲染表格,带后端排序功能
    renderFront(object)同layui表格渲染表格,前端分页、排序、搜索
    layui.use(['tableX'], function () {
        var tableX = layui.tableX;
    });

     

    7.1.2.合并单元格

    在table.render的done回调里面使用tableX.merges方法:

    table.render({
        elem: '#xTable2',
        cols: [[
            {type: 'numbers'},
            {field: 'parentName', title: '模块名称', sort: true},
            {field: 'authorityName', title: '菜单名称', sort: true}
        ]],
        done: function () {
            tableX.merges('xTable2', [1]);  
        }
    });

    参数说明:

    tableX.merges('xTable2', [1]);  // 合并第2列相同的单元格
    tableX.merges('xTable2', [1], ['parentName']);  // 合并第2列相同的单元格
    tableX.merges('xTable2', [1, 2]);   // 合并第2、3列相同的单元格
    tableX.merges('xTable2', [1, 2], ['parentName', 'authorityName']);   // 合并第2、3列相同的单元格
    
    tableX.merges('xTable2', [1, 2], false);   // 在后面加一个false可解决排序冲突的问题
    • 参数一   必填    表格的lay-filter
    • 参数二   必填    要合并列的索引,数组类型
    • 参数三   非必填   根据数据字段判断是否相同,为空时根据单元格的html内容判断
    • 参数四   非必填   是否需要监听排序后重新合并,默认为true

     

    7.1.3.行绑定鼠标右键

    在table.render的done回调里面使用tableX.bindCtxMenu方法:

    table.render({
        elem: '#xTable3',
        cols: [[
            {field: 'nickName', title: '用户名'},
            {field: 'sex', title: '性别'}
        ]],
        done: function () {
            tableX.bindCtxMenu('xTable3', [{
                icon: 'layui-icon layui-icon-edit',
                name: '修改此用户',
                click: function (d, tr) {
                    layer.msg('点击了修改,userId:' + d.userId);
                }
            }, {
                icon: 'layui-icon layui-icon-close text-danger',
                name: '<span class="text-danger">删除此用户</span>',
                subs: [{
                    icon: 'layui-icon layui-icon-camera',
                    name: '逻辑删除',
                    click: function (d) {
                        layer.msg('点击了逻辑删除,userId:' + d.userId);
                    }
                }, {
                    icon: 'layui-icon layui-icon-picture-fine',
                    name: '物理删除',
                    click: function (d) {
                        layer.msg('点击了物理删除,userId:' + d.userId);
                    }
                }]
            }]);
        }
    });
    • 参数一   表格的id
    • 参数二   右键菜单
      • icon     图标
      • name   标题
      • click     点击事件,d是当前行的数据

    根据不同行动态显示不同菜单,只需要把参数二换成function并return菜单数组即可:

    tableX.bindCtxMenu('xTable3', function(d, tr) {
        if(d.userId === 1) {
            return [{
               icon: 'layui-icon layui-icon-close text-danger',
               name: '<span class="text-danger">删除此用户</span>',
               click: function (d, tr) {
                   layer.msg('点击了删除,userId:' + d.userId);
               }
           }];
        } else {
            return [{
               icon: 'layui-icon layui-icon-edit',
               name: '修改此用户',
               click: function (d, tr) {
                   layer.msg('点击了修改,userId:' + d.userId);
               }
           }];
        }
    });

     

    7.1.4.后端排序

    tableX.render({
        elem: '#xTable3',
        url: '../../json/user.json',
        cols: [[
            {type: 'numbers'},
            {field: 'nickName', title: '用户名', sort: true},
            {field: 'sex', title: '性别', sort: true}
        ]]
    });

    仅仅是把table.render换成tableX.render就会在点击排序时自动传递sortorder参数,例如:user?page=1&limit=10&sort=sex&order=asc。

    • sort     排序字段,值是点击排序列的field
    • order   排序方式,升序是asc,降序是desc

    注意:如果写了sort: true开启排序,一定要写field: 'xxx'

     

    7.1.5.前端分页排序

    tableX.renderFront({
        elem: '#xTable1',
        url: '../../json/userAll.json',
        page: true,
        cols: [[
            {field: 'nickName', title: '用户名', sort: true},
            {field: 'sex', title: '性别', sort: true}
        ]]
    });

    仅仅是把table.render换成tableX.renderFront就可以有前端分页和排序功能了,参数跟layui表格的参数一样,url方式你的接口可以返回全部数据,前端来分页,也支持data方式。

    前端模糊搜索:

    <input tb-search="xTable1" class="layui-input icon-search"/>

     在页面任意位置加入上面输入框,通过tb-search关联表格,就实现了对表格的模糊搜索功能。 还可以增加name属性来设置搜索时只搜索某些字段,多个字段通过逗号分隔:

    <input tb-search="xTable1" name="sex,phone" class="layui-input icon-search"/>

    刷新功能:

    <button tb-refresh="xTable1" class="layui-btn">刷新</button>

     在页面任意位置加入上面按钮,通过tb-refresh关联表格。 也可以通过js刷新:

    // url方式渲染的只能用此方法刷新
    var insTb = tableX.renderFront({url: 'xxx'});
    insTb.reloadUrl();
    
    // data方式渲染的只能用此方法刷新
    var insTb = tableX.renderFront({data: []});
    insTb.reloadData({data: dataList, page: {curr: 1}});

    前端排序:

     前端排序如果有field字段,会根据field字段的值来排序,如果有templet会根据templet转换后的值排序, templet可能会返回表单元素,比如switch开关等,这些元素无法用来排序,可以通过export-showexport-hide来控制。

    <!-- switch开关列 -->
    <script type="text/html" id="tableState">
        <input type="checkbox" lay-skin="switch" lay-text="正常|锁定" lay-filter="ckState" value="{{d.userId}}" {{d.state==0?'checked':''}}/>
        <div class="export-show">{{d.state==0?'正常':'锁定'}}</div>
    </script>
    
    <!-- icon图标列 -->
    <script type="text/html" id="tableState">
        <div class="export-hide">{{d.state==0?'<i class="layui-icon layui-icon-ok"></i>':'<i class="layui-icon layui-icon-close"></i>'}}</div>
        <div class="export-show">{{d.state==0?'正常':'锁定'}}</div>
    </script>
    • export-show   排序和导出时有效,表格展示时屏蔽
    • export-hide   表格展示时有效,排序和导出时屏蔽

     

    7.1.6.导出数据

    tableX.exportData({
        cols: insTb.config.cols,   // 表头配置
        data: table.cache.xTable3,  // 数据,支持url方式
        fileName: '用户表'          // 文件名称
    });
    
    // exportDataX是新增的方法,参数与上面一摸一样
    tableX.exportDataX({});
    参数必填说明默认
    cols表头配置 
    data导出的数据,支持数组和string的url 
    fileName导出的文件名称table
    expType导出的文件类型xls(默认)、csv、xlsx
    optionurl方式的配置 

     如果data是string类型会把data当url请求数据,option是请求的配置,跟表格的配置一样,配置method、where、headers等, 接口返回的格式也要跟表格一样包含code、count、data等信息。

     cols的配置也跟表格一样,是一个多维数组,可以通过insTb3.config.cols来获取表格的cols,也可以重写。

     导出的数据会包含templet转换,如果templet返回的是switch开关、icon图标等,可以通过export-showexport-hide写两份, 一份用于表格的展示,一份用于表格的导出显示,具体用法参考前面前端排序章节的介绍。

    cols也可以重写:

    tableX.exportData({
        cols: [[
            {field: 'username', title: '账号'},
            {field: 'nickName', title: '用户名'}
        ]],
        data: table.cache.xTable3,
        fileName: '用户表'
    });

    exportDataX方法使用的是社区excel模块导出的,是真正的xls格式,exportData以及layui自带的导出都是假的xls格式,如果数字前面有0会自动去掉0,exportDataX可解决此问题。

     

    7.1.7.导出全部、搜索

    后端分页时如何导出全部数据:

    tableX.exportDataX({
        cols: insTb.config.cols,
        data: 'listAll.json',
        fileName: '用户表'
    });
    // 后端再写一个查询全部的接口,data写接口地址

    导出搜索后的全部数据:

    var lastWhere;  // 记录搜索的条件
    // 表格搜索
    form.on('submit(formSubSearchUser)', function (data) {
        lastWhere = data.field;
        insTb.reload({where: data.field}, 'data');
    });
    
    tableX.exportDataX({
        cols: insTb.config.cols,
        data: 'listAll.json',
        option: {
            where: lastWhere
        },
        fileName: '用户表'
    });

    在options里面加一个where把搜索条件传给后端。

     

    7.1.8.后端导出

    后端导出本质就是下载文件,一般用window.open(url)即可,如果要传递参数、post提交,那就麻烦了,tableX进行了完美的封装:

    tableX.exportDataBack('user/export', {sex: '男'});
    
    tableX.exportDataBack('user/export', {sex: '男'}, 'post');
    • 参数一   后端的url
    • 参数二   传递的参数
    • 参数三   请求方式

    如果是get方式,会使用?和&拼接参数,如果是post方式,会创建一个隐藏的表单来提交, 如果你的参数有复杂的类型,比如json格式,建议用post的形式,此方法也可以用来做post方式下载文件的操作。

     

    7.2.1.验证规则

    规则描述提示信息
    phoneX手机号请输入正确的手机号
    emailX邮箱邮箱格式不正确
    urlX网址链接格式不正确
    numberX数字只能填写数字
    dateX日期日期格式不正确
    identityX身份证请输入正确的身份证号
       
    psw密码密码必须5到12位,且不能出现空格
    equalTo重复两次输入不一致
    digits整数只能输入整数
    digitsP正整数只能输入正整数
    digitsN负整数只能输入负整数
    digitsPZ非负整数只能输入正整数和0
    digitsNZ非正整数只能输入负整数和0
       
    h5兼容h5的规则 

    使用示例:

    <form class="layui-form">
        <input class="layui-input" placeholder="请输入手机号" lay-verType="tips" lay-verify="phoneX"/>
        <input class="layui-input" placeholder="请输入手机号" lay-verType="tips" lay-verify="required|phoneX"/>
        <input class="layui-input" placeholder="请输入整数" lay-verType="tips" lay-verify="digits"/>
        <input class="layui-input" placeholder="请输入正整数" lay-verType="tips" lay-verify="digitsP"/>
    </form>
    <script>
    layui.use(['formX'],function(){
        var formX = layui.formX;  // 要引入formX模块才会生效
    });
    </script>

    equalTo用法,可以用来验证两次输入是否一致:

    <form class="layui-form">
        <input id="demoPsw" class="layui-input" placeholder="请输入密码" lay-verType="tips" lay-verify="required|psw"/>
        <input class="layui-input" placeholder="请再次输入密码" lay-verType="tips" 
            lay-verify="equalTo" lay-equalTo="#demoPsw" lay-equalToText="两次输入密码不一致"/>
    </form>
    属性描述
    lay-equalTo关联输入框的dom选择器
    lay-equalToText自定义提示文本

    h5用法:

    属性描述
    minlength最少输入字符长度
    maxlength最多输入字符长度
    min最小输入数值
    max最大输入数值
    <form class="layui-form">
        <input class="layui-input" placeholder="最少输入5个字符" minlength="5"
               lay-verType="tips" lay-verify="required|h5"/>
        <input class="layui-input" placeholder="最多输入10个字符" maxlength="10"
               lay-verType="tips" lay-verify="h5"/>
        <input class="layui-input" type="number" placeholder="值只能在-9到9之间" min="-9" max="9"
               lay-verType="tips" lay-verify="required|numberX|h5"/>
    </form>

    phoneX、emailX等与layui自带phone、email等的区别是如果没有输入不会验证,输入了才验证格式。

     

    7.2.2.扩展方法

    方法描述
    val(filter, object)赋值表单,解决top.layui.form.val()无效bug
    renderSelect(option)渲染select封装
    startTimer(elem, time, format)按钮验证码倒计时封装
    formUpdatedField(field, oldField)获取表单修改过的数据

    使用方法:

    layui.use(['formX'],function(){
        var formX = layui.formX;
    
        // 赋值表单,支持top.formX.val()用法
        formX.val('userForm', {name: 'user01'});  
    });

     

    7.2.3.渲染select封装

    <select id="sel"></select>
    <script>
    layui.use(['formX'],function(){
        var formX = layui.formX;
    
        // 数据方式
        formX.renderSelect({
            elem: '#sel',
            data: [
                {id: 1, name: '张三'},
                {id: 2, name: '李四'}
            ],
            name: 'name',
            value: 'id',
            hint: '请选择用户',
            initValue: 1,
            done: function() {}
        });
    
        // 异步方式
        formX.renderSelect({
            elem: '#sel',
            data: 'user.json',
            name: 'name',
            value: 'id',
            hint: '请选择用户',
            done: function(data) {},
            method: 'get',
            where: {page: 20},
            header: {token: 'xxx'},
            async: true,
            error: function(xhr, res){}
        });
    });
    </script>

    基础参数:

    • elem      要渲染的select
    • data       数据源,可以是数组,也可以是url
    • name     显示的字段名称
    • value     值的字段名称
    • hint     未选择提示文字
    • initValue   默认回显的数据
    • done      渲染完成后的回调
    • error      data为url时请求失败的回调
    • method    data为url时请求方式
    • where      data为url时请求参数
    • header     data为url时请求header
    • async    data为url时请求时否是异步

     后端返回数据格式为{"data": [], "code": 0},data有数据就是请求成功,没有数据就进入error,code等于多少都可以, 如果数据不是对象的形式,name和value可不填:

    formX.renderSelect({
        elem: '#sel',
        data: ['张三','李四']
    });

     

    7.2.4.验证码倒计时

    <button id="btnSend" class="layui-btn">发送验证码</button>
    
    <script>
    
    layui.use(['formX'],function(){
        var formX = layui.formX;
    
        // 按钮倒计时30s
        formX.startTimer('#btnSend', 30);
    
        // 自定义倒计时文字,默认是30s,29s,28s...
        formX.startTimer('#btnSend', 30, function(time){
            return time + 's 后可继续发送';
        });
    });
    </script>

     

    7.2.5.获取修改字段

    var user = {sex: 'male', age: 18};
    form.val('userForm', user);  // 表单回显数据
    // 获取表单修改后的字段
    var field = formX.formUpdatedField(form.val('userForm'), user);
    console.log(field);

    利用这个方法可以做判断用户是否修改了表单:

    var user = {sex: 'male', age: 18};
    form.val('userForm', user);  // 表单回显数据
    // 监听表单提交
    form.on('submit(submit-user)', function (data) {
        var u = formX.formUpdatedField(data.field, user);
        if(!u) { alert('你没有做任何修改'); }
        return false;
    });

     

     

    printer.print();
    
    printer.print({
        hide: ['.layui-btn', '#btn01'],  // 打印时隐藏的元素
        horizontal: true,         // 是否横向打印
        blank: true,              // 是否打开新页面打印
        close: true,              // 如果是打开新页面,打印完是否关闭
        iePreview: true          // 是否兼容ie打印预览
    });

    参数都是可以选参数,默认值已经符合大多数需求。

     

    7.3.2.设置不打印元素

    <div class="hide-print">非打印内容</div>

    hide-print这个class即可,可以跟hide参数叠加使用。

     

    var pWindow = printer.printHtml({
        html: '<span>xxxx</span>',  // 要打印的内容
        horizontal: true,         // 是否横向打印
        blank: true,              // 是否打开新页面打印
        close: true,              // 如果是打开新页面,打印完是否关闭
        iePreview: true,          // 是否兼容ie打印预览
        print: true              // 如果是打开新窗口是否自动打印
    });

    打印表格时可以给table加print-table这个class来设置表格的边框样式:<table class="print-table">

    如果print为false关闭自动打印,可以使用pWindow.print()触发打印。

     

    printer.printPage({
        htmls: [
            '<span>xxxx</span>',                 // 要打印的内容
            '<span>xxxx</span>'
        ],
        style: '<style>span{color:red;}</style>',// 页面样式
        horizontal: true,                // 是否横向打印
        blank: true,                     // 是否打开新页面打印
        close: true,                     // 如果是打开新页面,打印完是否关闭
        iePreview: true,                 // 是否兼容ie打印预览
        print: true,                     // 如果是打开新窗口是否自动打印
        padding: undefined,             // 页面间距
        debug: false,                    // 调试模式
        height: undefined,              // 页面高度
        width: undefined                // 页面宽度
    });

    参数都是可选参数:

    • htmls     数组,代表每一页;
    • style      样式,也可以写<link rel="stylesheet">的形式;
    • padding   页面间距,例如写'10px';
    • debug      调试模式,每一页会加红色边框,便于调试大小;

     

    7.3.5.拼接html

    var htmlStr = printer.makeHtml({
        title: '网页标题',
        style: '<link rel="stylesheet" href="layui.css"><script type="text/javascript" src="layui.js"><\/script>',
        body: $('#xxx').html()
    });

     

     

    7.4.1.快速使用

    layui.use(['contextMenu'], function () {
        var contextMenu = layui.contextMenu;
    
        // 重写整个页面右键菜单
        contextMenu.bind('html', [{
            icon: 'layui-icon layui-icon-snowflake',
            name: '菜单一',
            click: function (e, event) {
                // 通过$(event.currentTarget)可获取事件触发的元素
                alert('点击了菜单一');
            }
        }, {
            name: '菜单二',
            click: function (e) {
                alert('点击了菜单二');
            }
        }]);
    });
    • 参数一   绑定元素
    • 参数二   菜单数组

    菜单数组可支持无限极:

    [{
        icon: 'xxxxx',
        name: '菜单三',
        subs: [{
            icon: 'xxxxx',
            name: '子菜单一',
            click: function (e, event) {
                alert('点击了子菜单一');
            }
        }]
    }]
    • icon     图标
    • name   菜单名
    • click     点击事件
    • subs     子菜单(支持无限极)

    click事件里面的e是右键菜单的事件对象,event才是绑定的目标元素的事件对象

     

    7.4.2.自定义使用

    例如用于点击事件:

    $('#btn').click(function (e) {
        var x = $(this).offset().left;
        var y = $(this).offset().top + $(this).outerHeight() - $('html,body').scrollTop();
        contextMenu.show([{
            name: '按钮菜单一',
            click: function () {
            }
        }], x, y, e);
        e.preventDefault();
        e.stopPropagation();
    });

    你可以自己绑定事件,通过show方法显示出来,参数说明:

    • 参数一   菜单数组
    • 参数二   x坐标
    • 参数三   y坐标
    • 参数四   e 原始事件对象

     

    7.4.3.动态元素绑定

    对于动态生成的元素可以使用事件委托的方式来绑定:

    // 对.btn元素绑定鼠标右键
    $ (document). bind('contextmenu', '.btn', function (e) {
        contextMenu.show([{
            icon: 'layui-icon layui-icon-set',
            name: '删除',
            click: function (e, event) {
                layer.msg('点击了刪除');
            }
        }],e. clientX, e. clientY, e);
        return false;
    });

     

    7.5.1.快速使用

    后台管理页面大多用数据表格展示,如果要使用网格、瀑布流、卡片列表等形式,分页、自动渲染、搜索、排序等功能都需要自己实现, 极其麻烦,dataGrid模块就是对非表格形式的列表页面实现类似数据表格的功能,也在使用方法上与数据表格大致相同。

    <div id="demoGrid"></div><!-- 容器 -->
    
    <!-- 模板 -->
    <script type="text/html" id="demoGridItem">
        <div>
            <h2>{{d.title}}</h2>
            <p>{{d.content}}</p>
            <a lay-event="add">添加</a>
            <a lay-event="edit">修改</a>
        </div>
    </script>
    
    <script>
    layui.use(['dataGrid'], function () {
        var dataGrid = layui.dataGrid;
    
        /* 渲染 */
        var ins = dataGrid.render({
            elem: '#demoGrid',  // 容器
            templet: '#demoGridItem',  // 模板
            url: 'json/list.json',  // 数据接口
            page: {limit: 5}  // 开启分页
        });
    
        /* item点击事件 */
        dataGrid.on('item(demoGrid)', function (obj) {
            obj.data;  // 当前操作的数据对象
            obj.elem;  // 当前操作的dom元素
            obj.del();  // 删除当前item
            obj.update({title: 'new title'});  // 修改当前item
            layer.msg('点击了第' + (obj.index + 1) + '个');
        });
    
        /* item里面的lay-event的点击事件 */
        dataGrid.on('tool(demoGrid)', function (obj) {
            var data = obj.data;
            if (obj.event === 'add') {
                layer.msg('点击了添加');
            } else if (obj.event === 'edit') {
                layer.msg('点击了编辑');
            } 
        });
    
        /* item双击事件 */
        dataGrid.on('itemDouble(demoGrid)', function (obj) {
        });
    
        /* 监听复选框选择 */
        dataGrid.on('checkbox(demoGrid)', function (obj) {
            console.log(obj.checked); // 当前是否选中状态
            console.log(obj.data); // 选中行的相关数据
            console.log(obj.type); // 如果触发的是全选,则为all
        });
    
    });
    </script>

     

    7.5.2.全部参数

    参数类型说明示例
    elemString/DOM指定容器的选择器或DOM"#demo"
    templetStringitem模板,模板遵循 laytpl 语法 
    dataArray直接赋值数据,也可前端分页[{},{},{}]
    urlString接口地址 
    methodString接口http请求类型,默认:get 
    whereObject接口的请求参数where: {id: 123}
    headersObject接口的请求头headers: {token: 'sasasas'}
    contentTypeString发送到服务端的内容编码类型contentType: 'application/json'
    parseDataFunction数据格式解析的回调函数 
    requestFunction用于对分页请求的参数重新设定名称默认是page、limit
    useAdminBoolean是否使用admin.ajax默认false
    doneFunction数据渲染完的回调 
    pageObject开启分页,配置分页参数 
    loadMoreObject开启加载更多,配置加载更多参数 

    parseData和request参数说明:

    var ins = dataGrid.render({
        elem: '#demoGrid',
        templet: '#demoGridItem',
        url: 'json/list.json',
        parseData: function(res) {
            return {
                code: res.status,
                msg: res.message,
                count: res.total,
                data: res.list
            }
        },
        request: {pageName: 'page', limitName: 'limit'}
    });

    渲染完成的回调done说明:

    dataGrid.render({
        done: function(dataList, curr, count) {
            dataList;  // 当前页数据
            curr;      // 当前第几页
            count;     // 总数量
        }
    });

     

    7.5.3.分页功能

    使用page参数开启分页,page参数同layui分页组件的参数一致前往查看

    dataGrid.render({
        elem: '#demoGrid',  // 容器
        templet: '#demoGridItem',  // 模板
        url: 'json/list.json',  // 数据接口
        page: {limit: 5}  // 开启分页
    });

     

    7.5.4.加载更多功能

    dataGrid.render({
        elem: '#demoGrid',  // 容器
        templet: '#demoGridItem',  // 模板
        url: 'json/list.json',  // 数据接口
        loadMore: {limit: 5}  // 开启加载更多
    });

    loadMore和page只能二选一,loadMore的可选参数:

    参数说明默认值
    class自定义class''
    limit每页多少条10
    text显示文字'加载更多'
    loadingText加载中文字'加载中...'
    noMoreText无数据文字'没有更多数据了~'
    errorText加载失败文字'加载失败,请重试'

     

    7.5.5.实例方法

    var ins = dataGrid.render({});
    
    ins.reload();  // 重载
    ins.reload({page: {curr: 2} });  // 跳到第二页
    
    ins.update(index, fields, type);  // 修改数据
    // index是索引,fields是要修改的字段
    // type 0整个item更新, 1只更新item子元素, 2只更新数据不更新item
    
    ins.del(index);  // 删除item
    
    ins.getData();  // 获取当前数据
    
    ins.checkStatus();  // 获取选中行数据

     

    7.5.6.自动渲染

    <div id="demoGrid" lay-data="{url: 'json/list.json', page: {limit: 5} }" data-grid>
        <script type="text/html" data-grid-tpl>
            <div>
                <h2>{{d.title}}</h2>
                <p>{{d.content}}</p>
                <a lay-event="edit">修改</a>
            </div>
        </script>
    </div>

    通过添加data-grid和data-grid-tpl属性,dataGrid组件便会自动渲染,通过lay-data属性进行参数配置。

     

    7.6.1.快速使用

    layui.use(['fileChoose'], function () {
        var fileChoose = layui.fileChoose;
    
        fileChoose.open({
            fileUrl: '',  // 文件查看的url
            listUrl: '../template/file/files.json',  // 文件列表的url
            where: {
              access_token: 'xxxxxx'  
            },
            num: 3,  // 最多选择数量
            dialog: {
                offset: '60px'
            },
            onChoose: function (urls) {
                layer.msg('你选择了:' + JSON.stringify(urls), {icon: 1});
            }
        });
    });

     

    7.6.2.全部参数

    参数描述默认值
    fileUrl文件查看的url 
    listUrl文件列表的url 
    where文件列表请求参数{}
    num文件选择的数量1
    onChoose选择后回调 
    upload文件上传配置(同layui配置){}
    dialog弹窗配置(同layui配置){}
    menu点击弹出的菜单数组类型
    menuClick菜单点击事件处理 
    response接口数据格式化 

    菜单配置及点击事件:

    fileChoose.open({
        menu: [{
            name: '预览',
            event: 'preview'
        }, {
            name: '复制',
            event: 'copy'
        }, {
            name: '<span style="color: red;">删除</span>',
            event: 'del'
        }],
        menuClick: function(event, item) {
            // event  事件名称
            // item   当前数据
        }
    });

    name菜单项名称,event点击事件名称

    接口数据格式化:

    fileChoose.open({
        response: {
            method: 'get',  // 请求方式
            code: 0,  // 成功码,默认200
            name: 'name',  // 文件名称字段名称
            url: 'url',  // 文件url字段名称
            smUrl: 'smUrl',  // 文件缩略图字段名称
            isDir: 'isDir',  // 是否是文件夹字段名称,boolean类型
            dir: 'dir'  // 当前文件夹参数名称
        }
    });

    接口数据返回的格式需要为:

    {
        "code": 200,
        "msg": "请求成功",
        "data": [
            {
                "name": "图片一",
                "url": "2019/07/11/001.png",
                "smUrl": "sm/2019/07/11/001.png",
                "isDir": false
            }
        ]
    }

    code、msg、data是必须按这个名字的,name、url、smUrl、isDir这几个字段的名称可以通过response参数配置,也可以加其他字段, 比如id、create_time等,这些字段会在菜单点击事件和选择回调事件中返回。

    如果你的接口返回的数据不是code、msg,是其他的,比如status、message,可以使用parseData参数格式化:

    fileChoose.open({
        response: {
            parseData: function(res){
                return {
                    code: res.status,
                    msg: res.message,
                    data: res.list
                }
            }
        }
    });

    如果是文件夹,点击文件夹会重新请求接口,并且传递文件夹的名称,传递的字段名称可以通过response.dir修改。

    上传文件上传成功后默认会进入到当前日期生成的dir下面,你可以后端上传成功的接口返回dir指定上传成功后要进入的dir, 也可以把上传前端传递的dir原封不动的返回:

    {"code": 200,"msg": "上传成功", "dir": "/2020/0516"}

    不同文件显示不同的图标是前端根据文件url的后缀名称来判断的,在之前版本是服务器根据文件的content-type判断的。

     

     

     

    8.1.鼠标滚轮监听

    此插件来源于 jquery-mousewheel,使用方式:

    layui.use(['mousewheel'], function () {
        var $ = layui.jquery;
    
        // 滚动监听
        $('#xxx').on('mousewheel', function (event) {
            console.log(event.deltaX, event.deltaY, event.deltaFactor);
            event.stopPropagation();  // 阻止事件冒泡
            event.preventDefault();  // 阻止默认事件
        });
    
    });

    event对象中可以获取如下三个属性值:

    • deltaX:值为负的(-1)表示滚轮向左滚动,值为正的(1)表示滚轮向右滚动。
    • deltaY:值为负的(-1)表示滚轮向下滚动。值为正的(1)表示滚轮向上滚动。
    • deltaFactor:增量因子,通过deltaFactor*deltaX或者deltaFactor*deltaY可以得到浏览器实际的滚动距离。

     

    8.2.二维码模块

    此插件来源于 qrcodejs,使用方式:

    <div id="xxx"></div>
    <script>
        layui.use(['QRCode'], function () {
            var $ = layui.jquery;
            var QRCode = layui.QRCode;
    
            // 二维码
            var demoQrCode = new QRCode(document.getElementById("xxx"), {
                text: "Hello Word!",
                width: 101,  // 宽度
                height: 101,  // 高度
                colorDark: "#000000",  // 颜色
                colorLight: "#ffffff",  // 背景颜色
                correctLevel: QRCode.CorrectLevel.H
            });
    
            // 更换内容
            demoQrCode.makeCode("Easyweb");
    
        });
    </script>

     

    8.3.引导插件

    此插件来源于 intro.js,并对样式进行了微调,使用方式:

    <div data-step="1" data-intro="这是步骤一">步骤一</div>
    <div data-step="2" data-intro="这是步骤二">步骤二</div>
    <script>
        layui.use(['introJs'], function () {
            var introJs = layui.introJs;
    
            // 初始化
            introJs().start();
    
        });
    </script>

     

    8.4.剪贴板

    此插件来源于 clipboard.js,使用方式:

    <input id="foo" value="https://github.com/zenorocha/clipboard.js.git">
    <button id="btnCopy" data-clipboard-target="#foo">复制</button>
    <script>
        layui.use(['ClipboardJS'], function () {
            var ClipboardJS = layui.ClipboardJS;
    
            var clipboard = new ClipboardJS('#btnCopy');
            clipboard.on('success', function(e) {
                e.clearSelection();
            });
    
            clipboard.on('error', function(e) {
                console.error('Action:', e.action);
            });
    
        });
    </script>

    按钮通过data-clipboard-target绑定的不一定是input,div也可以,也不一定用id,jquery选择器都可以。

     

    8.5.视频播放器

    视频播放器使用的是西瓜视频开源的xgplayer,使用方式:

    <div id="demoVideo"></div>
    
    <script>
        layui.use(['Player'], function () {
            var Player = layui.Player;
    
            // 视频播放器
            var player = new Player({
                id: "demoVideo",
                url: "//s1.pstatp.com/cdn/expire-1-M/byted-player-videos/1.0.0/xgplayer-demo.mp4",  // 视频地址
                poster: "https://imgcache.qq.com/open_proj/proj_qcloud_v2/gateway/solution/general-video/css/img/scene/1.png",  // 封面
                fluid: true,  // 宽度100%
                playbackRate: [0.5, 1, 1.5, 2],  // 开启倍速播放
                pip: true,  // 开启画中画
                lang: 'zh-cn'
            });
    
            // 开启弹幕
            var dmStyle = {
                color: '#ffcd08', fontSize: '20px'
            };
            var player = new Player({
                id: "demoVideo2",
                url: "http://demo.htmleaf.com/1704/201704071459/video/2.mp4",  // 视频地址
                autoplay: false,
                fluid: true,  // 宽度100%
                lang: 'zh-cn',
                danmu: {
                    comments: [
                        {id: '1', start: 0, txt: '空降', color: true, style: dmStyle, duration: 15000},
                        {id: '2', start: 1500, txt: '前方高能', color: true, style: dmStyle, duration: 15000},
                        {id: '3', start: 3500, txt: '弹幕护体', color: true, style: dmStyle, duration: 15000},
                    ]
                }
            });
    
        });
    </script>

     

    8.6.富文本编辑器

    富文本编辑器使用的是TinyMCE,查看中文文档

    <textarea id="demoEditor"></textarea>
    
    <script type="text/javascript" src="assets/libs/tinymce/tinymce.min.js"></script>
    <script>
    layui.use(['layer'], function () {
        var $ = layui.jquery;
        var layer = layui.layer;
    
        // 渲染富文本编辑器
        tinymce.init({
            selector: '#demoEditor',
            height: 525,
            branding: false,
            language: 'zh_CN',
            plugins: 'code print preview fullscreen paste searchreplace save autosave link autolink image imagetools media table codesample lists advlist hr charmap emoticons anchor directionality pagebreak quickbars nonbreaking visualblocks visualchars wordcount',
            toolbar: 'fullscreen preview code | undo redo | forecolor backcolor | bold italic underline strikethrough | alignleft aligncenter alignright alignjustify | outdent indent | numlist bullist | formatselect fontselect fontsizeselect | link image media emoticons charmap anchor pagebreak codesample | ltr rtl',
            toolbar_drawer: 'sliding',
            images_upload_url: '../../../json/tinymce-upload-ok.json',
            file_picker_types: 'media',
            file_picker_callback: function (callback, value, meta) {
                layer.msg('演示环境不允许上传', {anim: 6});
            },
            init_instance_callback: function (editor) {
                console.log(editor);
                // 编辑器渲染完成回调,回显值应该在这里回显
                // tinymce.get('demoEditor').setContent('<span>Hello</span>');
            }
        });
    
        // 获取内容
        var content = tinymce.get('demoEditor').getContent();
    
        // 获取纯文本
        var content = tinymce.get('demoEditor').getContent({format: 'text'});
    
        // 设置内容
        tinymce.get('demoEditor').setContent('<span>Hello</span>');
    
        // 插入内容
        tinymce.get('demoEditor').insertContent('👍赞~', {});
    
    });
    </script>

    弹窗中使用应该在弹窗关闭后销毁编辑器实例:

    admin.open({
        type: 1,
        content: '<textarea id="demoEditor2"></textarea>',
        success: function () {
            // 渲染编辑器
            tinymce.init({
                selector: '#demoEditor2'
            });
        },
        end: function () {
            // 销毁编辑器
            tinymce.get('demoEditor2').destroy(false);
        }
    });

    解决弹窗遮挡富文本组件:

    <!-- 页面加入样式 -->
    <style>
        body .tox-tinymce-aux {
            z-index: 19892000 !important;
        }
    </style>

    单页面中使用应该在页面卸载后销毁编辑器实例:

    // 渲染编辑器
    tinymce.init({
        selector: '#demoEditor'
    });
    
    // 监听页面卸载并销毁编辑器
    admin.on('destroy(plugin/other/editor)', function () {
        tinymce.get('demoEditor').destroy(false);
    });

    如果你多个页面都用到了TinyMCE,建议js的引用放在index.html中:

    <script type="text/javascript" src="assets/libs/tinymce/tinymce.min.js"></script>

     

     

    9.1.主题功能

    默认的样式以及内置的几套主题都在admin.css中,如果要自定义主题步骤如下:

    1. 前往 主题生成器 在线定制主题;
    2. 将生成的css放在admin.css里面,也可以像admin.css一样引入,可以直接通过<style>写在页面中,也可以建一个theme-all.css引入, 将所有生成的主题都放在这个css文件里面;
    3. 打开“page/tpl/tpl-theme.html”添加生成的主题:
       <div class="more-theme-list">
           <!-- data-theme写主题的名称 -->
           <div class="more-theme-item" data-theme="theme-cyan">
               <img src="assets/module/img/theme-cyan.png"/>
           </div>
        </div>

    主题的预览图在主题生成器中会生成,右键可保存为图片,theme-all.css最好在admin.css之后引入。

    设置默认主题也会闪一下才会切换怎么办:

    因为主题切换是通过js切换的,js都是在css、html加在完毕之后执行的,有一点点延迟也很正常,而且换主题是换class, 大部分组件都写有transition的0.3s的css过渡效果,解决办法只能是直接在index.html的body上面加上主题对应的class:

    <body class="theme-red" data-theme="theme-red"></body>

    或者直接修改下主题的css,把前面的.theme-xxx改成body,这种方法只适合固定一套主题不需要切换的情况。

     

    9.2.自定义扩展模块

    集成社区模块:

    把下载好的模块放在/assets/module/下面,如果模块是一个js,不用做任何配置就可以使用了, 例如admin.js、index.js,如果模块是一个文件夹,还需要在main.js中配置模块的具体位置,如notice/notice

    自定义扩展模块:

    如果需要自己写一个扩展模块,请前往阅读Layui定义模块的开发文档, 或者参考admin.js、index.js等模块。

    集成jquery插件:

    jquery作为老牌框架,有着丰富的第三方插件,把插件放入libs下,页面中先引入jquery,再引入插件,即可使用。 当然更友好的集成方式是把它改造成layui扩展模块,改造方式请参考layui 封装第三方组件

     

    9.3.spa全部用iframe

    SPA单页面的缺点已经很明显了,就是ID不能重复(即使是多个页面),这个缺点只能通过规范ID命名来解决,或者关闭多标签模式, 或者标签全部用iframe。

    在3.1.6版本后menu.json新支持了iframe字段:

    {
        "name": "用户管理",
        "url": "#/system/user",
        "iframe": "http://baidu.com"
    }

    当浏览器访问#/system/user时,框架默认是通过ajax加载components/system/user.html的内容拼接到index.html中, 如果有iframe字段就是把<iframe src="http://baidu.com">拼接到index.html中,所以如果把菜单这样配置,就相当于iframe版的形式:

    {
        "name": "用户管理",
        "url": "#/system/user",
        "iframe": "components/system/user.html"
    }

    这样配置后user.html就不再是一个代码片段了,要完整的包含layui.css、admin.css、layui.js,而且还要参照main.js配置:

    layui.config({
        base: getProjectUrl() + 'assets/module/'
    }).extend({
        /// ......省略
    }).use(['layer', 'admin'], function () {
       var $ = layui.jquery;
       var layer = layui.layer;
       var admin = layui.admin;
    
    });

    你可以把这段js写一个common.js作为公共引用,你可以直接让后端返回这样的menu数据格式,也可以在注册路由的时候格式化数据, index模块有介绍,getProjectUrl()这个方法可以让不同路径的子界面都可以正确配置模块位置,这个方法的实现在前面main.js章节中有介绍。

     

     

    10.弹窗专题

    Layui没有像Bootstrap那样的直接写在页面中的模态弹窗,而是通过layer模块调用js弹出,对于用习惯了bootstrap了的可能不太适应, 下面介绍几种实现表单弹窗不同方式。

    10.1.第一种 页面层弹窗

    页面层弹窗就是弹窗页面和列表页面在一个html中,弹窗类型type=1:

    <button id="btnAddUser" class="layui-btn">添加</button>
    <table id="tableUser" lay-filter="tableUser"></table>
    
    <!-- 表单弹窗,注意这里要用script包起来 -->
    <script type="text/html" id="modelUser">
        <form id="modelUserForm" lay-filter="modelUserForm" class="layui-form model-form">
            <input name="userId" type="hidden"/>
            <div class="layui-form-item">
                <label class="layui-form-label">用户名</label>
                <div class="layui-input-block">
                    <input name="nickName" class="layui-input" placeholder="请输入角色名" lay-verType="tips" lay-verify="required" required/>
                </div>
            </div>
            <div class="layui-form-item">
                <label class="layui-form-label">性别</label>
                <div class="layui-input-block">
                    <input type="radio" name="sex" value="男" title="男" checked/>
                    <input type="radio" name="sex" value="女" title="女"/>
                </div>
            </div>
            <div class="layui-form-item text-right">
                <button class="layui-btn layui-btn-primary" type="button" ew-event="closeDialog">取消</button>
                <button class="layui-btn" lay-filter="modelSubmitUser" lay-submit>保存</button>
            </div>
        </form>
    </script>
    
    <!-- 表格操作列 -->
    <script type="text/html" id="tableBarUser">
        <a class="layui-btn" lay-event="edit">修改</a>
        <a class="layui-btn" lay-event="del">删除</a>
    </script>
    
    <!-- js部分 -->
    <script>
        layui.use(['layer', 'form', 'table', 'admin'], function () {
            var $ = layui.jquery, layer = layui.layer, form = layui.form, table = layui.table, admin = layui.admin;
    
            // 渲染表格
            var insTb = table.render({
                elem: '#tableUser',
                url: '../../json/user.json',
                cols: [[
                    {field: 'nickName', title: '用户名'},
                    {field: 'sex', title: '性别'},
                    {toolbar: '#tableBarUser', title: '操作'}
                ]]
            });
    
            // 添加
            $('#btnAddUser').click(function () {
                showEditModel();
            });
    
            // 工具条点击事件
            table.on('tool(tableUser)', function (obj) {
                var data = obj.data;
                var layEvent = obj.event;
                if (layEvent === 'edit') { // 修改
                    showEditModel(data);
                } else if (layEvent === 'del') { // 删除
                    layer.msg('点击了删除', {icon: 2});
                }
            });
    
            // 显示表单弹窗
            function showEditModel(mUser) {
                admin.open({
                    type: 1,
                    title: (mUser ? '修改' : '添加') + '用户',
                    content: $('#modelUser').html(),  // 注意这里有.html()
                    success: function (layero, dIndex) {
                        var url = mUser ? '/updateUser' : '/addUser';
                        form.val('modelUserForm', mUser);  // 回显数据
                        // 表单提交事件
                        form.on('submit(modelSubmitUser)', function (data) {
                            layer.load(2);
                            $.post(url, data.field, function (res) {
                                layer.closeAll('loading');
                                if (res.code == 200) {
                                    layer.close(dIndex);
                                    layer.msg(res.msg, {icon: 1});
                                    insTb.reload();  // 保存成功刷新表格
                                } else {
                                    layer.msg(res.msg, {icon: 2});
                                }
                            }, 'json');
                            return false;
                        });
                    }
                });
            }
    
        });
    </script>

    通过content: $("#modelUser").html()是指定弹窗内容,表单使用<script type="text/html">而不是使用div, 这样表单就不会默认显示出来,操作表单的代码都要写在success里面,因为弹窗是把表单的html复制一份动态插入到页面上, 这种方式修改回显数据、修改完刷新表格都比较方便。

    切记: 这种写法的弹窗所有操作弹窗内元素的代码都要放在弹窗的success里面。

     

    10.2.第二种 iframe弹窗

    iframe弹窗是弹窗内容页面和表格页面是两个页面,减少每个页面的代码量,弹窗类型type=2。

    表格页面,list.html:

    <button id="btnAddUser" class="layui-btn">添加</button>
    <table id="tableUser" lay-filter="tableUser"></table>
    
    <!-- 表格操作列 -->
    <script type="text/html" id="tableBarUser">
        <a class="layui-btn" lay-event="edit">修改</a>
        <a class="layui-btn" lay-event="del">删除</a>
    </script>
    
    <!-- js部分 -->
    <script>
        layui.use(['layer', 'table', 'admin'], function () {
            var $ = layui.jquery, layer = layui.layer, table = layui.table, admin = layui.admin;
    
            // 渲染表格
            var insTb = table.render({
                elem: '#tableUser',
                url: '../../json/user.json',
                cols: [[
                    {field: 'nickName', title: '用户名'},
                    {field: 'sex', title: '性别'},
                    {toolbar: '#tableBarUser', title: '操作'}
                ]]
            });
    
            // 添加
            $('#btnAddUser').click(function () {
                showEditModel();
            });
    
            // 工具条点击事件
            table.on('tool(tableUser)', function (obj) {
                var data = obj.data;
                var layEvent = obj.event;
                if (layEvent === 'edit') { // 修改
                    showEditModel(data);
                } else if (layEvent === 'del') { // 删除
                    layer.msg('点击了删除', {icon: 2});
                }
            });
    
            // 显示表单弹窗
            function showEditModel(mUser) {
                var layIndex = admin.open({
                    type: 2,
                    title: (mUser ? '修改' : '添加') + '用户',
                    content: 'userForm.html',
                    data: { user: mUser },  // 使用data参数传值给弹窗页面
                    end: function () {  // 监听弹窗关闭
                        if (admin.getLayerData(layIndex, 'formOk')) {  // 判断表单操作成功标识
                            insTb.reload();  // 成功刷新表格
                        }
                    }
                });
            }
    
        });
    </script>

    弹窗页面,userForm.html:

    <html>
    <head>
        <link rel="stylesheet" href="assets/libs/layui/css/layui.css"/>
        <link rel="stylesheet" href="assets/module/admin.css"/>
    </head>
    <body>
    <form id="modelUserForm" lay-filter="modelUserForm" class="layui-form model-form">
        <input name="userId" type="hidden"/>
        <div class="layui-form-item">
            <label class="layui-form-label">用户名</label>
            <div class="layui-input-block">
                <input name="nickName" class="layui-input" placeholder="请输入角色名" lay-verType="tips" lay-verify="required" required/>
            </div>
        </div>
        <div class="layui-form-item">
            <label class="layui-form-label">性别</label>
            <div class="layui-input-block">
                <input type="radio" name="sex" value="男" title="男" checked/>
                <input type="radio" name="sex" value="女" title="女"/>
            </div>
        </div>
        <div class="layui-form-item text-right">
            <button class="layui-btn layui-btn-primary" type="button" ew-event="closeDialog">取消</button>
            <button class="layui-btn" lay-filter="modelSubmitUser" lay-submit>保存</button>
        </div>
    </form>
    <!-- js部分 -->
    <script type="text/javascript" src="assets/libs/layui/layui.js"></script>
    <script type="text/javascript" src="assets/js/common.js"></script>
    <script>
        layui.use(['layer', 'form', 'admin', 'formX'], function () {
            var $ = layui.jquery, layer = layui.layer, form = layui.form, admin = layui.admin, formX = layui.formX;
    
            var mUser = admin.getLayerData().user;  // 获取列表页面传递的数据
            // 回显数据,这里一定要用formX.val,form.val不能回显跨iframe的数据
            formX.val('modelUserForm', mUser);
            // 表单提交事件
            form.on('submit(modelSubmitUser)', function (data) {
                layer.load(2);
                var url = mUser ? '/updateUser' : '/addUser';
                $.post(url, data.field, function (res) {
                    layer.closeAll('loading');
                    if (res.code == 200) {
                        layer.msg(res.msg, {icon: 1});
                        admin.putLayerData('formOk', true);  // 设置操作成功的标识
                        admin.closeThisDialog();  // 关闭当前iframe弹窗
                    } else {
                        layer.msg(res.msg, {icon: 2});
                    }
                }, 'json');
                return false;
            });
    
        });
    </script>
    </body>
    </html>

    content参数写表单的页面url,在end回调里面判断操作成功的标识然后刷新表格,end是弹窗关闭的回调, 参数传递的详细介绍请看下面章节的详细介绍。

    iframe弹窗的优点是页面独立,减少代码量,降低耦合,缺点是如果页面有下拉框、日期选择等,它们的范围不能超出弹窗的范围, 会导致弹窗出现滚动条,甚至不显示出来,下面章节介绍的url方式弹窗解决了这些缺点。

     

    10.3.第三种 url方式弹窗

    url方式弹窗就是使用url参数将弹窗页面独立出来,url参数admin.open特有的。

    弹窗页面,userForm.html:

    <!-- 注意这里不需要写`<html><body>`这些东西,它是一个html片段,不是完整的html页面 -->
    <form id="modelUserForm" lay-filter="modelUserForm" class="layui-form model-form">
        <input name="userId" type="hidden"/>
        <div class="layui-form-item">
            <label class="layui-form-label">用户名</label>
            <div class="layui-input-block">
                <input name="nickName" class="layui-input" placeholder="请输入用户名" lay-verType="tips" lay-verify="required" required/>
            </div>
        </div>
        <div class="layui-form-item">
            <label class="layui-form-label">性别</label>
            <div class="layui-input-block">
                <input type="radio" name="sex" value="男" title="男" checked/>
                <input type="radio" name="sex" value="女" title="女"/>
            </div>
        </div>
        <div class="layui-form-item text-right">
            <button class="layui-btn layui-btn-primary" type="button" ew-event="closeDialog">取消</button>
            <button class="layui-btn" lay-filter="modelSubmitUser" lay-submit>保存</button>
        </div>
    </form>
    
    <script>
        layui.use(['layer', 'form', 'admin'], function () {
            var $ = layui.jquery, layer = layui.layer, form = layui.form, admin = layui.admin;
    
            var mUser = admin.getLayerData('#modelUserForm').user;  // 列表页面传递的数据,#modelUserForm这个只要写弹窗内任意一个元素的id即可
            form.val('modelUserForm', mUser);  // 回显数据
            // 表单提交事件
            form.on('submit(modelSubmitUser)', function (data) {
                layer.load(2);
                var url = mUser ? '/updateUser' : '/addUser';
                $.post(url, data.field, function (res) {
                    layer.closeAll('loading');
                    if (res.code == 200) {
                        layer.msg(res.msg, {icon: 1});
                        admin.putLayerData('formOk', true, '#modelUserForm');  // 设置操作成功的标识,#modelUserForm这个只要写弹窗内任意一个元素的id即可
                        admin.closeDialog('#modelUserForm');  // 关闭页面层弹窗
                    } else {
                        layer.msg(res.msg, {icon: 2});
                    }
                }, 'json');
                return false;
            });
    
        });
    </script>

    表格页面,list.html:

    <button id="btnAddUser" class="layui-btn">添加</button>
    <table id="tableUser" lay-filter="tableUser"></table>
    
    <!-- 表格操作列 -->
    <script type="text/html" id="tableBarUser">
        <a class="layui-btn" lay-event="edit">修改</a>
        <a class="layui-btn" lay-event="del">删除</a>
    </script>
    
    <!-- js部分 -->
    <script>
        layui.use(['layer', table', 'admin'], function () {
            var $ = layui.jquery, layer = layui.layer, table = layui.table, admin = layui.admin;
    
            // 渲染表格
            var insTb = table.render({
                elem: '#tableUser',
                url: '../../json/user.json',
                cols: [[
                    {field: 'nickName', title: '用户名'},
                    {field: 'sex', title: '性别'},
                    {toolbar: '#tableBarUser', title: '操作'}
                ]]
            });
    
            // 添加
            $('#btnAddUser').click(function () {
                showEditModel();
            });
    
            // 工具条点击事件
            table.on('tool(tableUser)', function (obj) {
                var data = obj.data;
                var layEvent = obj.event;
                if (layEvent === 'edit') { // 修改
                    showEditModel(data);
                } else if (layEvent === 'del') { // 删除
                    layer.msg('点击了删除', {icon: 2});
                }
            });
    
            // 显示表单弹窗
            function showEditModel(mUser) {
                var layIndex = admin.open({
                    title: (mUser ? '修改' : '添加') + '用户',
                    url: 'userForm.html',
                    data: { user: mUser },     // 传递数据到表单页面
                    end: function () {
                        if (admin.getLayerData(layIndex, 'formOk')) {  // 判断表单操作成功标识
                            insTb.reload();  // 成功刷新表格
                        } 
                    },
                    success: function (layero, dIndex) {
                        // 弹窗超出范围不出现滚动条
                        $(layero).children('.layui-layer-content').css('overflow', 'visible');
                    }
                });
            }
    
        });
    </script>

    使用url参数指定弹窗的页面地址,url这个参数是admin.open新增的,这样做就会把表单页面的html使用ajax加载到弹窗中, 而不是iframe嵌入,这样表单里面的下拉框、日期等组件就可以超出弹窗的范围,不会导致弹窗出现滚动条。

    注意:表单页面是html片段,表单页面和表格页面不要出现重复的id,因为最终是在一个页面上

     

    10.7.第四种 捕获层弹窗

    第一种页面层弹窗由于所有关于弹窗内元素的操作都要写在弹窗的success里面, 部分人可能不适应这种方式,所以介绍第四种捕获层弹窗:

    <!-- 表单弹窗,加display: none默认隐藏 -->
    <form style="display: none;" id="modelRoleForm" lay-filter="modelRoleForm" class="layui-form model-form">
        <input name="roleId" type="hidden"/>
        <div class="layui-form-item">
            <label class="layui-form-label">角色名</label>
            <div class="layui-input-block">
                <input name="roleName" class="layui-input" placeholder="请输入角色名" lay-verType="tips" lay-verify="required" required/>
            </div>
        </div>
        <div class="layui-form-item">
            <label class="layui-form-label">备注</label>
            <div class="layui-input-block">
                <textarea name="comments" placeholder="请输入内容" class="layui-textarea"></textarea>
            </div>
        </div>
        <div class="layui-form-item text-right">
            <button class="layui-btn layui-btn-primary" type="button" ew-event="closeDialog">取消</button>
            <button class="layui-btn" lay-filter="modelSubmitRole" lay-submit>保存</button>
        </div>
    </form>
    <!-- js部分 -->
    <script>
        layui.use(['layer', 'form', 'table', 'admin'], function () {
            var $ = layui.jquery, layer = layui.layer, form = layui.form, table = layui.table,admin = layui.admin;
            var formUrl;
    
            // 渲染表格
            var insTb = table.render({...});
    
            // 添加
            $('#btnAddRole').click(function () {
                showEditModel();
            });
    
            // 表格工具条点击事件
            table.on('tool(tableRole)', function (obj) {
                var data = obj.data;
                var layEvent = obj.event;
                if (layEvent === 'edit') { // 修改
                    showEditModel(data);
                }
            });
    
            // 显示编辑弹窗
            function showEditModel(mRole) {
                $('#modelRoleForm')[0].reset();  // 重置表单
                form.val('modelRoleForm', mRole);  // 回显数据
                formUrl = mRole ? 'role/update' : 'role/add';
                admin.open({
                    type: 1,
                    fixed: true,  // 加这个可解决没有居中的问题
                    title: (mRole ? '修改' : '添加') + '角色',
                    content: $('#modelRoleForm')   // 这里是重点,没有.html()
                });
            }
    
            // 表单提交事件
            form.on('submit(modelSubmitRole)', function (data) {
                layer.load(2);
                $.post(formUrl, data.field, function (res) {
                    layer.closeAll('loading');
                    if (res.code == 200) {
                        admin.closeDialog('#modelRoleForm');
                        layer.msg(res.msg, {icon: 1});
                        insTb.reload();
                    } else {
                        layer.msg(res.msg, {icon: 2});
                    }
                }, 'json');
                return false;
            });
    
        });
    </script>

    与第一种的区别是form不用<script>包裹,加style="display:none"隐藏, admin.open的content是$('#roleForm')而不是$('#roleForm').html(), 表单的提交事件可以直接写在外面,而不用写在弹窗的success里面。

    捕获层的弊端就是弹窗的页面代码最好是写在body下面,不然样式会被其他样式影响。

     

    10.4.四种方式选择指南

    方式推荐理由
    第一、四种建议初学者使用这种不涉及两个页面传值问题
    第二种iframe推荐表单跟表格无交互使用,比如详情下拉框、日期不能超出弹窗
    第三种url表单弹窗、页面有交互建议使用页面传值方便,不存在问题

    如果四种弹窗方式的用法都掌握了更好,这四种足以灵活应对各种业务场景了。

     

    10.5.admin.modelForm方法

    此方法是把layer弹窗自带的确定按钮绑定成表单的提交按钮:

    <!-- 表单弹窗 -->
    <script type="text/html" id="modelUser">
        <div class="layui-form-item">
            <label class="layui-form-label">用户名</label>
            <div class="layui-input-block">
                <input name="nickName" class="layui-input" lay-verType="tips" lay-verify="required" required/>
            </div>
        </div>
        <div class="layui-form-item">
            <label class="layui-form-label">备注</label>
            <div class="layui-input-block">
                <textarea name="comments" class="layui-textarea"></textarea>
            </div>
        </div>
    </script>
    
    <!-- js部分 -->
    <script>
        layui.use(['layer', 'form', 'admin'], function () {
            var $ = layui.jquery, layer = layui.layer, form = layui.form, admin = layui.admin;
    
            admin.open({
                type: 1,
                title: '添加用户',
                btn: ['确定', '取消'],
                content: $('#modelUser').html(),
                success: function (layero, dIndex) {
                    // 把确定按钮绑定表单提交,参数二是给按钮起一个lay-filter,参数三是给表单起一个lay-filter
                    admin.modelForm(layero, 'demoFormSubmit', 'demoForm');
                    // 给表单赋值
                    form.val('demoForm', {nickName: '张三', sex: '男'}); 
                    // 监听表单提交
                    form.on('submit(demoFormSubmit)', function (data) {
                        layer.msg(JSON.stringify(data.field));
                        return false;
                    });
                },
                yes: function () {
                    // 确定按钮方法什么都不要操作
                }
            });
    
        });
    </script>

    admin.modelForm()这个方法会把弹窗外面包一个form,然后把确定按钮加lay-submit,所以你的表单页面不需要写form和确定按钮,只需要写表单项。

    这个方法的使用场景为你想要表单的按钮固定,只滚动表单内容部分,可以用这个操作, 当然前面介绍的4中方式也是支持固定按钮的,请到css组件样式中查看详细介绍。

     

    10.6.参数传递方法详解

    参数传递:

    admin.open({
        type: 2,
        content: 'userForm.html',
        data: {
            name: '李白',
            sex: '男'
        }
    });

    通过data属性进行参数传递,data同样是admin.open新增的参数。

    获取参数:

    方法说明参数
    admin.getLayerData(index)获取某弹窗的全部参数layer的index
    admin.getLayerData(index, key)参数某弹窗参数的某个字段index,字段
    admin.getLayerData()iframe弹窗子页面获取参数无任何参数
    admin.getLayerData('#xxForm')url方式弹窗子页面获取参数弹窗内任意元素id

    如果是在iframe弹窗的子页面中可以使用admin.getLayerData()直接获取父页面传递的全部参数, 如果是在url方式打开的弹窗中可以使用admin.getLayerData('#xx')直接获取父页面的全部参数,'#xx'是弹窗内任意元素的id。

    增加参数:

    方法说明参数
    admin.putLayerData(key, value, index)增加参数字段名,值,index
    admin.putLayerData(key, value)iframe弹窗子页面增加参数字段名,值
    admin.putLayerData(key, value, '#xx')url方式弹窗子页面增加参数弹窗内任意元素id

    关于子页面向父页面传递参数,子页面put新参数,父页面根据弹窗的index取参数就可以了,上面四种方式弹窗中就有示例, 子页面修改成功了put了一个formOk的标识,父页面通过这个标识判断是否要刷新表格。

    注意: data参数必须是对象的形式,data: 1、data: 'aa'这种写法会导致无法put新参数。

     

    10.7.刷新url方式弹窗

    admin.reloadLayer(index, url, success);
    • index     弹窗的index,可以用admin.getLayerIndex('#elem')获取页面层index
    • url       用新的url刷新(可不填)
    • success   刷新完成的回调,function类型(可不填)

    iframe弹窗可以用location.reload()或者iframe.contentWindow.location.reload()来刷新弹窗页面。

     

    10.8.弹窗使用模板引擎

    admin.open({
        url: 'dialog-url.html',
        data: {
            name: '妲己',
            sex: '女'
        },
        tpl: true  // 增加tpl:true开启模板引擎
    });

    dialog-url.html代码:

    <div>NAME: {{d.name}}</div>
    <div>SEX: {{d.sex}}</div>
    <a class="layui-btn" ew-event="closeDialog">关闭我</a>
    <script>
        layui.use(['layer'], function () {
            var $ = layui.jquery;
    
        });
    </script>

    模板引擎语法同laytpl,d表示弹窗传递的数据,页面层也支持tpl: true,捕获层和iframe层不支持, 可以使用动态模板功能。

     

    11.1.跨页面操作

    单页面是可以直接跨页面操作的:

    table.reload('userTab', {});  // 刷新其他页面表格

    layui.use里面定义的变量想在其他页面访问:

    layui.use(['layer'], function() {
    
        window.xxx = 'xxxx';  // 变量给其他页面访问
    
        // 方法给其他页面访问
        window.xxx = function(){
            alert('aa');
        };
    });

     

    11.2.nginx部署解决跨域

    部署只需要把前端所有代码放在nginx的html中,修改setter.js的baseServer为接口地址即可, 如果接口没有做跨域支持,可使用nginx反向代理来解决跨域问题:

    1. 打开“nginx/conf/nginx.conf”配置文件
    2. 设置反向代理:
       http {
           server {
               # 加入以下配置,之前的配置全部不要动,这个location是新加入的
               location /api/ {
                   proxy_pass  http://11.11.111.111:8088/; # 这个是后台接口所在的地址
               }
           }
       }
    3. 修改setter.js里面的baseServer为/api/。

    这样配置接口就会访问localhost:80/api/,然后nginx再反向代理到实际接口。

     

    11.3.多系统模式

    在header中有几个选项:“xx系统”、“xx系统”,点击不同的系统切换不同的侧边菜单,查看演示

    侧边栏代码,使用nav-id标识不同的菜单:

    <div class="layui-side">
        <div class="layui-side-scroll">
            <!-- 系统一的菜单,每个ul都加nav-id -->
            <ul nav-id="xt1" class="layui-nav layui-nav-tree" lay-filter="admin-side-nav">
                <!-- ...省略代码... -->
            </ul>
            <!-- 系统二的菜单,加layui-hide隐藏 -->
            <ul nav-id="xt2" class="layui-nav layui-nav-tree layui-hide" lay-filter="admin-side-nav">
                <!-- ...省略代码... -->
            </ul>
        </div>
    </div>

    header.html代码,使用nav-bind绑定侧边栏菜单:

    <div class="layui-header">
        <ul class="layui-nav layui-layout-left">
            <li class="layui-nav-item"><a nav-bind="xt1">系统一</a></li>
            <li class="layui-nav-item"<a nav-bind="xt2">系统二</a></li>
        </ul>
    </div>

     

    11.4.logo文字换行显示

    <div class="layui-logo">
        <img src="assets/images/logo.png"/>
        <cite style="display: inline-block;line-height: inherit;margin-top: -4px;">
            EasyWeb<br/>iframe
        </cite>
    </div>

     

    11.5.侧边栏全部展开

    首先要去掉lay-shrink="_all"这个属性关闭手风琴,然后加layui-nav-itemed默认展开:

    <ul class="layui-nav layui-nav-tree" lay-filter="admin-side-nav" lay-shrink="false">
        <li class="layui-nav-item layui-nav-itemed">
            ......省略
        </li>
        <li class="layui-nav-item layui-nav-itemed">
            ......省略
        </li>
    </ul>

    3.1.8之前的版本由于修改了layui还需要在layui-nav-child上加style:

    <ul class="layui-nav layui-nav-tree" lay-filter="admin-side-nav" lay-shrink="false">
        <li class="layui-nav-item layui-nav-itemed">
            <a>Dashboard</a>
            <dl class="layui-nav-child" style="display: block;">
                <dd><a>工作台</a></dd>
            </dl>
        </li>
    </ul>

     

    11.6.侧边栏折叠图标放大

    侧边栏折叠后图标会进行放大,如果要修改大小添加css修改font-size,如果不想放大改成14px:

    @media screen and (min-width: 750px) {
        .layui-layout-admin.admin-nav-mini .layui-side .layui-nav .layui-nav-item > a > .layui-icon {
            font-size: 18px;
        }
    }

     

    11.7.弹窗下拉框出现滚动条

    非iframe类型的弹窗才能解决(页面层、捕获层、url方式等):

     admin.open({
        type: 1,
        title: '添加用户',
        content: $('#model').html(),
        success: function (layero, index) {
            // 禁止出现滚动条,关键代码就是这句
            $(layero).children('.layui-layer-content').css('overflow', 'visible'); 
        }
    });

     

    11.8.弹窗宽度不能超出屏幕

    这个是针对手机屏幕下做了让弹窗宽度自适应,如果需要让弹窗宽度超出屏幕:

    admin.open({
        title: '添加用户',
        content: $('#model').html(),
        success: function (layero, index) {
            $(layero).css('max-width', 'unset');   // 去掉max-width属性,unset在ie无效可以用auto
        }
    });

     

    11.9.表单文字出现换行

    layui的表单左边标题最多显示5个字,超出会换行,添加css修改宽度:

    #userForm .layui-form-label {
        width: 100px;  /* 这里修改标题宽度 */
    }
    
    #userForm .layui-input-block {
        margin-left: 130px;  /* 这里要比上面始终大30px */
    }

    #userForm是表单的id,加id避免影响其他表单样式:

    <form id="userForm" class="layui-form">
        <div class="layui-form-item">
            <label class="layui-form-label">活动起止时间</label>
            <div class="layui-input-block">
                <input type="text" class="layui-input"/>
            </div>
        </div>
        <div class="layui-form-item">
            <label class="layui-form-label">活动详细介绍</label>
            <div class="layui-input-block">
                <textarea class="layui-textarea" maxlength="200"></textarea>
            </div>
        </div>
    </form>

     

    11.10.select、radio不显示

    select(下拉框)、radio(单选框)等表单元素在layui中会被美化,对于动态生成的元素需要重新渲染才能美化:

    $('div').appen('<select><option value="1">xxxx</option></select>');
    form.render('select');  // 重新渲染select
    form.render('radio');  // 重新渲染radio
    form.render('checkbox');  // 重新渲染checkbox
    
    // 对于弹窗内select不显示
    admin.open({
        type: 1,
        content: '<select><option value="1">xxxx</option></select>',
        success: function(){
            form.render('select');  // 弹窗要在success里重新渲染
        }
    });

    另外需要注意父元素有layui-form这个class才会被layui识别并美化。

     

    11.11.日期laydate不能显示

    如果是因为窗口太小不能显示,可以加个trigger: 'click'解决:

    laydate.render({
        elem: '#xxx',
        type: 'date',
        trigger: 'click'
    });

    如果是弹窗中的laydate不显示,检查是否是在弹窗的success里面渲染的:

    admin.open({
        type: 1,
        content: $('#modelUser').html(),
        success: function (layero, dIndex) {
            laydate.render({
                elem: '#xxx',
                type: 'date',
            });
        }
    });

     

    11.12.弹窗打开后按enter无限打开

    弹窗打开后焦点还位于点击打开的按钮上,就会导致按enter键无限打开,解决办法就是让焦点移到其他元素上, 下面是将焦点移到弹窗内表单提交按钮上:

    admin.open({
        type: 1,
        title: '添加用户',
        content: $('#userEditDialog').html(),
        success: function (layero, dIndex) {
            $(layero).find('[lay-submit]').focus();
        }
    });

     

    11.13.表单提交post变成了get

    首先检查监听表单提交事件里面有没有写return false,表单里面如果有其他按钮要加type="button",如果还会导致点击按钮刷新页面, 一般是你的代码有报错的地方,建议将<form class="layui-form"></form>改成<div class="layui-form"></div>,form改成div对表单提交不会有任何影响, 只是不能按回车键提交表单,不能重置表单了,改成div后报错就不会导致刷新页面了,你可以看控制台里面的错误信息。

    <form class="layui-form">
        <div class="layui-form-item">
            <div class="layui-inline">
                <label class="layui-form-label">账号:</label>
                <div class="layui-input-inline">
                    <input name="username" class="layui-input" placeholder="输入账号"/>
                </div>
            </div>
            <div class="layui-inline">
                <label class="layui-form-label">用户名:</label>
                <div class="layui-input-inline">
                    <input name="nickName" class="layui-input" placeholder="输入用户名"/>
                </div>
            </div>
            <div class="layui-inline">
                <button class="layui-btn" lay-filter="userTbSearch" lay-submit>搜索</button>
                <button type="reset" class="layui-btn">重置</button>
            </div>
        </div>
    </form>
    <script>
    /* 监听表单提交 */
    form.on('submit(userTbSearch)', function (data) {
        return false;
    });
    </script>

     

    11.14.修改表格背景和边框颜色

    /* 表格背景颜色 */
    .layui-table tbody tr:hover, .layui-table thead tr,
    .layui-table-click, .layui-table-header, .layui-table-hover, .layui-table-mend,
    .layui-table-patch, .layui-table-tool, .layui-table-total, .layui-table-total tr,
    .layui-table[lay-even] tr:nth-child(even) {
        background-color: #f5f7fa;
    }
    
    /* 表格边框颜色 */
    .layui-table td, .layui-table th, .layui-table-col-set, .layui-table-fixed-r,
    .layui-table-grid-down, .layui-table-header, .layui-table-page, .layui-table-tips-main,
    .layui-table-tool, .layui-table-total, .layui-table-view, .layui-table[lay-skin=line], .layui-table[lay-skin=row] {
        border-color: #ebeef5;
    }

     

    11.15.修改placeholder颜色

    .layui-input::-webkit-input-placeholder, .layui-textarea::-webkit-input-placeholder {
        color: #ccc;
    }
    
    .layui-input::-moz-placeholder, .layui-textarea::-webkit-input-placeholder {
        color: #ccc;
    }
    
    .layui-input::-ms-input-placeholder, .layui-textarea::-webkit-input-placeholder {
        color: #ccc;
    }
    
    body xm-select > .xm-tips {
        color: #ccc;
    }

     

    11.16.IE数据表格缓存严重

    在渲染和重载表格的时候加一个随机参数:

    /* 渲染表格 */
    var insTb = table.render({
        elem: '#userTable',
        url: '../../json/user.json',
        where: {v: new Date().getTime()},
        cols: [[
            {type: 'checkbox'},
            {type: 'numbers'},
            {field: 'username', title: '账号', sort: true},
            {field: 'nickName', title: '用户名', sort: true}
        ]]
    });
    
    /* 重载表格 */
    form.on('submit(userTbSearch)', function (data) {
        data.field.v = new Date().getTime();
        insTb.reload({where: data.field, page: {curr: 1}});
        return false;
    });
    
    insTb.reload({where: {v: new Date().getTime()}, page: {curr: 1}});

     

    11.17.使用parent.layer问题

    如果用的是parent.layui.admin.open打开的弹窗,弹窗success里面的一些操作也应该相应的加parent:

    function showEditModel(mData) {
        parent.layui.admin.open({
            type: 1,
            title: (mData ? '修改' : '添加') + '用户',
            content: $('#userEditDialog').html(),
            success: function (layero, dIndex) {
                // 回显表单数据
                parent.layui.formX.val('userEditForm', mData);
                // 表单提交事件
                parent.layui.form.on('submit(userEditSubmit)', function (data) {
                    return false;
                });
                // 禁止弹窗出现滚动条
                parent.layui.jquery(layero).children('.layui-layer-content').css('overflow', 'visible');
            }
        });
    }

    需要注意的是parent.layui.form.val不支持跨iframe的数据,可以使用formX模块,$应该用parent.layui.jquery

    如果你喜欢跨iframe操作,你需要了解window、parent、top:

    <iframe id="child" src="child.html"></iframe>
    <script>
    layui.use(['jquery'], function() {
        var $ = layui.jquery;
    
        window.aaa = 'aaa';  // 定义变量到window下
    
        // 定义方法到window下
        window.bbb = function(str) {
            alert(str);
        };
    
        // 访问iframe的变量
        var childWin = $('#child')[0].contentWindow;
        console.log(childWin.ccc);
        childWin.location.reload();  // 刷新iframe页面
    });
    </script>

    child.html:

    <script>
    layui.use(['jquery'], function() {
        window.ccc = 'ccc';  // 定义变量到window下
    
        parent.aaa = '__a';  // 修改parent的变量
    
        parent.bbb('bbb');  // 调用parent的方法
    });
    </script>

     

    11.18.表格打印太长列未换行

    // 如果phone这一列全是字母和数字并且很长打印的时候不会自动换行
    {field: 'phone', title: '手机号'}
    
    // 改成这样就会自动换行了
    {
        field: 'phone', title: '手机号', 
        templet: '<div><div style="word-break: break-all;">{{d.phone}}</div></div>'
    }

    注意要两个div,样式加在里面的div上面。

     

    11.19.弹窗layer.js报错404

    这个问题一般是由于弹窗是url方式的弹窗,弹窗页面内又引入js、css导致的:

    admin.open({
        url: 'password.html'
    });

    url方式的弹窗页面是片段,不是完整的html,请不要包含<html>、<head>、<body>这些,不要重复引用layui.js:

    <form class="layui-form model-form">
    </form>
    <script>
        layui.use(['layer', 'form'], function () {
        });
    </script>

    如果是主题、修改密码、便签、消息等弹窗出现的,是老版本使用的iframe弹窗方式,新版本默认改成url方式导致的,可升级对应的弹窗页面解决, 也可以配置成iframe弹窗:

    <a ew-event="theme" data-type="2" data-content="page/tpl/tpl-theme.html">主题</a>

     

    11.20.表格请求去掉page和limit

    数据表格即使设置了page: false发送的请求还是会有pagelimit这两个参数,page参数是无法去掉的,只能去掉limit参数:

    table.render({
        elem: '#userTable',
        url: '../../json/user.json',
        page: false,
        limit: null
    });

    后端可以判断如果limit参数为null就不分页查询全部,你也可以规定limit为0或者-1就查询全部。

     

     

    12.1.表格内switch获取行数据

    用户管理演示了表格内开关switch的使用,这里只用到了数据的id修改状态, 如果要获取所在行的更多数据,可以通过加data-属性:

    <script type="text/html" id="userTbState">
        <input type="checkbox" lay-filter="userTbStateCk" value="{{d.userId}}" lay-skin="switch"
               data-name="{{d.username}}" data-sex="{{d.sex}}" lay-text="正常|锁定" {{d.state==0?'checked':''}}/>
    </script>
    <script>
        form.on('switch(userTbStateCk)', function (obj) {
            var id = obj.elem.value;
            var data = $(obj.elem).data();
            console.log(id + data.name + data.sex);
        });
    </script>

    也可以利用LAY_TABLE_INDEX获取:

    <script type="text/html" id="userTbState">
        <input type="checkbox" lay-filter="userTbStateCk" value="{{d.LAY_TABLE_INDEX}}" lay-skin="switch"
               lay-text="正常|锁定" {{d.state==0?'checked':''}}/>
    </script>
    <script>
        form.on('switch(userTbStateCk)', function (obj) {
            var index = obj.elem.value;
            var data = table.cache['userTable'][index];
            console.log(data.userId + data.username);
        });
    </script>

    表格中的下拉框select的用法与表格中的开关switch是一样的,可以参考使用:

    <!-- 表格性别选择列 -->
    <script type="text/html" id="tbBasicTbSex">
        <div class="ew-select-fixed">
            <select lay-filter="tbBasicTbSexSel" data-index="{{d.LAY_INDEX}}">
                <option value="">请选择</option>
                <option value="男" {{d.sex=='男'?'selected':''}}>男</option>
                <option value="女" {{d.sex=='女'?'selected':''}}>女</option>
            </select>
        </div>
    </script>
    <script>
        form.on('select(tbBasicTbSexSel)', function(obj){
            var index = $(obj.elem).data('index');
            var data = table.cache['userTable'][index];
            console.log(data);  // 得到当前行数据
            console.log(obj.value); // 得到被选中的值
        });
    </script>

     

    12.2.表格回显复选框

    var insTb = table.render({
        elem: '#userTable',
        url: '../../json/user.json',
        cols: [[
            {type: 'checkbox'},
            {type: 'numbers'},
            {field: 'username', title: '账号', sort: true},
            {field: 'nickName', title: '用户名', sort: true}
        ]],
        parseData: function(res) {
            res.data[3].LAY_CHECKED = true;  // 让第4条数据选中
            return res;
        }
    });

     

    12.3.表格工具列动态显示

    工具列中可以使用模板引擎语法:

    <script type="text/html" id="userTbBar">
        <a class="layui-btn" lay-event="view">查看</a>
        {{# if(d.state==0){ }}
        <a class="layui-btn" lay-event="send">发送</a>
        {{# }else if(d.state==1){ }}
        <a class="layui-btn" lay-event="back">撤回</a>
        {{# } }}
        <a class="layui-btn" lay-event="del">删除</a>
    </script>

     

    12.4.表单提交数组

    layui的表单提交、赋值等不支持数组及嵌套的格式,可以通过简单的格式处理数据为自己想要的格式:

    <form class="layui-form" lay-filter="demoForm">
        <input name="name" class="layui-input"/>
        <input name="role__0" class="layui-input"/>
        <input name="role__1" class="layui-input"/>
        <input name="role__2" class="layui-input"/>
        <input name="sex__0" class="layui-input"/>
        <input name="sex__1" class="layui-input"/>
        <button class="layui-btn" lay-filter="demoSubmit" lay-submit>提交</button>
    </form>
    <script>
    /* 监听表单提交 */
    form.on('submit(demoSubmit)', function (data) {
        var roleList = [], sexList = [];
        for(var f in data.field) {
            if(f.indexOf('role__') === 0) {
                roleList.push(data.field[f]);
                delete data.field[f];
            }
            if(f.indexOf('sex__') === 0) {
                sexList.push(data.field[f]);
                delete data.field[f];
            }
        }
        data.field.roleList = roleList;
        data.field.sexList = sexList;
        console.log(data.field);
        return false;
    });
    
    /* 赋值 */
    var res = {roleList:[], sexList: []};
    for(var i=0;i<res.roleList.length;i++) {
        res['role__'+i] = res.roleList[i];
    }
    form.val('demoForm', res);
    </script>

     

    12.5.重载表格重置排序

    insTb.reload({
        where: {}, page: {curr: 1}, 
        initSort: {field: 'createTime', type: null}
    });

    field写任意一个字段名称即可。

     

    12.6.laydte动态控制日期限制

    以最小日期限制举例:

    /* 渲染日期 */
    var insDate = laydate.render({
        elem: '#test1',
        min: 7
    });
    var minConfig = insDate.config.min;  // 获取配置的最小日期限制
    
    /* 取消最小日期限制 */
    insDate.config.min = {}; 
    
    /* 恢复最小日期限制 */
    insDate.config.min = minConfig;

     

    12.7.下拉树一些数据不可选

    以演示页面的权限管理为例,让类型为按钮不可选:

    // 这个是treeTable提供的遍历数据的方法
    insTb.eachData(function(i,item){
        if (!item.isMenu) item.disabled = true;  // 如果是按钮设置不可选
    });
    
    // 渲染下拉树
    var insXmSel = xmSelect.render({
        el: '#authoritiesEditParentSel',
        data: insTb.options.data,  // 用treeTabled的数据
        model: {label: {type: 'text'}},
        prop: {
            name: 'authorityName',
            value: 'authorityId'
        },
        radio: true,
        clickClose: true,
        tree: {
            show: true,
            indent: 15,
            strict: false,
            expandedKeys: true
        }
    });

     

    12.8.修改弹窗禁用输入框

    /* 显示表单弹窗 */
    function showEditModel(mData) {
        admin.open({
            type: 1,
            title: (mData ? '修改' : '添加') + '用户',
            content: $('#userEditDialog').html(),
            success: function (layero, dIndex) {
                if(mData) {  // 表示是修改
                    // 把账号输入框变为只读
                    $(layero).find('[name="username"]').attr('readonly', 'readonly');
                    // 把密码输入框移除
                    $(layero).find('[name="password"]').parent().parent().remove();
                }   
            }
        });
    }

     

    12.9.表格中下拉框数据动态

    模板页面/列表页/数据表格 中展示了表格中下拉框的使用,如何将下拉框的数据变为动态的(来源后端的):

    var sexList = [{name: '男', value:0}, {name:'女', value: 1}];
    var sexHtml = '<div><div class="ew-select-fixed"><select lay-filter="tbBasicTbSexSel">';
    layui.each(sexList, function(i,item){
        sexHtml += ('<option value="' + item.value + '">' + item.name + '</option>');
    });
    sexHtml += '</select></div></div>';
    
    /* 渲染表格 */
    var insTb = table.render({
        elem: '#tbBasicTable',
        url: '../../../json/user.json',
        cols: [[
            {type: 'checkbox'},
            {type: 'numbers'},
            {field: 'username', title: '账号', align: 'center', sort: true},
            {field: 'sex', title: '性别', templet: sexHtml, sort: true}
        ]]
    });

    如果数据是ajax请求的,应该用同步的请求,或者在请求结束后再渲染表格:

    var insTb, sexList = [];
    $.get('sex.json', function(res) {
        sexList = res.data;
        var sexHtml = '......省略';
        /* 渲染表格,......省略具体代码 */
        insTb = table.render({});
    });

     

    12.10.实现点击后转一圈

    有一个刷新按钮,用的layui的刷新图标,点击后实现图标转圈,刷新完后停止转圈:

    <i id="btnRefresh" class="layui-icon layui-icon-refresh"></i>
    <script>
    $('#btnRefresh').click(function() {
        $('#btnRefresh').removeClass('layui-anim layui-anim-rotate');
        setTimeout(function() {
            $('#btnRefresh').addClass('layui-anim layui-anim-rotate');
            // $('#btnRefresh').addClass('layui-anim layui-anim-rotate layui-anim-loop');
        });
    });
    </script>

    多加一个classlayui-anim-loop是实现一直转圈,没有这个只会转一圈。

     

    12.11.页面下拉框数据动态

    演示页面里面的下拉框之所以都是直接写的静态的,是因为实际项目中也可能后端渲染,也可能ajax渲染, 如果是前后端不分离项目建议直接用后端模板引擎渲染,如果是前后端分离方式需要用ajax渲染。

    可以页面一进入就先获取下拉框的数据:

    <form class="layui-form" lay-filter="userTbSearchForm">
        性别: <select name="sex"></select>
    </form>
    <!-- 表单弹窗 -->
    <script type="text/html" id="userEditDialog">
        <form id="userEditForm" lay-filter="userEditForm" class="layui-form model-form">
            性别: <select name="sex" lay-verType="tips" lay-verify="required" required></select>
        </form>
    </script>
    <!-- js部分 -->
    <script>
        layui.use(['layer', 'form', 'table', 'formX'], function () {
            var $ = layui.jquery;
            var layer = layui.layer;
            var form = layui.form;
            var admin = layui.admin;
            var formX = layui.formX;
            var mSexList = [];  // 所有性别
    
            /* 获取性别数据字典 */
            var loadIndex = layer.load(2);
            admin.req('sys/dictdata', {dictCode: 'sex'}, function (res) {
                layer.close(loadIndex);
                if (0 === res.code) {
                    mSexList = res.data;
                    // 渲染搜索栏中的性别select
                    formX.renderSelect({
                        elem: '[lay-filter="userTbSearchForm"] select[name="sex"]',
                        data: mSexList,
                        name: 'dictDataName',
                        value: 'dictDataId',
                        hint: '请选择性别'
                    });
                } else {
                    layer.msg(res.msg, {icon: 2});
                }
            });
    
            /* 显示表单弹窗 */
            function showEditModel(mData) {
                admin.open({
                    type: 1,
                    title: (mData ? '修改' : '添加') + '用户',
                    content: $('#userEditDialog').html(),
                    success: function (layero, dIndex) {
                        form.val('userEditForm', mData);  // 回显表单数据
                        // 渲染性别下拉
                        formX.renderSelect({
                            elem: '[lay-filter="userEditForm"] select[name="sex"]',
                            data: mSexList,
                            name: 'dictDataName',
                            value: 'dictDataId',
                            hint: '请选择性别',
                            initValue: mData ? mData.sex : undefined
                        });
                    }
                });
            }
    
        });
    </script>

     

    12.12.表格动态tool事件处理

    <!-- 表格操作列 -->
    <script type="text/html" id="userTbBar">
        {{# layui.each(d.roles, function(i, item) { }}
        <a class="layui-btn" lay-event="role" data-index="{{i}}">{{item.roleName}}</a>
        {{# }); }}
    </script>
    <script>
    table.render({
        elem: '#userTable',
        cols: [[
            {field: 'username', title: '账号'},
            {field: 'sex', title: '性别'},
            {title: '角色', toolbar: '#userTbBar'}
        ]]
    });
    
    /* 表格工具条点击事件 */
    table.on('tool(userTable)', function (obj) {
        var d = obj.data;
        if (obj.event === 'role') {
            var i = $(this).data('index');
            console.log(d.roles[i]);
        }
    });
    </script>

    像上面这样角色是动态循环出来的,想监听点击每一行的每个角色的事件,并且获取到点击的行的数据和点击的角色的数据, 获取行的数据table模块直接提供,如果要获取点击的角色对应的数据,就可以参考上面用data-index来实现。

     

    12.13.表格复选框和序号列合并

    table.render({
        elem: '#userTable',
        cols: [[
            {
                title:'<input type="checkbox" name="layTableCheckbox" lay-skin="primary" lay-filter="layTableAllChoose">',
                templet: '<div><input type="checkbox" name="layTableCheckbox" lay-skin="primary"> {{d.LAY_INDEX}}</div>'
            },
            {field: 'username', title: '账号'},
            {field: 'sex', title: '性别'}
        ]]
    });

    title加全选框,用templet加复选框,用d.LAY_INDEX获取序号。

     

    12.14.表单提交带文件上传

    <form class="layui-form" id="demoForm">
        <input type="file" name="file" class="layui-input"/>
        <input type="text" name="title" class="layui-input"/>
        <button class="layui-btn" lay-filter="demoSubmit" lay-sunmit>提交</button>
    </form>
    <script>
        form.on('submit(demoSubmit)', function (data) {
            var formData = new FormData();
            for(var f in data.field) {
                if(!data.field.hasOwnProperty(f)) continue;
                formData.append(f, data.field[f]);
            }
            $('#demoForm [type="file"]').each(function() {
                formData.append($(this).attr('name'), $(this)[0].files[0]);
            });
            $.ajax({
                url:'/url',
                type:'post',
                processData:false,
                contentType:false,
                data:formData,
                success:function (res) {
                    console.log(res);
                }
            });
            return false;
        });
    </script>

     

    12.15.单标签模式加居中文字

    在index.loadHome方法之后加js插入内容:

    index.loadHome('......省略');
    // 插入居中文字
    $('.layui-body-header').addClass('text-center');
    $('.layui-body-header-title').addClass('pull-left').css({'line-height': 'initial', 'margin-top': '10px'})
        .after('<span>天气预报</span>');

    最后实现的效果:

    增加循环滚动的效果,类似滚动公告,加一个marquee就实现了:

    <span style="display: inline-block;height: 40px;"><marquee>天气预报</marquee></span>

     

     

    13.1.基础用法

    layRouter是封装的一个简单的路由模块,给index模块作为支撑的,一般不需你要去直接用它, layRouter模块相对独立,你也可以拿出来用在自己的网站中,使用示例:

    <a href="#/user">go user</a>
    <a href="#/home">go home</a>
    <div id="m"></div>
    
    <script>
    layui.use(['layRouter'], function() {
        var layRouter = layui.layRouter;
    
        layRouter.reg('#/home', function(routerInfo) {
            document.getElementById('m').innerHTML = 'Hello World';
        }).reg('#/user', function(routerInfo) {
            document.getElementById('m').innerHTML = 'This is user page';
        });
    
        layRouter.init({
            index: '/home' /* 首页地址 */
        });
    });
    </script>

    打开例子后,会默认在id为m的div中显示 Hello World。 然后点击go user的链接,会跳转到 http://xx.com/#/user ,并且在id为m的div中显示 his is user page。

     

    13.2.注册路由

    调用reg方法,参数一是路由关键字,参数二是路由触发的回调方法:

    layRouter.reg('#/home', function(routerInfo) {
        console.log(routerInfo);
    });
    
    // 参数一支持数组写法,并且#号是可以有可无的
    layRouter.reg(['#/home', '/user', 'order'], function(routerInfo) {
        console.log(routerInfo);
    });
    
    // 在easyweb框架中要使用这种,具体说明请前往index模块查看
    index.regRouter([{
        name: '用户管理',
        url: '#/system/user'
    }]);

    layRouter.reg是基础的写法,下面是index模块封装的写法,使用index.regRouter注册后访问#/system/user,就会打开一个“用户管理”的标签页,使用上面的写法不会。

    在路由触发的回调里面routerInfo包含什么:

    例如你访问 `#/system/user/id=1/sex=男` 它解析的信息为
    {
        path: ["system", "user"],
        search: {id: 1, sex: "男"},
        href: "/system/user/id=1/sex=男",
        refresh: false
    }
    • path     路径数组
    • search   参数列表
    • refresh   如果是刷新触发的值为true

     

    13.3.路由参数传递

    参数传递的规则:

    #/system/user                  // 无参数
    
    #/system/user/id=1             // 参数id=1
    
    #/system/user/id=1/name=aaa    // 参数id=1,name=aaa

    这三种类型的url注册路由的时候只会注册#/system/user这个url,后面两个都是加了参数,而且后面的参数可以无限加。

    获取路由的参数:

    var search = layui.router().search;
    
    var search = layui.router('#/system/user/id=1/name=aa').search;
    
    console.log(search);

    上面是layui提供的方法,建议使用layRouter模块封装的方法:

    var search = layRouter.routerInfo().search;
    
    var search = layRouter.routerInfo('#/system/user/id=1/name=aa').search;

    layRouter封装的方法具有容错性,不管有没有#号都可以正确解析。

    关于后端不能识别这种参数的解答:

    有人建议参数用正常的?id=1&name=aa的方式,认为上面这种后端识别不了。首先spa版本一般都是前后端分离的, http://localhost/#/user/id=1这个url不会进入后端,路由地址也并不代表页面的地址, 访问#/user实际请求的页面是components/user.html,而且是ajax请求的。其次这种解析规则是layui自带的方法解析的。 最后为了满足前后端不分离的情况,3.1.6版本开始已经做了适配,当你访问#/user/id=1/name=aa时, ajax请求html页面会发送components/user.html?id=1&name=aa的请求,会把路由的参数带上,便于后端接收。

     

    13.4.跳转页面

    跳转页面(#号可写可不写):

    layRouter.go('#/user');
    layRouter.go('/user');
    layRouter.go('user');

    刷新页面:

    layRouter.refresh('#/user');   // #号也是可写可不写

    刷新页面与跳转页面的区别:

    layRouter.reg('#/home', function(routerInfo) {
        console.log(routerInfo);
    });

    如果当前hash地址已经是#/home了,再go到home,回调是不会触发的,refresh会触发, 并且如果是刷新触发的,回调里面的routerInfo会多一个refresh字段值为true

     

    13.5.路由不存在处理

    layRouter.init({
        index: '/home',
        notFound: function(routerInfo) {
        }
    });

    在easyweb中处理路由不存在是setter.js中的routerNotFound方法。

     

    13.6.路由切换监听

    重写pop方法即可监听路由的切换:

    layRouter.pop = function(routerInfo) {
        console.log(routerInfo);
    };

     

    13.7.做一个单页网站

    下面演示如何从零实现一个单页面网站,项目结构:

    |- layui
    |- page
    |    |- home.html
    |    |- order
    |         |- product.html
    |         |- introduction.html
    |- expand
    |    |- layRouter.js
    |- index.html

    index.html:

    <html>
    <body>
        <a href="#/home">首页</a>
        <a href="#/order/product">产品</a>
        <a href="#/order/introduction">订单</a>
        <div id="LAY_MAIN"></div>
        <script type="text/javascript" src="layui/layui.js"></script>
        <script>
            layui.config({
                base: 'expand'
            }).use(['jquery', 'layRouter'], function() {
                var $ = layui.jquery;
                var layRouter = layui.layRouter;
    
                layRouter.reg(['#/home', '#/order/product', '#/order/introduction'], function(routerInfo) {
                    var path = routerInfo.path.join('/');
                    $('#LAY_MAIN').load('page/' + path + '.html');
                });
    
                layRouter.init({
                    index: '/home'
                });
            });
        </script>
    </body>
    </html>

    home.html:

    <style>
        #LAY_HOME h2 {
            color: red;
        }
    </style>
    <div id="LAY_HOME">
        <h2>This is Home page.</h2>
    </div>
    <script>
        layui.use(['layer'],function() {
            var layer = layui.layer;
            layer.msg('Hello');
        });
    </script>

    product.html、order.html可自行发挥,然后运行index.html就可以实现一个简单的单页面应用了。

     

     

     

     

     

     

     

     

     

     

     

     

    展开全文
  • excel页面的布局在哪里?

    千次阅读 2021-07-30 10:56:59
    【-字数组成】第1部分: “在Excel2010工作簿中使用“页面布局”视图”在Excel2010工作簿中使用“页面布局”视图在Excel2010和Excel2007之前的版本中,仅提供两种视图模式,即“正常”视图和“分页预览”视图....

    20170929091908987.jpg

    【-字数组成】

    第1部分: “在Excel2010工作簿中使用“页面布局”视图”

    在Excel2010工作簿中使用“页面布局”视图

    在Excel2010和Excel2007之前的版本中,仅提供两种视图模式,即“正常”视图和“分页预览”视图. 此功能限制使用户无法在“页面预览”视图模式下对工作表进行任何编辑. Excel2010添加了“页面布局”视图,以帮助用户在预览页面中的工作表时编辑数据,编辑页眉和页脚,使用工具栏编辑公式等. 适合打印Excel2010工作表.

    打开Excel2010工作簿窗口,单击右下角的“常规”,“页面布局”和“页面预览”按钮在三个视图之间切换,如图2010081201所示.

    图2010081201切换“页面布局”视图

    第2部分: “ Excel中页面布局的应用”

    Excel中的页面布局应用程序

    1. 单击页面布局,将显示以下菜单栏.

    12c994632c131a7a3b3b3e837b57b7b2.png

    我们通常需要设置的主要内容是“边距”,“纸张方向”和“纸张尺寸”提示1: 选择所有列,双击两个字母=适当的宽度

    提示2: 选择空白行,双击以显示光标,按Alt + Enter转到下一行

    两个. 打印时,纸张显示页码,并且在更改页面后还会显示标题行.

    1. 按下打印标题项,将出现以下框,然后分别设置“页面”,“页边距”,“页眉和页脚”和“工作表”.

    点击页面后,设置方向

    当您单击工作表时,按“顶部标题行”以返回主页并选择标题行.

    点击“页眉和页脚”以设置所需的格式.

    您还可以在“页边距”(哪里是Excel页面布局)中设置所需的页边距.

    最后,设置好效果后,您可以进入打印预览.

    3a8e2f1f86b850b98e22089f4a85995c.png

    第3部分: “在Excel2010工作簿中使用“页面布局”视图”

    在Excel2010工作簿中使用“页面布局”视图

    在Excel2010和Excel2007之前的版本中,仅提供两种视图模式,即“正常”视图和“分页预览”视图. 此功能限制使用户无法在“页面预览”视图模式下对工作表进行任何编辑. Excel2010添加了“页面布局”视图,以帮助用户在预览页面中的工作表时编辑数据,编辑页眉和页脚,使用工具栏编辑公式等. 适合打印Excel2010工作表.

    打开Excel2010工作簿窗口,单击右下角的“常规”,“页面布局”和“页面预览”按钮在三个视图之间切换,如图2010081201所示.

    图2010081201切换“页面布局”视图

    第4部分: “如何在excel中创建模板”

    如何在Excel工具/材料中创建模板: Excel 2007方法/步骤

    1个性化设置1: 设置文档的背景色. 切换到“页面布局”选项卡,单击“背景”按钮,然后从弹出窗口中选择图片作为背景. {Excel页面的布局在哪里}.

    56766146_9

    f56f5abe0a0319425273bf0a554511b4.png

    个性化设置2: 设置字体样式. 单击单元格区域的右上角,选择所有单元格,然后将字体设置为“模仿的歌曲_GB2312”,大小设置为“ 14”,颜色设置为“深红色”.

    个性化设置3: 设置页面布局. 切换到“页面布局”选项卡,单击“纸张方向”下拉箭头,然后移动方块

    将方向设置为“横向”,并以相同的方式将“纸张尺寸”设置为A4,将“页边距”设置为“ 2.54,上下左右各一面. ” <

    个性化4: 添加您自己的徽标. 单击“插入”选项卡中的“文本框”工具,以在当前页面中插入一个文本框. 在文本框中输入个性化的单词或图标信息,在此编辑器中输入您的百度ID“ feifeidown”,并设置字体样式和效果. 如图所示设置参数. 最后,将LOgo放置在相对于当前页面合适的位置.

    20160612014609339.jpg

    个性化5: 设置可编辑区域. 切换到“页面布局”选项卡,然后取消选中“查看网络电缆”选项. 然后在当前页面中选择要编辑的区域. {Excel页面的布局在哪里}.

    2. 然后右键单击所选区域,然后选择“设置单元格格式”. 在打开的“设置单元格格式”窗口字符串中,切换到“边框”选项卡,将边框的颜色设置为“红色”,将外部边框设置为“ 2倍线宽”,将内部边框设置为“ 1倍”线宽”,点击“确定”. 效果如图所示:

    3. 单击“ Office按钮”→“另存为”以打开“另存为”对话框,将文件名设置为“ MyTable”,记下保存路径,然后单击“保存”按钮. {Excel页面的布局在哪里}.

    4. 关闭Excel程序. 输入保存的路径(在这种情况下,文件将保存在“桌面”上),并将文件“ StartUp.xlsx”设置为“只读属性”.

    206fc6841c84415202dfc75dea1a67e1.png

    5. 最后将只读文件复制到

    “ D: \ Users \ Administrator \ AppData \ Roaming \ Microsoft \ Excel \ XLSTART”目录. (注意: 在实际情况下,应该在操作系统所在的磁盘下找到XLSTART文件夹. )

    第5部分: “ excel2007打印区域设置” {excel页面布局在哪里}.

    excel2007打印区域设置{哪里是excel页面布局}.

    excel2007的打印区域设置选项在哪里?对于2007版的新用户来说,并不是特别熟悉. excel2007的打印区域设置为: 单击“页面布局”选项卡->打印页面->设置打印区域.

    以下是excel2007打印区域设置的屏幕截图:

    对于刚切换到2010版本的用户,在哪里可以找到Excel绘图工具栏可能是一个问题. 使用过2003版本的用户知道,通过单击“视图工具栏绘图”,可以调用Excel绘图工具栏.

    在2010版本中,名称已更改,名称为Shape. 不再称为绘图工具栏,如下图所示: 单击插入形状,将弹出Excel绘图工具栏. 根据您的需要选择任何形状. 好吧.

    如何修改插入的形状对象? 2010版的Excel绘图工具栏不再是2003年的默认工具栏行.

    2010默认情况下不显示与图片相关的工具栏. 仅当插入图片并选择了图片时,才会显示绘图工具选项卡.

    在excel中删除网格线的方法是: 单击“查看”选项卡->“显示组”->取消选中“网格线”复选框.

    以上方法可以完成excel以删除网格线.

    Excel删除网格线并显示网格线,即在是否选中复选框之间来回切换,这比excel2003版本更加直观和方便.

    本文来自电脑杂谈,转载请注明本文网址:

    http://www.pc-fly.com/a/shumachanpin/article-297533-1.html

    展开全文
  • Unity开发 罗技方向盘 G29 白话版

    千次阅读 多人点赞 2019-04-20 00:42:53
    Unity开发罗技方向盘 大白话版欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中...
  • word2010怎么插入分节符word2010怎么插入分节符 通过在Word2010文档中插入分节符,可以将Word文档分成多个部分。每个部分可以有不同的页边距、页眉页脚、纸张大小等不同的页面设置。在Word2010文档中插入分节符的...
  • entry (应用的主模块)二、编写页面三、页面跳转1. 创建Feature Ability2. 跳转逻辑 首先要知道鸿蒙的APP是怎么构成的?   HarmonyOS的应用软件包以APP Pack(Application Package)形式发布,它是由一个或多个...
  • AI页面面板中如何调尺寸

    千次阅读 2020-12-22 12:25:35
    亦可执行菜单“选择-选择-文本对象”,若会被选中,当然这些文本对象没有 ctrl+alt+3,解除所有锁定 ctrl+alt+22.AI 怎么输出透明文件?答:最好另存为 PDF 或 EPS格式,PDF EPS支持透明功能比较好3.AI 格式的...
  • 基本的ui设计是由另一个同学进行,我负责帮忙进行小部分UI的修改,部分页面实现以及解决排版和页面实现时出现的问题。 微信小程序 首页界面 swiper swiper中的部分属性如下图,根据自己所需要的属性进行添加和选择 ...
  • LaTeX技巧563:LaTeX如何让页面横置?

    万次阅读 2019-01-16 19:41:22
    默认的页面布局是“竖置”,但有时仍然是有用的/需要有整个文件或改为“横置”,只有单页的。后者可能是由于一个大型表或图。我们看看如何改变整个文档或单页的“横置”的页面布局。此外,它有可能使单页横置,使...
  • 按右方向切换当前已打开的文件视图 Alt + 前方向键 当前光标跳转到当前文件的前一个方法名位置 Alt + 后方向键 当前光标跳转到当前文件的后一个方法名位置 Alt + 1,2,3...9 显示对应数值...
  • 页面重定向)方法:Server.Transfer,Response.Redirect,Server.Execute的区别 跨页面提交
  • 这几天,任务中有一个难点是把一个打印页面自动给生成PDF文档,并且上传至服务器,然而公司框架只有手动上传文档,打印时可以保存为PDF在本地吧,所以感到很头疼,刚开始没有方向,所以只有surf the Internet了,...
  • 如何旋转PDF文件中的某一个页面

    千次阅读 2017-03-08 18:11:56
    在浏览查看PDF文件的时候,如果发现有页面方向错误,可以直接在PDF阅读器中进行旋转,但是大家肯定也都发现了,在阅读器中旋转页面是对所有页面进行旋转的,而且不能保存旋转的结果,下次打开文档时还是原来那样。...
  • 在写静态网站的时候,经常回面临某些页面上传更新后,查看时会出现没有更新的清空,就是因为浏览器读取了缓存造成的,需要清空缓存刷新才可以看到页面的更新,但是有些用户不知道这些操作。就很头痛 浏览器缓存...
  • 微信小程序开发教程手册文档本教程将带你一步步创建完成一个微信小程序,并可以在手机上体验该小程序的实际效果。这个小程序的首页将会显示欢迎语以及当前用户的微信头像,点击头像,可以在新开的页面...
  • 职业方向定位 首先,只有确定好自己的职业方向,才能做好职业规划。 (1)资深WEB前端工程师 这个方向算是一个WEB前端最基本的选择了,在国外,很多老外都能够把自己的专业做到极致,能一辈子就在一个专业领域不断...
  • 如何在WPS文字中将小写数字金额变为... 首先,在电脑桌面上新建一个WPS文档并打开,在其中输入几组数据金额.将我们要设置的数字选中,然后点击页面上端的"插入",在其下菜单栏中找到并点击"插入数字".2. 打开数字窗口...
  • 如何让PPT转成PDF后占满整个页面

    千次阅读 2021-05-21 17:55:49
    首先我们要进行分辨确实是PDF文档页面尺寸不对,两侧或上下有空白,还是我们打开PDF的页面比例不对呢?可以将PDF的页面比例调整到100%也就是实际大小再查看,如果仍不是我们想要的效果如下图中的图1,则可进行下一步...
  • javaWeb静态页面_html_css

    千次阅读 2020-09-03 21:07:52
    其实不管是前端工程师还是后台工程师我 们要做的工作无非就是软件的开发。...表现:CSS用于控制页面中的元素的样式 行为:JavaScript用于响应用户操作 万维网联盟(W3C) 万维网联盟World Wide Web Conso
  • 此外,表通常要求站点上的每个网页都包含站点导航和其他常见的站点信息,这意味着,如果要在一页上对这些元素进行更改,则必须在每个页面上进行更改。 当您使用框架时,一个框架可以包含带有网站导航HTML文件,而...
  • 文章目录微信小程序入门(一)项目结构解读每个文件的功能xxx.js(index.js)文件xxx.json(index.json)xxx.wxml(index.wxml)xxx.wxss(index.wxss)总结文件约定文档结构解读小程序入门删除项目结构小程序页面的搭建技巧和...
  • 反编译其他apk,新增页面且不使用动态布局,完全使用开发习惯的xml包括shape 新增图片,一不替换已经存在的R.xxx,二不需要在反编译的apk public.xml中手动注册id,所以核心就是无视public.xml(R文件)完全新增。...
  • 前端工程师未来发展方向

    千次阅读 2020-07-07 17:19:16
    只有大量的使用,才能明白设计框架者在设计背后的思路,只有了解到设计的思路,才能做正确全面的分析,只有正确全面的分析才能支撑我们去对其裁剪或扩展,只有经过实际分析、修改别人的框架,才有可能写出优秀的、...
  • 摘 要:Word字处理软件的使用是大学计算机基础课中的重要内容,Word文档的排版是学生必需掌握的基本技能。Word长文档具有内容多、篇幅长的特点,因此排版工作量较大、相对较复杂。如果处理方式不规范且不遵循相应的...
  • 移动端Web页面适配方案(整理版)

    千次阅读 多人点赞 2020-05-15 14:17:50
    移动端web页面的开发,由于手机屏幕尺寸、分辨率不同,或者需要考虑横竖屏问题,为了使得web页面在不同移动设备上具有相适应的展示效果,需要在开发过程中使用合理的适配方案来解决这个问题。 早期网页设计采用静态...
  • Web前端性能优化——如何提高页面加载速度

    万次阅读 多人点赞 2018-09-04 07:57:15
    首先说明一下,将样式表放在头部对于实际页面加载的时间并不能造成太大影响,但是这会减少页面首屏出现的时间,使页面内容逐步呈现,改善用户体验,防止“白屏”。 我们总是希望页面能够尽快显示内容,为用户提供...
  • 它与路由和页面转换有什么关系? Nuxt.js到底是什么? 有趣的是,尽管听起来很复杂,但与Nuxt.js一起工作并探索的好处并不难。 让我们开始吧! 服务器端渲染 您可能听说过最近有人在谈论服务器端渲染。 最近...
  • 35、Flutter之PageView与页面缓存

    千次阅读 2022-01-17 22:01:37
    如果要实现页面切换和 Tab 布局,我们可以使用 PageView 组件。需要注意,PageView 是一个非常重要的组件,因为在移动端开发中很常用,比如大多数 App 都包含 Tab 换页效果、图片轮动以及抖音上下滑页切换视频功能...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 68,793
精华内容 27,517
关键字:

修改文档实际页面方向