美文网首页
Fe-7 js-todo

Fe-7 js-todo

作者: 吕阳 | 来源:发表于2018-01-06 17:18 被阅读49次

    Fe-7-1

    数据类型

    在 js 中, 每一个变量(也就是每一个值)都有一个类型

    • 内置的基本数据有以下几种类型
      number 数字
      string 字符串
      boolean 布尔变量(只有两个值 true 或 false)
      object 对象, 是高级一点的内容
      null 和 undefined

    这两个东西很相似, 有这么两个东西主要是历史原因造成的
    具体细节可看这个链接, 不过不需要关心
    http://www.ruanyifeng.com/blog/2014/03/undefined-vs-null.html

    函数也是一个变量, 稍微特殊点, 但在 js 中没什么本质不同
    它的类型是函数

    // 为一个变量赋值就创建了一个变量
    // JavaScript 中, 变量只是对值的一个引用
    // 比如下面, 分别把 3 个不同类型的值赋值给变量 a

    var a
    a = 1       // a 是 number
    a = 1.1     // number
    a = 'good'  // string
    
    // 可以用 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

    前提定义log函数

    // 定义 log 函数
    var log = function() {
        console.log.apply(console, arguments)
    }
    
    
    微信截图_20180106125231.png
    • 单行字符串变多行字符串用转意符号
    • 多行字符串
      多行字符串又称模板字符串
      使用反引号, 键盘左上角波浪线
    var a = `多
    行
    字符串`
    
    log('多行字符串', a)
    
    a = `
    i
    am
    good
    `
    
    log('多行字符串 2', a)
    

    不同的数据类型是不能混用的
    比如 float 就不能当下标

    • 转义符
      在代码中表示字符串的时候, 很多东西不方便表示, 因此我们使用转义符的方式来表示
      转义符是字符串中的特殊符号,由反斜杠(backslash)开始
      接另一个字符结束
      常用的转义符有
      还有一些别的转义符,但极少使用,对于这种东西,不必记忆,知道有这么回事就好了。
    // \n     // 表示一个换行符
    // \t     // 表示一个 TAB(制表符)
    // \\     // 表示一个反斜杠 \
    // \'     // 表示一个单引号
    // \"     // 表示一个双引号
    //
    // 例子:
    log('I\'a\tm \n\ngood\n')
    
    
    微信截图_20180106165038.png

    高阶函数 就是函数当参数传递

    // =====
    // 高阶函数
    // =====
    //
    // 高阶函数这个名字很唬人, 实际上概念很简单——函数可以作为参数传递
    //
    // 有什么用呢?灵活性高,舒适度佳
    // 请看例子
    //
    // String 函数是用来把数据转换成 string 类型的一个函数
    log('string ', String(6.3))
    
    var process = function(array, processor) {
        /*
        array 是一个数组
        processor 是一个函数, 注意, 这是一个函数, 所以可以调用
    
        把 array 中的每个元素都用 processor 函数处理并返回一个
        新的 array
        */
        var l = []
        for (var i = 0; i < array.length; i++) {
            var a = array[i]
            // processor 必须能调用成功, 否则这里就跪了
            var element = processor(a)
            l.push(element)
        }
        return l
    }
    
    // 创建一个 array, 包含 3 个 number
    var array = [1.1, -2.2, 3.3]
    
    // String 内置函数
    var stringList = process(array, String)
    log('stringList', stringList)
    
    // Math.floor 函数可以把小数转成整数, 可以自行试试
    process(array, Math.floor)
    
    // 输出结果如下
    // 我们可以看到, process 函数通过 参数传进来的函数 对数据进行了处理
    // stringList ['1.1', '-2.2', '3.3']
    
    
    // =====
    // 匿名函数
    // =====
    //
    // 有时候要传递高阶函数的时候, 函数很短, 可能就一行
    // 如果去定义一个新函数有人觉得划不来, 就想了一个偷懒的办法
    // 那就是匿名函数
    // 匿名函数的意思是没有函数名, 一般定义了就用
    // 实际上我们之前写的函数都是匿名函数, 只不过把它赋值给了一个变量而已
    
    // 例子
    // 定义一个 square 函数求平方
    var square = function(n) {
        return n * n
    }
    
    // 用上面的 process 函数处理试试
    var array = [1, 2, 3]
    var squareList = process(array, square)
    log('square list', squareList)
    
    var addList = process(array, function(n){
        // 我们定义一个接受一个参数的函数并且直接使用, 它没有名字
        return n + 1
    })
    log('add list', addList)
    
    
    // 输出结果如下
    // square list [1, 4, 9]
    // add list [2, 3, 4]
    
    微信截图_20180106130947.png

    Fe-7-2 Todo

    • 添加,删除,完成,还有本地存储


      todo.gif

    todo.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <title>Todo</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" name="button">Add</button>
    </div>
    <div id="id-div-container">
      <div class="todo-cell">
                  <!-- <button class='todo-done'>完成</button>
                  <button class='todo-delete'>删除</button>
                  <span class='todo-content' contenteditable='true'>上课</span>
                
                 -->
    
      </div>
    </div>
    <script src="todo.js" charset="utf-8"></script>
    </body>
    </html>
    
    

    todo.js

    // 2016/12/06
    //
    // 此为第 7 课的上课内容 2
    //
    // 这部分的主要内容有
    //
    // 通过一个 Todo 应用, 学习下面这个概念
    // 1, 什么是事件委托
    // 2, 为什么需要事件委托
    // 3, 如何实现事件委托
    //
    // 时间操作
    // content editable (标签的可编辑属性)
    // localStorage (本地存储) 和 JSON 数据格式
    //
    //
    // 应该都能看懂, 不懂的稍微做个笔记, 等上课讲解
    
    
    // 自己定义一个 log 函数
    var log = function() {
        console.log.apply(console, arguments)
    }
    
    // 用自己实现的 e 替代 document.querySelector
    // 因为这个东西太长了
    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对象标记)
    // 这个格式已经是现在用于互联网数据交换的事实标准格式了
    // ISO 是国际标准
    // IEEE 国际电子电气工程师协会
    // GB 中国国标
    
    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
    }
    
    

    相关文章

      网友评论

          本文标题:Fe-7 js-todo

          本文链接:https://www.haomeiwen.com/subject/nahynxtx.html