دراسات حالة API لتخزين الويب



يوم جيد يا اصدقاء!

في هذه المقالة ، سنلقي نظرة على بضعة أمثلة على استخدام Web Storage API أو كائن التخزين.

ماذا سنفعل بالضبط؟

  • تعلم أن تتذكر وقت تشغيل الفيديو.
  • سنعمل مع نموذج تسجيل الدخول للصفحة.
  • دعنا نكتب منطق قائمة المهام.
  • ننفذ الدردشة.
  • رسم سلة للسلع.

إذن هيا بنا نذهب.

مراجعة قصيرة


يتم استخدام كائن التخزين لتخزين البيانات على جانب العميل ، وبهذا المعنى ، يعمل كبديل لملفات تعريف الارتباط. ميزة التخزين هي حجم التخزين (من 5 ميغابايت ، يعتمد على المتصفح ، عندما يتم تجاوز الحد ، يتم طرح الخطأ "QUOTA_EXCEEDED_ERR") ولا توجد حاجة للوصول إلى الخادم. العيب الرئيسي هو الأمن: يكلف البرنامج النصي الضار للوصول إلى الصفحة ، وتضيع الكتابة. لذلك ، يوصى بشدة بعدم تخزين المعلومات السرية في التخزين.

في الإنصاف ، تجدر الإشارة إلى أن هناك اليوم حلول أكثر تقدمًا لتخزين البيانات على جانب العميل - هذه هي IndexedDB ، Service Workers + Cache API ، إلخ.

يمكنك القراءة عن عمال الخدمة هنا .

تتضمن واجهة برمجة تطبيقات تخزين الويب localStorage و sessionStorage. الفرق بينهما هو وقت تخزين البيانات. في التخزين المحلي ، يتم تخزين البيانات بشكل دائم حتى يتم حذفها "صراحة" (لا يؤدي إعادة تحميل الصفحة أو إغلاقها إلى حذف البيانات). وقت تخزين البيانات في جلسة التخزين ، كما يوحي الاسم ، يقتصر على جلسة المتصفح. نظرًا لأن جلسة التخزين لا تُستخدم تقريبًا تقريبًا في الممارسة العملية ، فسوف نفكر فقط في التخزين المحلي.

ما تحتاج لمعرفته حول التخزين المحلي؟


  • عند استخدام localStorage ، يتم إنشاء تمثيل لعنصر التخزين.
  • يتم تخزين البيانات في localStorage كأزواج المفتاح / القيمة.
  • يتم تخزين البيانات كسلاسل.
  • لا يتم فرز البيانات ، مما يؤدي في بعض الأحيان إلى خلطها (كما سنرى في مثال قائمة المهام).
  • عند تمكين وضع التصفح المتخفي أو الخاص في متصفحك ، قد يصبح استخدام localStorage مستحيلا (يعتمد على المتصفح).

لدى localStorage الطرق التالية:

  • Storage.key (n) - اسم المفتاح مع الفهرس n
  • Storage.getItem () - احصل على العنصر
  • Storage.setItem () - كتابة عنصر
  • Storage.removeItem () - حذف عنصر
  • Storage.clear () - تخزين واضح
  • Storage.length - طول التخزين (عدد العناصر - أزواج المفتاح / القيمة)

في المواصفات ، يبدو مثل هذا:

interface Storage {
    readonly attribute unsigned long length;
    DOMString? key(unsigned long index);
    getter DOMString? getItem(DOMString key);
    setter void setItem(DOMString key, DOMString value);
    deleter void removeItem(DOMString key);
    void clear();
};

تتم كتابة البيانات في وحدة التخزين بإحدى الطرق التالية:

localStorage.color = 'deepskyblue'
localStorage[color] = 'deepskyblue'
localStorage.setItem('color', 'deepskyblue') //    

يمكنك الحصول على البيانات مثل هذا:

localStorage.getItem('color')
localStorage['color']

كيفية التكرار عبر مفاتيح التخزين والحصول على القيم؟


//  1
for (let i = 0; i < localStorage.length; i++) {
    let key = localStorage.key(i)
    console.log(`${key}: ${localStorage.getItem(key)}`)
}

//  2
let keys = Object.keys(localStorage)
for (let key of keys) {
    console.log(`${key}: ${localStorage.getItem(key)}`)
}

