springboot整合web开发的各个组件在前面已经有详细的介绍,下面是用springboot整合layui实现了基本的增删改查。

  同时在学习mui开发app,也就用mui实现了一个简单的自动登录和用户列表上拉刷新的app。

下面是自己实现前的思路:

1.  web端实现用户的增删改查,SSM实现。  Spring + SpringMVC +Mybatis + PageHelper
表主要有两个user表和token表。
user表就是基本的信息(ID、username、password、userfullname、createtime等字段)
token表id、token创建时间、token串、失效时间、username、userIdcode等信息 2. 安卓端实现token自动登录和下拉刷新查询列表。
1. 自动登录的思路:
(1) 首次登录: 带着username、password去后台请求登录信息,
后台如果登录成功返回一个{ token,username,userfullname} , token表包括:id、token创建时间、token串、失效时间、username、userIdcode等信息。token的生成方式可以用md5算法加密username生成
(2) 主页面访问的时候每次先带着本地的token去后台验证一下token,如果token失效的话就返回到登录界面,如果token有效期在5天以内就在后台生成一个token并且重新刷新本地token
后台返回json数据,msg包括:invalidToken--表示无效token,需要退出到登陆界面;
ok:表示有效,然后根据返回的token串与本地串是否一致,如果不一致更新本地token即可。
(3)安卓端退出的时候清除本地的token
2.安卓端分页下拉刷新展示所有的user信息

===========Web端实现用户增删改查========

  主要是springboot+layui+thymeleaf。

  主要是layui整合thymeleaf的时候,html的所有的自闭标签都必须带结束标记,比如<input > 必须写为<input />;而且标签的属性必须有值,例如<input checked /> 必须是<input checked="checked"/>,否则会报解析错误。而且页面的JS有时在解析时也报语法错误,所以JS尽量写在单独的JS文件中。

  另外需要注意的是使用springboot+thymeleaf的时候,如果需要访问html页面,所有的请求都必须经过后台进行转发。即使是在layui的框架中使用iframe等进行引进html也需要到后台进行转发一下。

目录结构如下:

