通过在页面应用使用 localStorage 提升用户使用体验。
背景
首先,来说两个关于用户体验的经历。
大学在校期间,经常被安排在教学系统上填写各种信息采集表,教学系统是学校找外面外包公司做的,给的钱多,出的活却很烂,信息采集的表单是很老旧的 table 布局,一页一个表单,一个表单有几十个项,当你辛辛苦苦填完了整个表单,点击提交按钮页面却没有响应,系统卡了?你抱着试一试的心态刷新了页面,恭喜你,之前填的数据全部丢失,像是卷入了一个黑洞,你又从第一项开始填。这样的系统毫无用户体验可言,不是强制要求,没人愿意打开这样的网站。
到了大三找实习,投简历到阿里,需要在系统上填一些信息,对应的也是一个表单很多项,巧的是,提交时页面卡住了,虽然脑海中重现了被学校系统支配的恐惧,但除了刷新页面别无选择,刷新之后,页面回来了,之前填写的数据竟然原封不动的回来了,当时很菜,不知道是怎么实现,就觉得背后的技术肯定很厉害,后面才去了解这方面的知识。
后来了解了 localStorage 之后,才意识到表单数据保存背后的技术很简单,但是用在了相应的场景,给用户带来的是非常棒的用户体验,从那之后,我对阿里校招页面一直很有好感。
关于 localStorage
容量
localStorage 的容量是相对其作用域而言,而 localStorage 的作用域是 协议 + 主机名 + 端口
,目前业界默认同一作用域下拥有 5M 的容量,手机端和 PC 端标准略有不同。
数据以键值对方式存储,同一作用域下的数据可以被相互访问,并且不允许跨域。
注意: localStorage 存储只支持存储字符串,因此在存储对象时需要使用 JSON.stringify()
以及 JSON.parse()
进行序列化以及解析。
API
1 2 3 4 5
| localStorage.setItem("name","leeon"); localStorage.getItem("name"); localStorage.key(0); localStorage.removeItem("name"); localStorage.clear();
|
应用场景
上面提到的表单数据保存是最常见的场景,避免信息的丢失,实现方式是在 input
标签 blur
(失焦) 后,触发 localStorage 存储,页面加载之后,从 localStorage 读取已存储的数据,表单提交成功后,移除存储的数据。
还有一种情况,类似于博客系统内置的评论功能,页面可以参见下图,这样的场景,没有登陆,用户信息不能持久化保存,每次评论都需要再次填写基础信息
应用 localStorage 保存用户基础信息,我用 React 写了一个评论框输入组件,包含的 _saveUsername
和 _loadUsername
方法对应着用户信息的存储以及获取,分别会在输入框失焦以及页面渲染时被调用,体验更好的方式则是提供一个保存基本信息的选项,用户在勾选后,信息被保存。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
| class CommentInput extends Component { constructor(props) { super(props); this.state = { username: '', content: '' } } static PropType = { onSubmit: PropType.func } componentDidMount() { this.textarea.focus() } componentWillMount() { this._loadUsername() } _saveUsername (username) { localStorage.setItem('username', username) } _loadUsername () { const username = localStorage.getItem('username') if(username) { this.setState({username}) } } handleUserNameBlur (event) { this._saveUsername(event.target.value) } handleUsernameChange (event) { this.setState({ username: event.target.value }) } handleContentChange (event) { this.setState({ content: event.target.value }) } handleSubmit () { if(this.props.onSubmit) { const {username, content} = this.state this.props.onSubmit({ username: this.state.username, content: this.state.content, createdTime: +new Date() }) } this.setState({content: ''}) } render () { return ( <div className="comment-input"> <div className="comment-field"> <span className="comment-field-name">userName:</span> <div className="comment-field-input"> <input onBlur={this.handleUserNameBlur.bind(this)} value={this.state.username} onChange={this.handleUsernameChange.bind(this)} /> </div> </div> <div className="comment-field"> <span className="comment-field-name">Comment:</span> <div className="comment-field-input"> <textarea ref={(textarea) => {this.textarea = textarea}} value={this.state.content} onChange={this.handleContentChange.bind(this)} ></textarea> </div> </div> <div className="comment-field-button"> <button onClick={this.handleSubmit.bind(this)} >comment</button> </div> </div> ) } }
|
关于用户体验
因为做的工作的原因,遇到一些很棒的网站第一反应是打开控制台看代码,每每看到那些巧妙的代码都赞叹不已,少量的代码带来用户体验的大幅度提升,这是具有很高性价比的一件事。遇到一些烂糟糟的设计,会考虑烂的原因,以及如何去改进,比如渣浪的微博。