كما ذكرنا أعلاه ، فإن البيانات الموجودة في التخزين لها تنسيق سلسلة ، لذلك هناك بعض الصعوبات في كتابة الكائنات ، والتي يمكن حلها بسهولة باستخدام JSON.stringify () - JSON.parse () tandem:

localStorage.user = {
    name: 'Harry'
}
console.dir(localStorage.user) // [object Object]

localStorage.user = JSON.stringify({
    name: 'Harry'
})
let user = JSON.parse(localStorage.user)
console.dir(user.name) // Harry

للتفاعل مع localStorage ، هناك حدث خاص - التخزين (onstorage) ، والذي يحدث عند كتابة / حذف البيانات. له الخصائص التالية:

  • مفتاح - مفتاح
  • oldValue - القيمة القديمة
  • newValue - قيمة جديدة
  • url - عنوان التخزين
  • storageArea - الكائن الذي حدث فيه التغيير

في المواصفات ، يبدو مثل هذا:

[Constructor(DOMString type, optional StorageEventInit eventInitDict)]
    interface StorageEvent : Event {
    readonly attribute DOMString? key;
    readonly attribute DOMString? oldValue;
    readonly attribute DOMString? newValue;
    readonly attribute DOMString url;
    readonly attribute Storage? storageArea;
};

dictionary StorageEventInit : EventInit {
    DOMString? key;
    DOMString? oldValue;
    DOMString? newValue;
    DOMString url;
    Storage? storageArea;
};

هل يسمح التخزين المحلي بالنماذج الأولية؟


Storage.prototype.removeItems = function() {
    for (item in arguments) {
        this.removeItem(arguments[item])
    }
}

localStorage.setItem('first', 'some value')
localStorage.setItem('second', 'some value')

localStorage.removeItems('first', 'second')

console.log(localStorage.length) // 0

كيفية التحقق من البيانات في localStorage؟


//  1
localStorage.setItem('name', 'Harry')

function isExist(name) {
    return (!!localStorage[name])
}

isExist('name') // true

//  2
function isItemExist(name) {
    return (name in localStorage)
}

isItemExist('name') // true

يمكن العثور على متصفح localStorage هنا:



ما يكفي من الكلمات ، حان الوقت لبدء العمل.

أمثلة على الاستخدام


تذكر وقت تشغيل الفيديو


window.onload = () => {
    //   <video>
    let video = document.querySelector('video')
    
    //  localStorage   currentTime ( ),    video.currentTime
    if(localStorage.currentTime) {
        video.currentTime = localStorage.currentTime
    }
    
    //    video.currentTime,     localStorage.currentTime
    video.addEventListener('timeupdate', () => localStorage.currentTime = video.currentTime)
}

تبدو النتيجة كما يلي:



بدء تشغيل الفيديو وإيقاف التشغيل في الثانية الثالثة ، على سبيل المثال. يتم تخزين الوقت الذي تركناه في التخزين المحلي. للتحقق من ذلك ، أعد تحميل أو إغلاق / فتح الصفحة. نرى أن وقت تشغيل الفيديو الحالي لا يزال كما هو.

Codepen

Github

نحن نعمل مع نموذج تسجيل الدخول


يبدو الترميز كالتالي:

<form>
    Login: <input type="text">
    Password: <input type="text">
    <input type="submit">
</form>

لدينا نموذج وثلاثة "مدخلات". بالنسبة إلى كلمة المرور ، نستخدم <input type = "text"> ، لأنه إذا كنت تستخدم النوع الصحيح (كلمة المرور) ، فسيحاول Chrome حفظ البيانات المدخلة ، مما سيمنعنا من تنفيذ وظائفنا الخاصة.

جافا سكريبت:

//         
let form = document.querySelector('form')
let login = document.querySelector('input')
let password = document.querySelector('input + input')

//  localStorage  
//     
//    
if (localStorage.length != 0) {
    login.value = localStorage.login
    password.value = localStorage.password
}

//      "submit"
form.addEventListener('submit', () => {
    //      localStorage
    localStorage.login = login.value
    localStorage.password = password.value
    
    //    hello  world     , 
    //       "welcome"  
    if (login.value == 'hello' && password.value == 'world') {
        document.write('welcome')
    }
})

يرجى ملاحظة أننا لا "التحقق" من صحة النموذج. هذا ، على وجه الخصوص ، يسمح لك بتسجيل الأسطر الفارغة كاسم مستخدم وكلمة مرور.

تبدو النتيجة كالتالي:



نقدم كلمات سحرية.



يتم كتابة البيانات على localStorage ، ويتم عرض تحية على الصفحة.

Codepen

Github

كتابة منطق قائمة المهام


يبدو الترميز كالتالي:

<input type="text"><button class="add">add task</button><button class="clear">clear storage</button>

<ul></ul>

لدينا "إدخال" لإدخال مهمة وزر لإضافة مهمة إلى القائمة وزر لتنظيف القائمة والتخزين وحاوية للقائمة.

جافا سكريبت:

//      
let input = document.querySelector('input')
input.focus()
//       
let addButton = document.querySelector('.add')
//    
let list = document.querySelector('ul')

//   localStorage  
if (localStorage.length != 0) {
    //     /
    for (let i = 0; i < localStorage.length; i++) {
        let key = localStorage.key(i)
        //   -  
        let template = `${localStorage.getItem(key)}`
        //    
        list.insertAdjacentHTML('afterbegin', template)
    }
    
    //      "close" -    
    document.querySelectorAll('.close').forEach(b => {
        //   
        b.addEventListener('click', e => {
            //    "li"
            let item = e.target.parentElement
            //    
            list.removeChild(item)
            //    localStorage
            localStorage.removeItem(`${item.dataset.id}`)
        })
    })
}

//       "Enter"
window.addEventListener('keydown', e => {
    if (e.keyCode == 13) addButton.click()
})

//           ""
addButton.addEventListener('click', () => {
    //   - 
    let text = input.value
    //  ,          "data-id"
    let template = `<li data-id="${++localStorage.length}"><button class="close">V</button><time>${new Date().toLocaleDateString()}</time> <p>${text}</p></li>`
    //   -   
    list.insertAdjacentHTML('afterbegin', template)
    //    localStorage
    localStorage.setItem(`${++localStorage.length}`, template)
    //   
    input.value = ''

    //           ""
    document.querySelector('.close').addEventListener('click', e => {
        //    -   
        let item = e.target.parentElement
        //    
        list.removeChild(item)
        //    localStorage
        localStorage.removeItem(`${item.dataset.id}`)
    })
})

//        ""
document.querySelector('.clear').onclick = () => {
    //  
    localStorage.clear()
    //    
    document.querySelectorAll('li').forEach(item => list.removeChild(item))
    //   
    input.focus()
}

تبدو النتيجة كما يلي:



يتم تخزين المهام المضافة إلى القائمة في localStorage كترميز جاهز. عند إعادة تحميل الصفحة ، يتم تشكيل القائمة من بيانات التخزين (هناك خلط ، كما ذكر أعلاه).



تؤدي إزالة مهمة من القائمة بالنقر فوق علامة الاختيار الخضراء إلى إزالة زوج المفتاح / القيمة المطابق من المستودع.

Codepen

Github

تنفيذ الدردشة


يبدو الترميز كالتالي:

<input type="text">
<button class="send">send message</button>
<button class="save">save chat</button>
<button class="clear">clear chat</button>

<div></div>

لدينا إدخال لإدخال رسالة ، ثلاثة أزرار: لإرسال رسالة ، لحفظ المراسلات وتنظيف الدردشة والتخزين ، بالإضافة إلى حاوية للرسائل.

جافا سكريبت:

//      
let input = document.querySelector('input')
input.focus()

//  
let sendButton = document.querySelector('.send')
let saveButton = document.querySelector('.save')
let clearButton = document.querySelector('.clear')

//  
let box = document.querySelector('div')

//      "messages"
if (localStorage.messages) {
    //  
    localStorage.messages
        .split('</p>,')
        .map(p => box.insertAdjacentHTML('beforeend', p))
}

//   
sendButton.addEventListener('click', () => {
    //   
    let text = document.querySelector('input').value
    //  
    let template = `<p><time>${new Date().toLocaleTimeString()}</time> ${text}</p>`
    //    
    box.insertAdjacentHTML('afterbegin', template)
    //   
    input.value = ''
    //    
    localStorage.message = template
})

//       "Enter"
window.addEventListener('keydown', e => {
    if (e.keyCode == 13) sendButton.click()
})

//   "storage"
window.addEventListener('storage', event => {
    //     "messages"
    //  
    if (event.key == 'messages') return
    //      null
    //     
    //     
    event.newValue == null ? clearButton.click() : box.insertAdjacentHTML('afterbegin', event.newValue)
})

