浏览器存储及 HTML5 拖放

论坛 期权论坛 期权     
百果科技研发团队   2019-6-10 03:55   3189   0
Part
1
浏览器存储
    浏览器存储数据有诸多益处,最主要的一点是能快速访问(网页)数据。
目前主流的浏览器端数据存储方法有:Cookies,Local Storage,Session Storage,IndexedDB(不常用)。
    还有一些不推荐使用的技术如 FlashCookie,GoogleGear,UserData(IE),Web SQL(W3C 已废弃其标准的制定)。
    除此之外,缓存也是浏览器的一种存储方式,其技术有:Application Cache(已废弃)、Service Workers (详情可见 PWA  - 渐进式 WEB 应用)。
Cookie
    由于 http 协议是无状态的,一旦客户端和服务器的数据交换完毕,就会断开连接,再次请求,会重新连接,这就说明服务器单从网络连接上是没有办法知道用户身份的。怎么办呢?那就给每次新的用户请求时,给它颁发一个身份证(独一无二)吧,下次访问,必须带上身份证,这样服务器就会知道是谁来访问了,针对不同用户,做出不同的响应。而 Cookie 的功能就是用于存储这些唯一标识,每次与服务器通信时,都会把这些数据给带上。
Cookie操作流程示意图


    当我们首次访问某网站时,服务器会在报文头中使用 Set-Cookie 字段给我们分配一个或多个标识,浏览器会将其自动保存。

在之后浏览器对该服务器请求时,将会自动带上 Cookie 数据,跟随着请求头中传送到服务器。
1Cookie的属性
    Cookie 由变量名和值组成,类似 Javascript 变量。其属性里既有标准的 Cookie 变量,也有用户自己创建的变量,属性中变量是用“变量=值”形式来保存。Cookie 就是一串字符串,格式就是键值对,分号隔开,三个属性可有可无。
    NAME 为该 Cookie 名称
Expires:有效日期(默认关闭浏览器后失效, -1为马上删除)
    Domain: 有效域名 (默认服务器的域名)
Path:有效路径(默认为 / )
2
cookie的增删改查
document.cookie方法

    Cookie 技术比较古老,其以字符串的方式存储数据,用分号分隔一对键值。它也没有提供简便的 AP 让我们进行操作。增上改查都可以调用 document.cookie,该方法基本不会覆盖整个 cookie 而是覆盖对应的值:
增/改:
    document.cookie= 'NAME=VALUE;Expires=DATE;
    Path=PATH;Domain=DOMAIN_NAME;
删:
    document.cookie= 'NAME=VALUE;Expires = -1'
查:
    document.cookie   
    一般我们都会将增删改查方法封装起来,方便调用。另外,Cookie 采用同源政策,每个域名可存储 4KB 数据(因浏览器不同而变化,部分浏览器还限制了 Cookie 的个数)。
    在过去的开发中,我们经常把很多非服务器必要的数据存放在 Cookie,导致每次请求都带上这些数据,浪费流量,很不符合现代的开发思想。


Web Storage
    Web Storage 是 HTML5 中提出的标准,主要目的是克服 Cookie 的一些限制,当数据需要被严格控制在客户端上时,无需持续的将数据发回服务器。
    WebStorage 提供两种类型的 API:localStorage 和 sessionStorage,两者的区别看名字就有大概了解, localStorage 在本地永久性存储数据,除非显式将其删除或清空,sessionStorage 存储的数据只在会话期间有效,关闭浏览器则自动删除。两个对象都有共同的 API。

    Api:

    保存数据:localStorage.setItem(key,value)
    读取数据:localStorage.getItem(key)
    删除单个数据:localStorage.removeItem(key)
    删除所有数据:localStorage.clear()
    得到某个索引的 key:localStorage.key(index)
    Storage 也是采取同源政策,若需要跨域获取,可以使用 postMessage 接口。
    Local Storage 与 Session Storage 两者的区别:
    两者完全相同,唯独不同在于,Session Storage仅在同一个窗口生效,当关闭窗口便会清空,而 Local storage,除非手动清空,不然就永久存在。
