js学习笔记七(多行字符串,转义符,高阶函数,匿名函数,todo,JSON,localStorage)

·  阅读 155

-可以用 typeof 语句得到一个变量的类型:

a = 10

b = true

c = 'I am good'

log('type a', typeof a)

log('type b', typeof b)

log('type c', typeof c)

运行, 输出如下:

type a number

type b boolean

type c string

-多行字符串:多行字符串又称模板字符串,使用反引号, 键盘左上角波浪线

var a = `多
行
字符串`

log('多行字符串', a)

a = `
i
am
good
`
复制代码

-转义符:在代码中表示字符串的时候,很多东西不方便表示,因此我们使用转义符的方式来表示,转义符是字符串中的特殊符号,由反斜杠(backslash)开始,接另一个字符结束,常用的转义符有:

// \n     // 表示一个换行符
// \t     // 表示一个 TAB(制表符)
// \\     // 表示一个反斜杠 \
// \'     // 表示一个单引号
// \"     // 表示一个双引号
//
// 例子:
log('I\'a\tm \n\ngood\n')
输出:
I'a	m

good
复制代码

-高阶函数:函数可以作为参数传递

作用:灵活性高,舒适度佳

-匿名函数:没有函数名, 一般定义了就用

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>上课用品 7-2</title>
        <style>
            /* 完成的样式 */
            .done {
                color: gray;
                text-decoration: line-through;
                background: lightblue;
            }
        </style>
    </head>
    <body>
        <div class="todo-form">
            <input id='id-input-todo' type="text">
            <button id='id-button-add' type="button">Add</button>
        </div>
        <div id="id-div-container">
            <div class='todo-cell'>

            </div>
        </div>
        <script src=todo.js></script>
    </body>
</html>

复制代码
var e = function(selector) {
    return document.querySelector(selector)
}

// 给 add button 绑定添加 todo 事件
var addButton = e('#id-button-add')
addButton.addEventListener('click', function(){
    // 获得 input.value
    var todoInput = e('#id-input-todo')
    var todo = todoInput.value
    // 添加到 container 中
    insertTodo(todo, false)
    // 添加之后 保存 todos
    saveTodos()
})

var insertTodo = function(todo, done) {
    // 添加到 container 中
    var todoContainer = e('#id-div-container')
    var t = templateTodo(todo, done)
    // 这个方法用来添加元素
    // 第一个参数 'beforeend' 意思是放在最后
    todoContainer.insertAdjacentHTML('beforeend', t);
}

var templateTodo = function(todo, done) {
    var status = ''
    if(done) {
        status = 'done'
    }
    var t = `
        <div class='todo-cell ${status}'>
            <button class='todo-done'>完成</button>
            <button class='todo-delete'>删除</button>
            <span class='todo-content' contenteditable='true'>${todo}</span>
        </div>
    `
    return t
}

// 事件委托相关概念
// 问题在于, todo 都是运行的时候才添加的元素
// 对于这样的元素, 我们没办法实现绑定事件
// 我们可以把 click 事件绑定在事先存在的父元素上
// 然后在运行的时候检查被点击的对象(通过 event.target 属性)
// 是否是我们需要的对象, 这个概念就是事件委托

var todoContainer = e('#id-div-container')

// 通过 event.target 的 class 来检查点击的是什么
todoContainer.addEventListener('click', function(event){
    log('container click', event, event.target)
    var target = event.target
    // classList.contains 可以检查元素是否有一个 class
    if(target.classList.contains('todo-done')) {
        log('done')
        // target.parentElement 用来获取按钮的父节点
        // 给 todo div 开关一个状态 class
        var todoDiv = target.parentElement
        toggleClass(todoDiv, 'done')
        // 改变 todo 完成状态之后,保存 todos
        saveTodos()
    } else if (target.classList.contains('todo-delete')) {
        log('delete')
        // 找到按钮的父节点并且删除
        var todoDiv = target.parentElement
        todoDiv.remove()
        // 删除之后 保存 todos
        saveTodos()
    }
})

// 这个函数用来开关一个元素的某个 class
var toggleClass = function(element, className) {
    // 检查元素是否拥有某个 classs
    if (element.classList.contains(className)) {
        // 拥有则删除之
        element.classList.remove(className)
    } else {
        // 没有则加上
        element.classList.add(className)
    }
}
// localStorage(本地存储) 是浏览器自带的功能
// localStorage 可以用来存储字符串数据, 在浏览器关闭后依然存在
// 但是不同页面拥有各自独立的 localStorage
// 存储方法如下
localStorage.name = 'gua'
// 关闭浏览器, 再次打开, 仍然能获取到这个值
// log('关闭浏览器后', localStorage.name)
//
// 利用 localStorage 就可以存储 todo
// 但是 todo 存在 array 中
// 而 localStorage 只能存储 string 数据
// 所以没办法直接存储
//
// 可行的办法如下
// 存储的时候把 array 转换为字符串
// 读取的时候把字符串转成 array
// 这个过程通常被称之为 序列化 和 反序列化
// 在 js 中, 序列化使用 JSON 数据格式
// 全称 JavaScript Object Notation (js对象标记)
// 这个格式已经是现在用于互联网数据交换的事实标准格式了