下面贴出pom.xml和application.properties

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cn.qlq</groupId>
<artifactId>springboot-ssm</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging> <parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.2.RELEASE</version>
</parent> <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency> <!-- 设置Tomcat打包的时候不打包下面配置 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency> <!--springboot单元测试 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency> <!--热加载 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency> <!-- spring-boot整合mybatis -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.1.1</version>
</dependency>
<!-- mysql驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency> <!-- 使用事务需要引入这个包 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency> <!-- 引入 spring aop 依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency> <!--pagehelper插件 -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.1.2</version>
</dependency> <!-- 引入 freemarker 模板依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency> <!-- 引入 thymeleaf 模板依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency> <!-- commons工具包 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.1</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.2</version>
</dependency>
<!-- 阿里的fastjson用于手动转JSON -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.56</version>
</dependency>
</dependencies> <distributionManagement>
<repository>
<id>releases</id>
<url>http://192.168.0.133:8081/repository/maven-releases/</url>
</repository>
<snapshotRepository>
<id>snapshots</id>
<url>http://192.168.0.133:8081/repository/maven-snapshots/</url>
</snapshotRepository>
</distributionManagement> <build>
<!-- 配置了很多插件 -->
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
############################################################
#
# 日志相关配置(默认集成的有slf4j,Logback等)
#
############################################################
#指定配置文件的位置,只能是xml或者groovy结尾
#logging.config=classpath:logback.xml
#默认的日志级别
logging.level.root=INFO
# mapper 接口所在的包设置为 debug
logging.level.cn.qlq.mapper=DEBUG
#生成日志文件的位置
logging.file=G:/springboot.log
#生成日志文件的目录,名称默认为spring.log
#logging.path=e:/
#指定日志的格式
#logging.pattern.console=%d{yyyy/MM/dd-HH:mm:ss} [%thread] %-5level %clr(%logger){cyan} %clr(%msg%n){green}
#logging.pattern.file=%d{yyyy/MM/dd-HH:mm} [%thread] %-5level %logger- %msg%n ############################################################
#
# Mybatis settings
#
############################################################
#jiazai mybatis peizhiwenjian(**代表任意目录,*代表任意多个字符)
mybatis.mapper-locations = classpath:mapper/**/*Mapper.xml
mybatis.config-location = classpath:mybatis/SqlMapConfig.xml
mybatis.type-aliases-package = cn.qlq.bean ############################################################
#
# datasource settings
#
############################################################
spring.datasource.driver-class-name= com.mysql.jdbc.Driver
spring.datasource.url = jdbc:mysql://localhost:3306/test1?useUnicode=true&characterEncoding=utf-8
spring.datasource.username = root
spring.datasource.password = 123456 ############################################################
#
# Server 服务端相关配置
#
############################################################
# 配置api端口号
server.port=8088
# 配置context-path, 一般来说这个配置在正式发布的时候不配置
#server.context-path=/MySpringboot
server.serverlet-path=*.do,*.action
# 错误页,指定发生错误时,跳转的URL --> BasicErrorController
#server.error.path=/error
# session最大超时时间(分钟),默认为30分钟
server.session-timeout=60
# 该服务绑定IP地址,启动服务器时如本机不是该IP地址则抛出异常启动失败,
# 只有特殊需求的情况下才配置, 具体根据各自的业务来设置
#server.address=192.168.1.2 ############################################################
# Server - tomcat 相关常用配置
############################################################
# tomcat最大线程数, 默认为200
#server.tomcat.max-threads=250
# tomcat的URI编码
server.tomcat.uri-encoding=UTF-8
# 存放Tomcat的日志、Dump等文件的临时文件夹,默认为系统的tmp文件夹
#(如:C:%users\Shanhy\AppData\Local\Temp)
#server.tomcat.basedir=H:/springboot-tomcat-tmp
# 打开Tomcat的Access日志,并可以设置日志格式的方法:
#server.tomcat.access-log-enabled=true
#server.tomcat.access-log-pattern=
# accesslog目录,默认在basedir/logs
#server.tomcat.accesslog.directory=
# 日志文件目录
#logging.path=H:/springboot-tomcat-tmp
# 日志文件名称,默认为spring.log
#logging.file=myapp.log ############################################################
#
# freemarker 静态资源配置
#
############################################################
#设定ftl文件路径
spring.freemarker.template-loader-path=classpath:/templates
# 关闭缓存, 即时刷新, 上线生产环境需要改为true
spring.freemarker.cache=false
#spring.freemarker.enabled=false
spring.freemarker.charset=UTF-8
spring.freemarker.check-template-location=false
spring.freemarker.content-type=text/html
spring.freemarker.expose-request-attributes=true
spring.freemarker.expose-session-attributes=true
spring.freemarker.request-context-attribute=request
spring.freemarker.suffix=.ftl ############################################################
#
# thymeleaf 静态资源配置
#
############################################################
spring.thymeleaf.prefix=classpath:/templates/thymeleaf/x-admin/
spring.thymeleaf.suffix=.html
spring.thymeleaf.mode=HTML5
spring.thymeleaf.encoding=UTF-8
spring.thymeleaf.content-type=text/html
# 关闭缓存, 即时刷新, 上线生产环境需要改为true
spring.thymeleaf.cache=false
#关闭thymeleaf引擎
#spring.thymeleaf.enabled=false ############################################################
#
# JSP 配置
#
############################################################
#spring.mvc.view.suffix=.jsp
#spring.mvc.view.prefix=/WEB-INF/jsp/ #设定静态文件路径,js,css等
spring.mvc.static-path-pattern=/static/**
#静态资源的存储位置
#spring.resources.static-locations=classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/ ############################################################
#
# 配置i18n 资源文件,供thymeleaf 读取
#
############################################################
spring.messages.basename=i18n/messages
spring.messages.cache-seconds=3600
spring.messages.encoding=UTF-8 ############################################################
#
# 格式化日期类型为JSON的格式
#
############################################################
spring.jackson.date-format=yyyy-MM-dd
spring.jackson.time-zone=GMT+8
spring.jackson.serialization.write-dates-as-timestamps=false

  git地址:https://github.com/qiao-zhi/springboot-ssm.git

===========app端实现自动登录和用户列表查询========

  app的开发主要是采用HBuilder建的移动app工程,以及mui框架。mui可以调用手机自带的API,比如手机二维码扫描、微信登录等。而且HBuilder已经集成了mui,所以新建工程的时候选择的是带登录模板的工程。而且只有apk打包的程序才可以访问h5+。直接在浏览器访问是不可行的。

  

  下面是自己开发过程中对mui注意事项的总结:

0.每一个页面对应一个JS。而且在JS第一行首先调用mui.init();进行初始化。
1.mui的localStorage 可用于本地存储。除非用JS删除
localStorage.setItem('$settings', JSON.stringify(settings));
var stateText = localStorage.getItem('$state') || "{}"; 2.不要在没有plus和mui的环境下调用相关API
普通浏览器里没有plus环境,只有HBuilder真机运行和打包后才能运行plus api。
在普通浏览器里运行时plus api时控制台必然会输出plus is not defined错误提示。
mui作为一个前端框架,你必须保证当前页面引入了mui.js。否则也会出现mui is not defined。 3.不要在plus和mui未完成初始化时调用相关API
就像在dom初始化完成前(DOMContentLoaded)去操作dom,就会报错是一样的道理。
plus和mui都需要初始化,在初始化完成后调用再调用。
一般我们在plusready的回调事件里调用plus api。=======也就是说一般我们都要先mui.init({...}),然后mui相关所有的JS函数都写在mui.plusReady里面,遵循大部分前端框架的规则 mui框架对此进行了封装,写法更简单:
mui.init({
pullRefresh: {
container: '#pullrefresh',
down: {
style:'circle',
callback: pulldownRefresh
},
up: {
auto:true,
contentrefresh: '正在加载...',
callback: pullupRefresh
}
}
}); mui.plusReady(function() {
mui.toast("提示");
}); 4.mui页面跳转的方式:===预加载的方式
(1)在$.plusReady中提前加载页面
var mainPage = $.preload({
"id": 'main',
"url": 'main.html'
});
(2)通过函数跳转页面的方法:
var toMain = function() {
$.fire(mainPage, 'show', null);
setTimeout(function() {
$.openWindow({
id: 'main',
show: {
aniShow: 'pop-in'
},
waiting: {
autoShow: false
}
});
}, 0);
};
通过mui.fire()方法可触发目标窗口的自定义事件。
5.mui页面跳转的方式:===预加载的方式,也可以通过a标签的方式进行加载
一般在新的页面用下面格式:
<body>
<!--上面的导航窗格,mui-pull-left表示居左还是居右-->
<header class="mui-bar mui-bar-nav">
<!--返回按钮-->
<a class="mui-action-back mui-icon mui-icon-left-nav mui-pull-left"></a>
<h1 class="mui-title">三行列表</h1>
</header>
<!--下面存放所有的内容-->
<div class="mui-content">
</div>
<body> 6.mui重写手机返回按钮的事件:
<script>
mui.init({
swipeBack:true //启用右滑关闭功能
}); mui.plusReady(function() {
mui.back = function(event) {
alert("xxx");
};
});
</script> 一般在主页面重写返回按钮的事件:--双击退出应用
//--
$.oldBack = mui.back;
var backButtonPress = 0;
mui.back = function(event) {
backButtonPress++;
if (backButtonPress > 1) {
plus.runtime.quit();
} else {
plus.nativeUI.toast('再按一次退出应用');
}
setTimeout(function() {
backButtonPress = 0;
}, 1000);
return false;
}; 7. mui带箭头的列表导航的格式
<ul id="list" class="mui-table-view mui-table-view-chevron">
<li class="mui-table-view-cell">
<a class="mui-navigate-right" href="view/user.html">
进入用户列表
</a>
</li>
<li class="mui-table-view-cell mui-collapse">
<a class="mui-navigate-right" href="#">
测试连接
</a>
<ul class="mui-table-view mui-table-view-chevron">
<li class="mui-table-view-cell">
<a class="mui-navigate-right" href="examples/actionsheet.html">
页面1
</a>
</li>
<li class="mui-table-view-cell mui-plus-visible">
<a class="mui-navigate-right" href="examples/actionsheet-plus.html">
页面2
</a>
</li>
</ul>
</li>
</ul>

1.自动登录的主要思想:

  如果对模板的项目稍有研究可以发现,app默认的页面是login.html,如果登录成功或者是自动登录而且自动登录的信息在本地存储的是正确的就调用toMain()方法跳转到main.html。

  自动登录的思想就是:登录成功之后将从后台生成一个token串保存到本地,每次打开app的时候如果是自动登录就带着本地的token去后台验证,当然后台的代码在上面的springboot项目地址都实现了。这里主要介绍前端的交互。

1.重写app.js的登录方法:(我们知道mui的ajax请求本身是跨域的)

    /**
* 用户登录
**/
owner.login = function(loginInfo, callback) {
callback = callback || $.noop;
loginInfo = loginInfo || {};
loginInfo.account = loginInfo.account || '';
loginInfo.password = loginInfo.password || '';
if (loginInfo.account.length < 5) {
return callback('账号最短为 5 个字符');
}
if (loginInfo.password.length < 5) {
return callback('密码最短为 5 个字符');
}
var users = JSON.parse(localStorage.getItem('$users') || '[]');
//模拟登陆
var loginAddress = appServerAddressPrefix + "/mobile/doLogin.html";
$.post(loginAddress,
{
"username":loginInfo.account,
"password":loginInfo.password
},
function(res){
if(res && res.success){
return owner.createState(res.data, callback);
}else{
return callback(res.msg);
}
},
'json');
};

  appServerAddressPrefix 是自己的后台服务器的地址,如下:

var appServerAddressPrefix = "http://192.168.1.6:8088";

createState 以及setState是保存登录的token等信息到本地:

    owner.createState = function(token, callback) {
var state = owner.getState();
state.account = token.username;
state.token = token.tokenstr;
owner.setState(state);
return callback();
};
    /**
* 设置当前状态
**/
owner.setState = function(state) {
state = state || {};
localStorage.setItem('$state', JSON.stringify(state));
//var settings = owner.getSettings();
//settings.gestures = '';
//owner.setSettings(settings);
};

2.重写login.html的toMain()方法:也就是在跳转之前先对本地的token进行验证:

                    var toMain = function() {
//跳转之前先验证token
var stateText = localStorage.getItem('$state') || "{}";
var state = JSON.parse(stateText);
var isValidToken = true;
if(state != null && state.token!=null){
//如果token生效就加载页面,如果不生效就返回到登录页面
$.ajax({
url:appServerAddressPrefix+"/mobile/token/validateToken.html",
async:false,
data:{"tokenStr":state.token},
success:function(res){
if(res && res.success){
//根据tokenStr判断是否需要更新本地token
if(res.data.tokenstr != state.token){
$.alert("需要更新Token");
state.token = res.data.tokenstr;
localStorage.setItem('$state', JSON.stringify(state));
}
}else{
//提示token无效且将标记设为false不进行跳转
$.toast(res.msg);
isValidToken = false;
}
},
dataType:'json'
});
}
if(!isValidToken){//如果Token无效就返回不跳转主页面
return;
}
//进行页面跳转
$.fire(mainPage, 'show', null);
setTimeout(function() {
$.openWindow({
id: 'main',
show: {
aniShow: 'pop-in'
},
waiting: {
autoShow: false
}
});
}, 0);
};