//  
saveButton.addEventListener('click', () => {
    //  
    let messages = []
    //  
    document.querySelectorAll('p').forEach(p => messages.push(p.outerHTML))
    //    
    localStorage.messages = messages
})

//    
clearButton.addEventListener('click', () => {
    localStorage.clear()
    document.querySelectorAll('p').forEach(p => box.removeChild(p))
    input.focus()
})

تبدو النتيجة كما يلي:



الرسالة المرسلة مكتوبة إلى localStorage.message. يتيح لك حدث "التخزين" تنظيم تبادل الرسائل بين علامات تبويب المتصفح.



عند حفظ محادثة ، تتم كتابة جميع الرسائل في localStorage.messages. عندما يتم إعادة تحميل الصفحة ، يتم تشكيل المراسلات من الرسائل المسجلة.

Codepen

Github

تخطيط سلة التسوق


نحن لا نهدف إلى إنشاء سلة تعمل بكامل طاقتها ، لذلك ستتم كتابة الرمز "على الطراز القديم".

يبدو تخطيط منتج واحد كما يلي:

<div class="item">
    <h3 class="title">Item1</h3>
    <img src="http://placeimg.com/150/200/tech" alt="#">
    <p>Price: <span class="price">1000</span></p>
    <button class="add" data-id="1">Buy</button>
</div>

لدينا حاوية للبضائع ، واسم وصورة وسعر البضاعة ، بالإضافة إلى زر لإضافة البضائع إلى السلة.

لدينا أيضًا حاوية للأزرار لعرض محتويات السلة وإفراغ السلة والتخزين وحاوية للسلة.

<div class="buttons">
    <button id="open">Cart</button>
    <button id="clear">Clear</button>
</div>
<div id="content"></div>

جافا سكريبت:

//    
let itemBox = document.querySelectorAll('.item'),
    cart = document.getElementById('content');

//    localStorage
function getCartData() {
    return JSON.parse(localStorage.getItem('cart'));
}

//    
function setCartData(o) {
    localStorage.setItem('cart', JSON.stringify(o));
}

//    
function addToCart() {
    //       
    this.disabled = true;
    //        ,   
    let cartData = getCartData() || {},
        //    "Buy"
        parentBox = this.parentNode,
        // id 
        itemId = this.getAttribute('data-id'),
        //  
        itemTitle = parentBox.querySelector('.title').innerHTML,
        //  
        itemPrice = parentBox.querySelector('.price').innerHTML;
    // +1  
    if (cartData.hasOwnProperty(itemId)) {
        cartData[itemId][2] += 1;
    } else {
        // + 
        cartData[itemId] = [itemTitle, itemPrice, 1];
    }
    //    localStorage
    if (!setCartData(cartData)) {
        //   
        this.disabled = false;
    }
}

//    ""    "Buy"
for (let i = 0; i < itemBox.length; i++) {
    itemBox[i].querySelector('.add').addEventListener('click', addToCart)
}

//  
function openCart() {
    //    
    let cartData = getCartData(),
        totalItems = '',
        totalGoods = 0,
        totalPrice = 0;
    //    
    if (cartData !== null) {
        totalItems = '<table><tr><th>Name</th><th>Price</th><th>Amount</th></tr>';
        for (let items in cartData) {
            totalItems += '<tr>';
            for (let i = 0; i < cartData[items].length; i++) {
                totalItems += '<td>' + cartData[items][i] + '</td>';
            }
            totalItems += '</tr>';
            totalGoods += cartData[items][2];
            totalPrice += cartData[items][1] * cartData[items][2];
        }
        totalItems += '</table>';
        cart.innerHTML = totalItems;
        cart.append(document.createElement('p').innerHTML = 'Goods: ' + totalGoods + '. Price: ' + totalPrice);
    } else {
        //    
        cart.innerHTML = 'empty';
    }
}
//  
document.getElementById('open').addEventListener('click', openCart);

//  
document.getElementById('clear').addEventListener('click', () => {
    localStorage.removeItem('cart');
    cart.innerHTML = 'leared';
});

تبدو النتيجة كالتالي:



يتم تسجيل المنتجات المحددة في المتجر كزوج من مفتاح / قيمة واحدة.



عند النقر فوق الزر Cart ، يتم عرض البيانات من localStorage في جدول ، ويتم حساب إجمالي عدد السلع وقيمتها.

Codepen

Github

شكرا لكم على اهتمامكم.

All Articles