Layui本地存储:cookie与localStorage使用

Layui本地存储:cookie与localStorage使用

【免费下载链接】layui 【免费下载链接】layui 项目地址: https://gitcode.com/gh_mirrors/lay/layui

本地存储(Local Storage)是Web开发中不可或缺的技术,用于在客户端保存用户数据,提升页面性能和用户体验。Layui作为一款经典的前端UI框架,虽然未直接提供封装的本地存储模块,但通过原生JavaScript API结合Layui的工具函数,可高效实现Cookie和localStorage的管理。本文将从实际应用场景出发,详细讲解如何在Layui项目中使用这两种存储方案,并对比其优缺点及适用场景。

技术选型:Cookie与localStorage核心差异

在开始编码前,需明确两种存储方案的核心差异,以便根据业务场景选择合适的方案。以下是两者的关键对比:

特性CookielocalStorage
存储容量约4KB约5MB
过期时间可设置过期时间,默认随会话消失永久存储,需手动清除
网络请求携带每次HTTP请求自动携带不参与网络传输
作用域基于域名,支持跨域访问控制仅当前域名可访问
API复杂度原生API繁琐,需手动封装原生API简洁,支持键值对直接操作

适用场景决策流程图

mermaid

Cookie操作:Layui环境下的封装实现

Cookie适用于存储少量需跨请求传递的数据(如用户认证令牌、主题偏好)。由于原生JavaScript操作Cookie的API较为繁琐,我们可基于Layui的工具函数封装一套简洁的操作方法。

核心代码实现

创建examples/js/cookie.js文件,实现Cookie的增删改查:

/**
 * Cookie操作工具类(基于Layui环境)
 * 存储路径:examples/js/cookie.js
 */
layui.define(['jquery'], function(exports) {
    var $ = layui.$;
    
    var CookieUtil = {
        /**
         * 设置Cookie
         * @param {string} key - 键名
         * @param {string} value - 值
         * @param {Object} options - 配置项
         * @param {number} options.expires - 过期天数
         * @param {string} options.path - 路径
         * @param {string} options.domain - 域名
         * @param {boolean} options.secure - 是否安全传输
         */
        set: function(key, value, options) {
            options = options || {};
            var expires = options.expires;
            
            if (expires && typeof expires === 'number') {
                var date = new Date();
                date.setTime(date.getTime() + (expires * 24 * 60 * 60 * 1000));
                expires = options.expires = date;
            }
            
            if (expires && expires.toUTCString) {
                options.expires = expires.toUTCString();
            }
            
            value = encodeURIComponent(value);
            var updatedCookie = key + '=' + value;
            
            for (var propName in options) {
                updatedCookie += '; ' + propName;
                var propValue = options[propName];
                if (propValue !== true) {
                    updatedCookie += '=' + propValue;
                }
            }
            
            document.cookie = updatedCookie;
        },
        
        /**
         * 获取Cookie
         * @param {string} key - 键名
         * @returns {string|null} 值(解码后)
         */
        get: function(key) {
            var cookieValue = null;
            if (document.cookie && document.cookie !== '') {
                var cookies = document.cookie.split(';');
                for (var i = 0; i < cookies.length; i++) {
                    var cookie = $.trim(cookies[i]);
                    if (cookie.substring(0, key.length + 1) === (key + '=')) {
                        cookieValue = decodeURIComponent(cookie.substring(key.length + 1));
                        break;
                    }
                }
            }
            return cookieValue;
        },
        
        /**
         * 删除Cookie
         * @param {string} key - 键名
         * @param {Object} options - 配置项(需与设置时一致)
         */
        remove: function(key, options) {
            options = options || {};
            options.expires = -1;
            this.set(key, '', options);
        },
        
        /**
         * 清除所有Cookie
         */
        clear: function() {
            var cookies = document.cookie.split(';');
            for (var i = 0; i < cookies.length; i++) {
                var cookie = cookies[i];
                var eqPos = cookie.indexOf('=');
                var key = eqPos > -1 ? cookie.substr(0, eqPos) : cookie;
                document.cookie = key + '=; expires=Thu, 01 Jan 1970 00:00:00 GMT';
            }
        }
    };
    
    exports('cookie', CookieUtil);
});

实际应用示例

examples/cookie.html中使用封装的Cookie工具:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Layui Cookie示例</title>
    <link rel="stylesheet" href="../src/css/layui.css">
</head>
<body>
    <div class="layui-container layui-row layui-col-space15" style="margin-top: 30px;">
        <div class="layui-col-md6">
            <div class="layui-card">
                <div class="layui-card-header">用户偏好设置</div>
                <div class="layui-card-body">
                    <form class="layui-form" lay-filter="preferenceForm">
                        <div class="layui-form-item">
                            <label class="layui-form-label">主题颜色</label>
                            <div class="layui-input-block">
                                <input type="radio" name="theme" value="default" title="默认" checked>
                                <input type="radio" name="theme" value="dark" title="深色">
                                <input type="radio" name="theme" value="blue" title="蓝色">
                            </div>
                        </div>
                        <div class="layui-form-item">
                            <label class="layui-form-label">每页显示条数</label>
                            <div class="layui-input-block">
                                <select name="pageSize" lay-verify="required">
                                    <option value="10">10条/页</option>
                                    <option value="20">20条/页</option>
                                    <option value="50">50条/页</option>
                                </select>
                            </div>
                        </div>
                        <div class="layui-form-item">
                            <div class="layui-input-block">
                                <button class="layui-btn" lay-submit lay-filter="save">保存设置</button>
                                <button type="button" class="layui-btn layui-btn-primary" id="load">读取设置</button>
                                <button type="button" class="layui-btn layui-btn-danger" id="clear">清除设置</button>
                            </div>
                        </div>
                    </form>
                </div>
            </div>
        </div>
        <div class="layui-col-md6">
            <div class="layui-card">
                <div class="layui-card-header">当前Cookie数据</div>
                <div class="layui-card-body">
                    <pre id="cookieData" style="background-color: #f5f5f5; padding: 10px; border-radius: 4px; height: 200px; overflow-y: auto;"></pre>
                </div>
            </div>
        </div>
    </div>

    <script src="../src/layui.js"></script>
    <script>
        layui.config({
            base: '../examples/js/' // 配置自定义组件路径
        }).use(['form', 'cookie', 'jquery'], function() {
            var form = layui.form;
            var cookie = layui.cookie;
            var $ = layui.$;
            
            // 保存设置到Cookie,有效期7天
            form.on('submit(save)', function(data) {
                cookie.set('userTheme', data.field.theme, {expires: 7, path: '/'});
                cookie.set('pageSize', data.field.pageSize, {expires: 7, path: '/'});
                layer.msg('设置已保存', {icon: 1});
                renderCookieData();
                return false;
            });
            
            // 读取Cookie设置并回显
            $('#load').click(function() {
                var theme = cookie.get('userTheme');
                var pageSize = cookie.get('pageSize');
                
                if (theme) {
                    $('input[name="theme"][value="' + theme + '"]').prop('checked', true);
                }
                if (pageSize) {
                    $('select[name="pageSize"]').val(pageSize);
                }
                
                form.render(); // 重新渲染表单
                layer.msg('设置已加载', {icon: 1});
                renderCookieData();
            });
            
            // 清除Cookie设置
            $('#clear').click(function() {
                cookie.remove('userTheme', {path: '/'});
                cookie.remove('pageSize', {path: '/'});
                layer.msg('设置已清除', {icon: 1});
                renderCookieData();
            });
            
            // 显示当前Cookie数据
            function renderCookieData() {
                $('#cookieData').text(document.cookie || '暂无Cookie数据');
            }
            
            // 初始化显示
            renderCookieData();
        });
    </script>
</body>
</html>

关键代码解析

  1. 封装设计:通过Layui的define方法创建独立模块,避免全局污染,符合Layui的模块化规范。
  2. 过期时间处理:支持按天数设置过期时间,内部自动转换为UTC时间格式。
  3. 作用域控制:通过pathdomain参数限制Cookie的作用范围,增强安全性。
  4. Layui集成:与Layui的form组件无缝结合,实现设置的保存与回显。

localStorage操作:Layui中的数据持久化方案

localStorage适用于存储大量不随请求发送的客户端数据(如离线缓存、复杂表单草稿)。其原生API已足够简洁,可直接使用,也可结合Layui工具函数进行增强。

基础操作示例

创建examples/localStorage.html演示localStorage的基本用法:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Layui localStorage示例</title>
    <link rel="stylesheet" href="../src/css/layui.css">
</head>
<body>
    <div class="layui-container" style="margin-top: 30px;">
        <div class="layui-row">
            <div class="layui-col-md8">
                <div class="layui-card">
                    <div class="layui-card-header">
                        <h2>用户数据离线存储</h2>
                        <p style="color: #666; margin-top: 5px;">使用localStorage保存用户表单数据,支持页面刷新后恢复</p>
                    </div>
                    <div class="layui-card-body">
                        <form class="layui-form" lay-filter="userForm">
                            <div class="layui-form-item">
                                <label class="layui-form-label">用户名</label>
                                <div class="layui-input-block">
                                    <input type="text" name="username" lay-verify="required" placeholder="请输入用户名" autocomplete="off" class="layui-input">
                                </div>
                            </div>
                            <div class="layui-form-item">
                                <label class="layui-form-label">邮箱</label>
                                <div class="layui-input-block">
                                    <input type="text" name="email" lay-verify="email" placeholder="请输入邮箱" autocomplete="off" class="layui-input">
                                </div>
                            </div>
                            <div class="layui-form-item">
                                <label class="layui-form-label">兴趣爱好</label>
                                <div class="layui-input-block">
                                    <input type="checkbox" name="hobby" value="reading" title="阅读">
                                    <input type="checkbox" name="hobby" value="sports" title="运动">
                                    <input type="checkbox" name="hobby" value="coding" title="编程">
                                    <input type="checkbox" name="hobby" value="music" title="音乐">
                                </div>
                            </div>
                            <div class="layui-form-item layui-form-text">
                                <label class="layui-form-label">个人简介</label>
                                <div class="layui-input-block">
                                    <textarea name="bio" placeholder="请输入个人简介" class="layui-textarea" style="height: 100px;"></textarea>
                                </div>
                            </div>
                            <div class="layui-form-item">
                                <div class="layui-input-block">
                                    <button class="layui-btn" lay-submit lay-filter="save">保存到localStorage</button>
                                    <button type="button" class="layui-btn layui-btn-primary" id="load">从localStorage加载</button>
                                    <button type="button" class="layui-btn layui-btn-danger" id="clear">清除存储</button>
                                </div>
                            </div>
                        </form>
                    </div>
                </div>
            </div>
            <div class="layui-col-md4">
                <div class="layui-card">
                    <div class="layui-card-header">存储状态</div>
                    <div class="layui-card-body">
                        <div class="layui-row">
                            <div class="layui-col-md12">
                                <p><span class="layui-badge">存储键名</span> <code>userProfile</code></p>
                                <p><span class="layui-badge">最后更新时间</span> <span id="updateTime">-</span></p>
                                <p><span class="layui-badge">数据大小</span> <span id="dataSize">-</span></p>
                            </div>
                        </div>
                        <hr>
                        <div class="layui-row">
                            <div class="layui-col-md12">
                                <h3 style="font-size: 16px; margin-bottom: 10px;">localStorage数据预览</h3>
                                <pre id="storageData" style="background-color: #f5f5f5; padding: 10px; border-radius: 4px; height: 200px; overflow-y: auto; font-size: 12px;"></pre>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <script src="../src/layui.js"></script>
    <script>
        layui.use(['form', 'layer'], function() {
            var form = layui.form;
            var layer = layui.layer;
            var $ = layui.$;
            
            // 存储键名
            var STORAGE_KEY = 'userProfile';
            
            // 保存表单数据到localStorage
            form.on('submit(save)', function(data) {
                // 补充时间戳
                var saveData = {
                    data: data.field,
                    updateTime: new Date().toISOString()
                };
                
                // 存储到localStorage
                localStorage.setItem(STORAGE_KEY, JSON.stringify(saveData));
                
                // 更新状态显示
                updateStorageStatus();
                layer.msg('数据已保存到localStorage', {icon: 1});
                return false;
            });
            
            // 从localStorage加载数据
            $('#load').click(function() {
                var storedData = localStorage.getItem(STORAGE_KEY);
                if (!storedData) {
                    layer.msg('没有找到存储的数据', {icon: 2});
                    return;
                }
                
                try {
                    var parsedData = JSON.parse(storedData);
                    var formData = parsedData.data;
                    
                    // 填充表单数据
                    for (var key in formData) {
                        var $elem = $('[name="' + key + '"]');
                        if ($elem.is(':checkbox')) {
                            // 处理复选框
                            $elem.each(function() {
                                $(this).prop('checked', formData[key].includes($(this).val()));
                            });
                        } else {
                            $elem.val(formData[key]);
                        }
                    }
                    
                    form.render(); // 重新渲染表单
                    updateStorageStatus();
                    layer.msg('数据已从localStorage加载', {icon: 1});
                } catch (e) {
                    layer.msg('数据解析失败', {icon: 2});
                }
            });
            
            // 清除localStorage数据
            $('#clear').click(function() {
                localStorage.removeItem(STORAGE_KEY);
                updateStorageStatus();
                layer.msg('localStorage数据已清除', {icon: 1});
            });
            
            // 更新存储状态显示
            function updateStorageStatus() {
                var storedData = localStorage.getItem(STORAGE_KEY);
                if (storedData) {
                    var parsedData = JSON.parse(storedData);
                    $('#updateTime').text(new Date(parsedData.updateTime).toLocaleString());
                    $('#dataSize').text((storedData.length / 1024).toFixed(2) + ' KB');
                    $('#storageData').text(JSON.stringify(parsedData, null, 2));
                } else {
                    $('#updateTime').text('-');
                    $('#dataSize').text('-');
                    $('#storageData').text('暂无数据');
                }
            }
            
            // 初始化状态显示
            updateStorageStatus();
        });
    </script>
</body>
</html>

高级应用:结合Layui表格的本地缓存

在数据表格场景中,可使用localStorage缓存表格列配置、排序状态等信息,提升用户体验:

// 表格列配置缓存示例(位于examples/table.html)
var TABLE_CONFIG_KEY = 'productTableConfig';

// 尝试从localStorage加载表格配置
var savedConfig = localStorage.getItem(TABLE_CONFIG_KEY);
var tableCols = savedConfig ? JSON.parse(savedConfig) : [
    {field: 'id', title: 'ID', width: 80, sort: true},
    {field: 'name', title: '产品名称', width: 200},
    {field: 'category', title: '分类', width: 120},
    {field: 'price', title: '价格', width: 100, sort: true},
    {field: 'stock', title: '库存', width: 100, sort: true},
    {field: 'operate', title: '操作', width: 150, toolbar: '#barDemo'}
];

// 渲染表格
table.render({
    elem: '#productTable',
    url: '../examples/json/table/demo1.json',
    cols: [tableCols],
    page: true,
    limit: 10,
    limits: [10, 20, 50],
    done: function() {
        // 监听列调整事件,保存新配置
        this.elem.next().find('.layui-table-header th').on('mouseup', function() {
            var newCols = table.config.cols[0];
            localStorage.setItem(TABLE_CONFIG_KEY, JSON.stringify(newCols));
        });
    }
});

安全性与性能优化最佳实践

数据安全处理

  1. 敏感数据加密:存储用户凭证等敏感信息时,需先加密:
// 简易加密函数(实际项目建议使用专业加密库)
function encryptData(data, key) {
    var encrypted = CryptoJS.AES.encrypt(JSON.stringify(data), key).toString();
    return encrypted;
}

function decryptData(encryptedData, key) {
    var bytes = CryptoJS.AES.decrypt(encryptedData, key);
    return JSON.parse(bytes.toString(CryptoJS.enc.Utf8));
}

// 使用示例
var userData = {username: 'admin', token: 'xxx'};
var secretKey = 'your-secret-key'; // 实际项目中应动态生成并安全管理

// 加密存储
localStorage.setItem('secureUserData', encryptData(userData, secretKey));

// 解密读取
var decryptedData = decryptData(localStorage.getItem('secureUserData'), secretKey);
  1. XSS防护:读取存储数据后渲染到页面时,使用Layui的util.escape方法过滤HTML:
var util = layui.util;
var userInput = localStorage.getItem('userInput');
$('#content').html(util.escape(userInput)); // 防止XSS攻击

性能优化策略

  1. 批量操作优化:频繁操作localStorage时,使用临时对象缓存变更,减少实际存储次数:
// 优化前:多次存储
localStorage.setItem('a', 'value1');
localStorage.setItem('b', 'value2');
localStorage.setItem('c', 'value3');

// 优化后:单次存储
var tempObj = {
    a: 'value1',
    b: 'value2',
    c: 'value3'
};
localStorage.setItem('batchData', JSON.stringify(tempObj));
  1. 存储数据压缩:对于大型JSON数据,可使用pako等库进行压缩后存储:
// 引入pako库(需提前加载)
<script src="https://cdn.bootcdn.net/ajax/libs/pako/2.1.0/pako.min.js"></script>

// 压缩存储
var largeData = {/* 大量数据 */};
var compressed = pako.gzip(JSON.stringify(largeData), {to: 'string'});
localStorage.setItem('compressedData', compressed);

// 解压缩读取
var compressedData = localStorage.getItem('compressedData');
var decompressed = pako.ungzip(compressedData, {to: 'string'});
var originalData = JSON.parse(decompressed);

总结与扩展应用

技术选型建议

mermaid

  • 优先使用localStorage:存储大量客户端数据、表单草稿、用户偏好设置等
  • 使用Cookie:存储认证令牌、跨域数据共享、服务器需读取的配置
  • 考虑sessionStorage:临时会话数据、页面间传递临时参数(关闭标签页即消失)

扩展应用场景

  1. 离线应用:结合Service Worker实现完全离线功能
// 注册Service Worker(位于examples/offline.js)
if ('serviceWorker' in navigator) {
    window.addEventListener('load', function() {
        navigator.serviceWorker.register('../examples/js/offline-sw.js').then(function(registration) {
            console.log('ServiceWorker registration successful');
        }, function(err) {
            console.log('ServiceWorker registration failed: ', err);
        });
    });
}
  1. 状态管理:小型应用可使用localStorage实现简单的状态管理,替代Vuex/Redux
// 简易状态管理(examples/js/store.js)
layui.define(function(exports) {
    var Store = {
        getState: function() {
            return JSON.parse(localStorage.getItem('appState') || '{}');
        },
        setState: function(newState) {
            var state = this.getState();
            var updatedState = {...state, ...newState};
            localStorage.setItem('appState', JSON.stringify(updatedState));
            // 触发自定义事件通知状态变更
            var event = new Event('stateChange');
            event.state = updatedState;
            window.dispatchEvent(event);
        }
    };
    
    exports('store', Store);
});

通过本文的讲解,你已掌握在Layui项目中使用Cookie和localStorage的完整方案。合理选择存储方案,结合Layui的组件生态,可显著提升Web应用的性能和用户体验。完整示例代码可参考项目中的examples/cookie.html和examples/localStorage.html文件,更多工具函数可查阅src/modules/util.js源码。

【免费下载链接】layui 【免费下载链接】layui 项目地址: https://gitcode.com/gh_mirrors/lay/layui

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值