2.下拉刷新的思想:

  在mui.init事件中声明下拉刷新,如果是最后一页就结束下拉刷新事件。 mui.init...的auto:true,是页面初始化自动调用一次对应的事件。

页面:

<!DOCTYPE html>
<html> <head>
<meta charset="utf-8">
<title>Hello MUI</title>
<meta name="viewport" content="width=device-width, initial-scale=1,maximum-scale=1,user-scalable=no">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black"> <!--标准mui.css-->
<link rel="stylesheet" href="../css/mui.min.css">
<!--App自定义的css-->
<link rel="stylesheet" type="text/css" href="../css/app.css"/>
<style>
.mui-content>.mui-table-view:first-child {
margin-top: -1px;
}
#pullrefresh{
margin-top: 80px;
}
.mui-table-view div{
float: left;
}
</style>
</head> <body>
<header class="mui-bar mui-bar-nav">
<a class="mui-action-back mui-icon mui-icon-left-nav mui-pull-left"></a>
<h1 class="mui-title">用户列表</h1>
</header>
<div class="mui-content">
<div style="margin:5px 0px ;">
<table width="100%" class="table" id="tablevalue">
<tr>
<th width=25%>序号</th>
<th width=25%>姓名</th>
<th width=25%>性别</th>
<th width=25%>地址</th>
</tr>
</table>
</div> <!--下拉刷新容器-->
<div id="pullrefresh" class="mui-scroll-wrapper">
<div class="mui-scroll">
<!--数据列表-->
<ul class="mui-table-view mui-table-view-chevron">
<!--<li class="mui-table-view-cell">
<a class="mui-navigate-right">init</a>
</li>-->
</ul>
</div>
</div>
</div>
</body>
<script src="../js/mui.min.js" type="text/javascript" charset="utf-8"></script>
<script src="../js/constants.js" type="text/javascript" charset="utf-8"></script>
<script src="../js/user.js" type="text/javascript" charset="utf-8"></script>
</html>

页面对应的JS:

    mui.init({
pullRefresh: {
container: '#pullrefresh',
down: {//下拉刷新未实现
style:'circle',
callback: pulldownRefresh
},
up: {//上拉刷新实现
auto:true,
contentrefresh: '正在加载...',
callback: pullupRefresh
}
}
}); var downPage = 0,upPage=0;//标记下拉、上滑动的页号
var count = 0; function pullupRefresh() {
setTimeout(function() {//将主要代码有个延迟是为了有个缓冲的过程,当然可以不延迟,显示效果不太好
upPage++;
mui.post(appServerAddressPrefix+"/mobile/user/getUsers.html",{"pageNum":upPage},function(res){
//1.添加数据
addData(res.list,res.isFirstPage); //2.刷新数据,如果是最后一页停止加载加载事件
/*if(res.isLastPage){//刷新数据,如果是最后一页就停止上滑刷新事件
mui('#pullrefresh').pullRefresh().endPullupToRefresh(true);
}else{
mui('#pullrefresh').pullRefresh().endPullupToRefresh();
}*/
mui('#pullrefresh').pullRefresh().endPullupToRefresh(res.isLastPage);
},'json');
}, 1500);
} function addData(datas,isfirstpage) {
var table = document.body.querySelector('.mui-table-view');
var cells = document.body.querySelectorAll('.mui-table-view-cell');
for(var i = cells.length, len = i + datas.length; i < len; i++) {
var li = document.createElement('li');
var user = datas[i-cells.length];
li.className = 'mui-table-view-cell';
li.innerHTML = '<a class="mui-navigate-right">'+user.username +' '+user.sex+ '</a>';
//下拉刷新,新纪录插到最前面;
table.insertBefore(li, table.firstChild);
}
if(!isfirstpage){//如果不是第一页就提示加载 了数据
mui.toast("为你加载了"+datas.length+"条数据!");
}
}
/**
* 下拉刷新具体业务实现
*/
function pulldownRefresh() {
setTimeout(function() {
addData();
mui('#pullrefresh').pullRefresh().endPulldownToRefresh();
mui.toast("为你推荐了5篇文章");
}, 1500);
}

效果如下:

          

app代码git地址:https://github.com/qiao-zhi/MyApp.git

后端git与上面的web项目是同一个地址:https://github.com/qiao-zhi/springboot-ssm.git

  至此实现了一个简单的app,在使用的时候我们可以通过HBuilder打一个apk安装包出来,然后通过连接进行下载或者通过二维码扫描进行下载。安卓手机访问http连接后缀是apk的时候会自动安装软件

========HBuilder中app的打包以及手机端的安装========

1.右键项目:发行->发行为原生安装包

 2.然后选择参数配置去补全参数之后进行配置

3.填写应用的appid、选择图标等信息。====一般需要修改默认的log、启动的flash等替代默认图标,当然需要配置一些权限。如果第三方登录还需要在SDK设置选项卡设置appid等信息。当然需要在对应的应用程序后台建立对应的app实现对接。

 4.然后保存之后再次发行为原生安装包(这里可能需要改一下Android的包名)

 5.然后等待打包即可

6.打包成功之后下载安装包

7.下载完成之后文件如下:

8.接下来创建一个http链接进行访问apk即可 (或者通过QQ、微信等将apk传到手机都可以,只是http访问后缀为apk的时候会自动作为app安装软件)

  例如我将它放在自己的服务器上,然后手机端的网页通过http访问链接的时候效果如下:

   http://qiaoliqiang.cn/fileDown/qlq.mytestapp2_0226180452.apk

9.手机端通过网页访问下载app即可,如下:

  

  当然可以做一个二维码来实现扫码下载,二维码中的内容存放上面的地址链接就可以了。如下面:(只能通过浏览器扫码下载,不能通过微信和QQ下载,腾讯只允许扫码安装自己域名下的app、)

    

补充:关于  localStorage

  localStorage 会可以将第一次请求的数据直接存储到本地,这个相当于一个 5M 大小的针对于前端页面的数据库,相比于 cookie 可以节约带宽,但是这个却是只有在高版本的浏览器中才支持的。

  使用 localStorage 创建一个本地存储的 name/value 对。localStorage 用于长久保存整个网站的数据,保存的数据没有过期时间,直到手动去删除。localStorage 属性是只读的。

#保存
localStorage.setItem("key", "value"); #读取
var lastname = localStorage.getItem("key"); #删除
localStorage.removeItem("key");

(1) localStorage的key不允许重复,会产生覆盖

        localStorage.setItem("name", "zhangsan");
localStorage.setItem("name", "lisi");
localStorage.setItem("age", "25");
console.log(localStorage);

结果:

(2)localStorage的数据会永久生效。同一浏览器,标签页全部共享,它是直接存到电脑硬盘上的。

(3)sessionStorage是当前会话有效,用法同localStorage。

springboot+layui实现PC端用户的增删改查 & 整合mui实现app端的自动登录和用户的上拉加载 & HBuilder打包app并在手机端下载安装的更多相关文章

  1. 移动端上拉加载下拉刷新插件-mescroll.js插件

    官网地址是:http://www.mescroll.com // 初始化mescroll function initMeScroll() { //创建MeScroll对象,内部已默认开启下拉刷新,自动 ...

  2. 用SpringBoot+MySql+JPA实现对数据库的增删改查和分页

    使用SpringBoot+Mysql+JPA实现对数据库的增删改查和分页      JPA是Java Persistence API的简称,中文名Java持久层API,是JDK 5.0注解或XML描述 ...

  3. AD 域服务简介(三)- Java 对 AD 域用户的增删改查操作

    博客地址:http://www.moonxy.com 关于AD 域服务器搭建及其使用,请参阅:AD 域服务简介(一) - 基于 LDAP 的 AD 域服务器搭建及其使用 Java 获取 AD 域用户, ...

  4. 大数据之路week05--day01(JDBC 初识之实现一个系统 实现用户选择增删改查 未优化版本)

    要求,实现用户选择增删改查. 给出mysql文件,朋友们可以自己运行导入到自己的数据库中: /* Navicat MySQL Data Transfer Source Server : mysql S ...

  5. 移动端touch事件 || 上拉加载更多

    前言: 说多了都是泪,在进行项目开发时,在上拉加载更多实现分页效果的问题上,由于当时开发任务紧急,所以就百度找了各种移动端的上拉下拉 实现加载更多的插件.然后就留下了个坑:上拉加载的时候会由于用户错误 ...

  6. 基于SwiperJs的H5/移动端下拉刷新上拉加载更多的效果

    最早时,公司的H5项目中曾用过点击一个"加载更多"的DOM元素来实现分页的功能,后来又用过网上有人写的一个上拉加载更多的插件,那个插件是页面将要滚动到底部时就自动请求数据并插入到页 ...

  7. 基于SwiperJs的H5/移动端下拉刷新上拉加载更多

    最早时,公司的H5项目中曾用过点击一个"加载更多"的DOM元素来实现分页的功能,后来又用过网上有人写的一个上拉加载更多的插件,那个插件是页面将要滚动到底部时就自动请求数据并插入到页 ...

  8. 移动端h5列表页上拉加载更多

    背景 上星期公司要求做一个回收书籍的h5给安卓用,里面有一个功能是回收记录列表.设计师那边出的稿子是没有要求分页或者是上拉刷新的,但是众所周知,列表页数据很多的情况下,h5加载是很慢的.所以我一开始是 ...

  9. vux-scroller实现移动端上拉加载功能

    本文将讲述vue-cli+vux-scroller实现移动端的上拉加载功能: 纠错声明:网上查阅资料看到很多人都将vux和vuex弄混,在这里我们先解释一下,vuex是vue框架自带的组件,是数据状态 ...

随机推荐

  1. oracle出现无法响应新的请求,报ora-12516错误

    oracle的会话数超出了限制,一般都是由于多次connect建立多个连接会话引起.   解决办法: (oracle登录后台,1)sqlplus /nolog  2)conn / as sysdba) ...

  2. Nginx入门篇-基础知识与linux下安装操作

    我们要深刻理解学习NG的原理与安装方法,要切合实际结合业务需求,应用场景进行灵活使用. 一.Nginx知识简述Nginx是一个高性能的HTTP服务器和反向代理服务器,也是一个 IMAP/POP3/SM ...

  3. day-03(js)

    回顾: css: 层叠样式表 作用: 渲染页面 提供工作效率,将html和样式分离 和html的整合 方式1:内联样式表 通过标签的style属性 <xxx style="...&qu ...

  4. 记一次给自己的本子更换一个SSD盘

    记一次给自己的本子更换一个SSD盘 关于笔记本电脑:特别讨厌联想的本子(个人习惯:键盘超级硬-按着手疼)dell的可以考虑一下,不过如果我推荐的话:小米的本子还是可以考虑一下的一般买的话建议买6000 ...

  5. As 400错

    8:25 Gradle sync started 8:25 Gradle sync failed: Unable to tunnel through proxy. Proxy returns &quo ...

  6. JavaSE_坚持读源码_HashMap对象_put_Java1.7

    当你往HashMap里面put时,你其实在干什么? /** * Associates the specified value with the specified key in this map. * ...

  7. 《Go并发编程实战》读书笔记-初识Go语言

    <Go并发编程实战>读书笔记-初识Go语言 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 在讲解怎样用Go语言之前,我们先介绍Go语言的特性,基础概念和标准命令. 一. ...

  8. Shell中引号的操作

    单引号.双引号.反撇号的作用与区别 单引号属于强引用,它会忽略所有被引起来的字符的特殊处理,被引用起来的字符会被原封不动的使用,唯一需要注意的点是不允许引用自身: 示例如下: sh-4.2# echo ...

  9. golang json序列化

    结构体序列化 func main() { var j = js{ Name: "zhangsan", Age: 16, Sal: 1500.3, Intro: "aiha ...

  10. HTML第二耍 列表标签

    先复习下上一节 <!doctype html> <html> <head> <meta charset="utf-8"> <t ...