var s = JSON.stringify([1, 2, 3, 4])
log('序列化后的字符串', typeof s, s)
var a = JSON.parse(s)
log('反序列化后的数组', typeof a, a)

// 使用 JSON 序列化后, 就可以把 todo 存入浏览器的 localStorage 了

// 定义一个函数, 用于把 数组 写入 localStorage
var save = function(array) {
    var s = JSON.stringify(array)
    localStorage.todos = s
}

// 定义一个函数, 读取 localStorage 中的数据并解析返回
var load = function() {
    var s = localStorage.todos
    return JSON.parse(s)
}

// 定义一个函数, 把页面上所有的 todo 用 save 保存
var saveTodos = function() {
    // 1 先选出所有的 content 标签
    // 2 取出 todo
    // 3 添加到一个 数组中
    // 4 保存数组
    log('save todos')
    var contents = document.querySelectorAll('.todo-content')
    var todos = []
    for (var i = 0; i < contents.length; i++) {
        var c = contents[i]
        var done = c.parentElement.classList.contains('done')
        var todo = {
            done: done,
            content: c.innerHTML,
        }
        // 添加到数组中
        todos.push(todo)
    }
    // 保存数组
    save(todos)
}

var loadTodos = function() {
    var todos = load()
    log('load todos', todos)
    // 添加到页面中
    for (var i = 0; i < todos.length; i++) {
        var todo = todos[i]
        insertTodo(todo.content, todo.done)
    }
}

loadTodos()

// 时间标准库
// 常用用法如下
// var d = new Date()
// d.getFullYear()
// 年份, 2016
// d.getMonth()
// 月份, 0-11
// d.getDate()
// 日期, 1-31
// d.getHours()
// 小时, 0-23
// d.getMinutes()
// 分钟, 0-59
// d.getSeconds()
// 秒数, 0-59
// d.getMilliseconds()
// 毫秒, 0-999
// d.getDay()
// 星期几, 0-6

var now = function() {
    var d = new Date()
    var nm = d.getFullYear()
    var yt = d.getMonth() + 1
    var ri = d.getDate()
    var ui = d.getHours()
    var ff = d.getMinutes()
    var mc = d.getSeconds()

    return `${nm}/${yt}/${ri} ${ui}:${ff}:${mc}`
    // return nm + '/' + yt + '/' + ri + ' ' + ui + ':' + ff + ':' + mc
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>learntodo</title>
    <style>
        .inputValue {
            background: aqua;
            text-decoration-line: line-through;
            color: grey;
        }
    </style>
</head>
<body>
<input id='id-input' type="text">
<button id="id-add">add</button>
<div id="id-contain">

</div>
<script>
    let e = function (self) {
        return document.querySelector(self)
    }
    let container = e('#id-contain')
    let todoValue = function(value) {
        let t = `
        <div id="id-div">
        <button id='id-complete'>完成</button>
        <button id="id-delete">删除</button>
        <span id="id-value">${value}</span>
        </div>`
        container.insertAdjacentHTML('beforeend', t)
    }

    let load = function() {
        if (localStorage.arr == null) {
            return
        }
        let arr = JSON.parse(localStorage.arr)
        for (let i = 0; i < arr.length; i++) {
            let o = arr[i]
            todoValue(o.content)
        }
    }

    load()

    let add = e('#id-add')
    add.addEventListener('click', function () {
        let input = e('#id-input')
        let value = input.value
        if (repeat(value)) {
            alert('请勿重复添加')
        } else {
            todoValue(input.value)
        }
        save()
    })

    let save = function() {
        let container = e('#id-contain')
        let children = container.children
        let arr = []
        for(let i = 0; i < children.length; i++) {
            let item = children[i]
            let span = item.children[2]
            let o = {
                content: span.innerHTML,
                complete: span.classList.contains("inputValue")
            }
            arr.push(o)
        }
        localStorage.arr = JSON.stringify(arr)
    }

    let repeat = function(value) {
        let span = document.querySelectorAll('#id-value')
        for (let i = 0; i < span.length; i++) {
            let spanValue = span[i].innerHTML
            if (spanValue === value) {
                return true
            }
        }
        return false
    }

    container.addEventListener('click', function (event) {
        let target = event.target
        let target_id = target.getAttribute('id')
        let parent = target.parentElement
        if (target_id === 'id-complete') {
            toggle(parent)
        } else if (target_id === 'id-delete') {
            parent.remove()
        }
    })
    let toggle = function (target) {
        let children = target.children
        let span = children[2]
        let button = children[0]
        if(span.classList.contains('inputValue')) {
            span.classList.remove('inputValue')
            button.innerHTML = '完成'
        } else {
            span.classList.add('inputValue')
            button.innerHTML = '取消'
        }
    }


</script>
</body>
</html>
复制代码
分类:
阅读
标签: