• 仿微博字符统计和本地存储功能的实现


    1.1.1 摘要

    随着移动设备和Web应用的普及,为了更好的便于用户的使用,对于网页或应用程序的用户体验要求就越来越高,确实是这样,作为用户更喜欢选择用户体验效果好的网站或应用程序,所以作为开发者的我们就需要开发出更人生化的应用程序了。

    相信许多人有使用微博的经验,像微博这样的社交平台,好的用户体验就变得尤其重要了。

    例如:我们在发微博时,文本框会实时地提示我们剩余字符数,这样人性化的提示方便了用户知道微博字数的限制,同时也限制了用户的输入字数。

    有一句话我们要牢记在心的是:凡是输入,必有限制;凡是输入,必须校验。

    在接下来的博文中,我们将介绍如何实现输入字符实时提示功能和本地存储(localStorage)技术。

    本文目录

    1.1.2 正文

    jQuery字符统计插件

    现在,我们以新浪微博发送微博输入框为例子,介绍使用jQuery实现实时提示用户剩余字符数。

    新浪微博是限制140个中文(280个英文),当然还有各种其他字符空格的情况,在用户输入达到限制之前或达到了,好的用户体验应该提示用户接近或达到了限制,当然我们可以通过使用不同颜色或加粗字体方式提示用户。

    charcount0

    图1新浪微博用户输入限制

    字符数统计插件会在输入框后创建一个同级元素span,它用来显示当前剩余字符数,当触发输入框的keyup、keydown和change事件时,实时修改span中剩余字符数,如果剩余字符数接近“warning”(接近零)修改CSS样式提示用户接近输入限制。

    当剩余字符达到“warning”时,在span元素中添加相应的样式类,当剩余字符等于或大于输入限制时,添加相应的样式类提示用户已经超出字符数限制。

    我们通过字符数统计插件在页面中动态地插入如下代码:

    <!-- adds element dynamic -->
    <span class="counter">140</span>

    在默认情况下,字符限制是140个,当可输入字符数少于等于25个提示用户,当可输入字符数少于等于0时,提示用户字符数超出了限制。下面我们定义默认情况下条件对象:

    // The default limitation.
    var defaults = {
        allowed: 140,
        warning: 25,
        css: 'counter',
        counterElement: 'span',
        cssWarning: 'warning',
        cssExceeded: 'exceeded',
        counterText: ''
    };

    上面,我们定义了defaults对象,它包含allowed、warning、css、cssWarning和cssExceeded等属性,通过修改defaults对象属性,我们可以很方便修改字符统计插件。

    Allowed:允许输入的字符数。

    Warning:提示用户剩余字符数接近限零。

    Css:添加到counter元素的CSS样式类名。

    cssWarning:警告提示样式。

    cssExceeded:超出字符限制提示样式。

    接下来,我们在字符统计插件中定义方法calculate(),它计算当前剩余字符数,如果到达了警告范围则在页面中增加样式类“warning”,当剩余字符数少于等于零时,在页面中增加样式“exceeded”。

    /***
    * Calculates the char
    * @param obj
    */
    function calculate(obj) {
    
        // Get the count.
        var count = getLength($(obj).val());
        var available = options.allowed - count;
    
        if (available <= options.warning && available >= 0) {
            $(obj).next().addClass(options.cssWarning);
        }
        else {
            $(obj).next().removeClass(options.cssWarning);
        }
        if (available < 0) {
            $(obj).next().addClass(options.cssExceeded);
        }
        else {
            $(obj).next().removeClass(options.cssExceeded);
        }
        $(obj).next().html(options.counterText + available);
    }

    我们又定义方法getLength(),当输入字符是中文时totLen加1,如果是英文字符或数字时totLen加0.5(默认允许输入140个中文字符)。

    /**
    * Get the length of char.
    * @param str
    * @return {Number}
    */
    function getLength(str) {
        var totLen = 0;
        for (var i = 0; i < str.length; i++) {
            // If the char is Chinese.
            if (str.charCodeAt(i) > 256) {
                totLen += 1;
            }
            else {
                totLen += 0.5;
            }
        }
        return Math.floor(totLen);
    }

    接下来,我们在控件中绑定keyup(),keydown()和change()事件方法,当页面对象触发keyup(),keydown()或change()事件方法时,调用calculate()方法计算当前剩余的字符数,并且添加相应的CSS样式到页面中。

    // Binds text area keyup, keydown and change event.
    this.each(function() {
        $(this).after('<' + options.counterElement + ' class="' + options.css + '">' + options.counterText + '</' +
                    options.counterElement + '>');
        calculate(this);
        $(this).keyup(function() { calculate(this), storeWeibo(this) });
        $(this).keydown(function() { calculate(this), storeWeibo(this) });
        $(this).change(function() { calculatea(this) });
    });

    Web Storage

    现在,我们基本实现了jQuery字符数统计插件功能了,相信许多人都注意到,如果我们在发微博时,没有发送出去的微博下次打开页面,发送框依然保存着我们未发送的微博,即使关闭浏览器重新打开页面,我们没发送的信息依然存在。

    其实,要实现这一个功能方法是多种多样的,例如我们可以使用:CookiesSession等技术。

    随着HTML5规范的制定,与此同时W3C制定了网络存储(Web Storage)的规范,它提供将数据存储在客户端中,直到Session过期(会话存储)或超出本地容量(本地存储),它比传统的Cookies存储功能更强大、更容易实现和容量更大(大部分浏览器支持5M的本地存储)。

    会话存储

    会话存储:它将数据保存在会话中,一旦我们关闭浏览器选项卡时,会话中的数据将失效。

    本地存储

    本地存储:当数据需要持久地保存在客户端中,这时我们可以使用本地存储(Local Storage),它是以key/value 的形式来存储数据的,如果关闭了页面或浏览器后,重新打开页面数据依然存在,它提供了数据的持久保存。一个简单的应用是:记录用户访问页面的次数。

     charcount1

    图2存储空间的对比

    接下来,我们将介绍如何使用本地存储保存用户数据。

    由于,localStorage提供了setItem(),getItem(),removeItem(),key()和clear() 5个方法,和一个属性length,具体定义如下:

    // Storage definition.
    interface Storage {
      readonly attribute unsigned long length;
      DOMString key(in unsigned long index);
      getter any getItem(in DOMString key);
      setter creator void setItem(in DOMString key, in any value);
      deleter void removeItem(in DOMString key);
      void clear();
    };

    在现代浏览器中使用本地存储是非常的简单,我们只需在Javascript代码中直接调用localStorage对象的方法或属性就OK了。

    // stores the username 'jkrush',
    // then get the username.
    localStorage.setItem('username', 'jkrush');
    var userName = localStorage.getItem('username');

    上面,我们通过调用localStorage的setItem()和getItem()方法实现数据的存储和获取,由于localStorage是以Key/Value形式存储数据的,所以我们在存储时需要提供Key/Value值,然后调用getItem()方法获取存储在Key中的值。

    由于本地存储是以Key/Value的形式进行存储的,那么我们可以很容易存储字符串类型的数据,如果我们需要存储对象类型,那么本地存储就显得捉襟见肘了。

    假设,我们把一个student对象存储到localStorage中,具体代码如下:

    // Defines a student object.
    var student = {
        name: 'JK_Rush',
        age: '26',
        sex: 'male'
    };
    
    // Prints student object
    console.log(student);
    
    // Stores student object.
    // Gets student object again.
    localStorage.setItem('student', student);
    console.log(localStorage.getItem('student'));

     charcount

    图3 localStorage存储对象

    通过上面示例,我们注意到在Firebug的控制台中输出的并不是真正的student对象,而是student对象的信息而已。

    那么我们该如何把对象存储到localStorage中呢?其实,我们可以把对象序列化为JSON数据进行存储,最后通过反序列化把JSON数据转换为对象。具体实现如下:

    // Defines a student object.
    var student = {
        name: 'JK_Rush',
        age: '26',
        sex: 'male'
    };
    
    console.log(student);
    
    // Serializes the object to json string.
    localStorage.setItem('student', JSON.stringify(student));
    
    // Deserializes the json string to object.
    console.log(JSON.parse(localStorage.getItem('student')));

    上面示例中,在存储student对象之前,我们使用JSON的stringify()方法序列化对象为JSON字符串,然后存储到localStorage中;如果我们要获取student对象,只需使用JSON的parse()方法反序列化字符串为对象。

     charcount3

    图4 localStorage存储对象

    上面,我们实现了student对象转换为JSON格式字符串存储到localStorage中,接下来,我们在前面的例子中添加localStorage功能,具体代码如下:

    /**
    * Store user data into local storage.
    * @param obj
    */
    function storeWeibo(obj) {
    
        // Checks the browser supports local storage or not.
        if (window.localStorage) {
            localStorage.setItem('publisherTop_word', $(obj).val());
        }
        else {
    
            // For instance, ie 6 and 7 do not support local storage,
            // so we need to provider other way.
            window.localStorage = {
                getItem: function(sKey) {
                    if (!sKey || !this.hasOwnProperty(sKey)) { return null; }
                    return unescape(document.cookie.replace(new RegExp("(?:^|.*;\\s*)" + escape(sKey).replace(/[\-\.\+\*]/g,
                                "\\$&") + "\\s*\\=\\s*((?:[^;](?!;))*[^;]?).*"), "$1"));
                },
                key: function(nKeyId) {
                    return unescape(document.cookie.replace(/\s*\=(?:.(?!;))*$/, "").split(/\s*\=(?:[^;](?!;))*[^;]?;\s*/)[nKeyId]);
                },
                setItem: function(sKey, sValue) {
                    if (!sKey) { return; }
                    document.cookie = escape(sKey) + "=" + escape(sValue) + "; expires=Tue, 19 Jan 2038 03:14:07 GMT; path=/";
                    this.length = document.cookie.match(/\=/g).length;
                },
                length: 0,
                removeItem: function(sKey) {
                    if (!sKey || !this.hasOwnProperty(sKey)) { return; }
                    document.cookie = escape(sKey) + "=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/";
                    this.length--;
                },
                hasOwnProperty: function(sKey) {
                    return (new RegExp("(?:^|;\\s*)" + escape(sKey).replace(/[\-\.\+\*]/g, "\\$&") + "\\s*\\=")).test(document.cookie);
                }
            };
            window.localStorage.length = (document.cookie.match(/\=/g) || window.localStorage).length;
        }
    }

    现在我们在自定义字符统计插件(jquery.charcount.js)中,添加方法storeWeibo(),首先我们判断当前浏览器是否支持localStorage,主流的浏览器如:Chrome、Firefox、Opera、Safari以及IE 8都支持本地存储(localStorage)和会话存储(sessionStorage)。

    如果浏览器支持本地存储,那么我们可以直接调用localStorage的setItem()方法,将textarea中的数据存储起来;当我们再次打开页面或浏览器,首先检查localStorage是否存储了相应的数据,如果有数据存储,那么我们再次把数据取出显示到textarea中。

    但由于一些用户可能使用旧版的浏览器(如:IE6和IE7),考虑到兼容我们必须提供支持旧版浏览器的方案。

    我们知道旧版浏览器(如:IE6和IE7),它们支持Cookies的持久化存储方式,所以我们使用Cookies实现getItem(), setItem()和removeItem()等方法。

     charcount4

     charcount5

    图5 主流浏览器支持Web Storage

    现在,我们已经完成了字符统计插件jquery.charcount.js,由于时间的关系我们已经把发送框的界面设计好了,具体的HTML代码如下:

    <!-- From design-->
    <body>
        <form id="form" method="post">
        <h2>
            有什么新鲜事想告诉大家?</h2>
        <div>
            <label class="mali_oglas_kategorija" for="message">
                有什么新鲜事想告诉大家?<b></b></label>
            <textarea id="weiboMsg" placeholder="请Fun享"></textarea>
            <span class="counter"></span>
            <input onclick="SaveCache()" type="submit" value="发布">
        </div>
        </form>
    </body>

     charcount6

    图6 发送框界面设计

    接下来,我们在页面代码中引用jQuery库和自定义字符统计插件jquery.charcount.js,具体代码如下:

    <!-- Adds Javascript reference -->
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"></script>
    <script type="text/javascript" src="./js/jquery.charcount.js"></script>
    

    上面,我们直接引用Google提供的jQuery库,当然我们也把jQuery库下载到本地,然后引入到项目中,接下来我们在HTML页面中添加调用字符统计插件的代码,具体代码如下:

    <!-- When document ready invokes charCount function-->
    <script type="text/javascript">
        $(document).ready(function () {
            // Uses default setting.
            $("#weiboMsg").charCount();
        });
    </script>

    上面,我们完成了在页面代码中调用字符统计插件,每当我们在文本框中输入字符时,都会实时地显示剩余的字符数,而且我们在文本框中输入的字符都会保存到localStorage中。

    接下来,我们分别在Chrome和Firefox中查看保存在localStorage中的数据。

    首先,我们打开Chrome的“开发者工具”(Ctr+Shift+I),然后我们选择“Resources”选项,这时我们就可以看到保存在localStorage中的数据了。

    charcount10

    图7 Chrome的本地存储

        

    同样,我们打开Firefox的“Firebug”(F12),然后我们选择“DOM”选项,这时我们需要查找window的对象localStorage,这样就可以看到保存在localStorage中的数据了。

    charcount9 图8 Firefox的本地存储

    我们知道IE8也是支持localStorage对象的,但是我做测试时候发现IE8中一直提示localStorage对象未定义,后来我上Stackoverflow查看了一下,有人说在IE8中,localStorage对象是依赖于域名的,所以需要运行在Web服务器中才可以成功保存数据到localStorage中。

    1.1.3 总结

    本文通过微博发送框例子介绍了如何定义jQuery字符统计插件和本地存储技术,首先,我们知道限制用户输入是必须的,但如何有效而且人性化提示用户输入限制呢?这里我们通过定义一个jQuery插件,动态地统计剩余字符数。

    我们注意到微博通过本地存储技术,保存用户在发送框中的数据,一旦数据发送了就清空本地存储,反之保存用户的输入。

    参考

    Demo下载

  • 相关阅读:
    Vue自定义指令
    Vue实例生命周期
    Vue学习目录
    Vue表单控件绑定
    Vue事件处理
    Vue数组更新及过滤排序
    Vue模板逻辑
    Vue模板内容
    Vue实例对象的数据选项
    Vue组件基础用法
  • 原文地址:https://www.cnblogs.com/rush/p/2883694.html
Copyright © 2020-2023  润新知