IndexedDB
    IndexedDB 是一个为了能够在客户端存储可观数量的结构化数据,并且在这些数据上使用索引进行高性能检索的 API。
    IndexedDB 分别为同步和异步访问提供了单独的 API ,异步 API 方法调用完后会立即返回,同步 API 还没有在任何浏览器中得以实现。它原本是要和 WebWorkers 一起使用的。
    因使用场景较少,目前前端开发比较少会用到,就不详细说了。
IndexedDB 的异步 api


    目前前端开发者主要用到的浏览器存储方式是 Local Storage、Session Storage,而 Cookie 除了给服务器认证用户标识外,多用于互联网的精准广告定向技术中。

    虽然本地存储技术有着极大的便捷性,但它们也存在风险,例如 XSS、CSRF 攻击,当然我们也有一定的应对策略去应对。


Part
2
HTML5 拖放
拖拽:Drag
释放:Drop
因此两个都动作合起来就是一个拖放事件,拖放 API 是 HTML5 新标准中的新特性。

在拖放过程中,涉及两个对象
    源对象,指的是我们鼠标点击的一个事物,这里可以是一张图片,一个 DIV ,一段文本等等。
    目标对象,指的是我们拖动源对象后移动到一块区域,源对象可以进入这个区域,可以在这个区域上方悬停(未松手),可以释松手释放将源对象放置此处(已松手),也可以悬停后离开该区域。

    在 HTML5 中,所有元素只要加上 draggable="true" 属性,即可被拖动。
拖动我!

注意:图片、链接、被选中的文字是默认可拖动的,不需要设置 draggable。
    拖放事件是一个复杂的过程,要完成一个最简单的拖放事件,我们除了要将元素设置为可拖动外,还要目的地对象允许被释放。
拖拽 API 总共就是这七个函数,其触发顺序为:
dragstart -> drag(不断触发) -> dragenter -> dragover(不断触发) -> dragleave / drop -> dragend
    dragover 事件的默认行为是拒绝接受任何被拖放的元素。因此,我们要阻止浏览器这种默认行为。
dragOver (ev) {
        ev.preventDefault() // 阻止浏览器默认行为
}

    这样,我们就能把源对象拖放到目标对象中,但是触发的事件需要自己写在 drop 中,我们可以通过回调参数,获取到源对象和目标对象,进行数据处理。
拖放的 API
dataTransfer 对象
    每个拖放事件都会回调一个 DragEvent 对象的参数,它派生于  MouseEvent,具有 Event 对象的所有功能,并增加了 dataTransfer,它是用于记录和设置拖放事件的对象。

    通过 effectAllowed 和 dropEffect 共同设置拖放时指针的图标
dragStart (ev) {
    // 指定拖动时被允许的效果,可设置
    //move,copy,link,copyLink,copyMove,linkMove,all,none     ev.dataTransfer.effectAllowed = 'all'
}
dragOver (ev, effectIndex) {
    ev.preventDefault() // 阻止浏览器默认行为
        ev.dataTransfer.dropEffect = 'move' // 改变指针图标, 可设置move,copy,link
}


    使用 setDragImage 方法设置拖拽时的背景图片,接收三个参数(图片路径,相对x位移,相对y位移)
dragStart (ev) {
        // 设置拖拽时背景图片
        const img = new Image()
        img.src = '/static/img/bgy.png'
        ev.dataTransfer.setDragImage(img, 120, 10)
}


     我们从外部把文件(这里以图片为例)拖动到浏览器中,可以从 dataTransfer.files 中获取到,并进行 dom 操作添加到页面指定位置中。
drop (ev) {
        ev.preventDefault() // 浏览器默认打开拖进来的图片
        let files = ev.dataTransfer.files
        Array.from(files).forEach((file) => {
                 const fr = new FileReader()
                 file && fr.readAsDataURL(file)
                 fr.onload = function () {
                         if (fr.result.includes('data:image'))
                         {
                                  const img = new Image()
                                  img.src = fr.result
                                  img.style.width = '20px'
                                 document.querySelector('.blue').appendChild(img)
                         }
                 }
        })
}

    另外,其实 dataTransfer 对象中还有 setData,getData 方法,用于存放数据,但是其实这里有点小坑,个人建议用外部变量去存储更为便捷。


百果科技研发团队
致力于提供更好的技术
长按识别二维码
关注我们

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:
帖子:
精华:
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP