Fe-7 js-todo

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
}

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,902评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,037评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,978评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,867评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,763评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,104评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,565评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,236评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,379评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,313评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,363评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,034评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,637评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,719评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,952评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,371评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,948评论 2 341

推荐阅读更多精彩内容

  • 第2章 基本语法 2.1 概述 基本句法和变量 语句 JavaScript程序的执行单位为行(line),也就是一...
    悟名先生阅读 4,102评论 0 13
  • 原文: https://github.com/ecomfe/spec/blob/master/javascript...
    zock阅读 3,370评论 2 36
  • 第5章 引用类型(返回首页) 本章内容 使用对象 创建并操作数组 理解基本的JavaScript类型 使用基本类型...
    大学一百阅读 3,204评论 0 4
  • 母亲,是一个词语,一个千百年来被人们歌颂的词语; 母亲,是一种大爱,一种舍我忘我,只为儿女的付出之情; 母亲,是一...
    读娘阅读 1,652评论 2 2
  • 一大早沈碧云就被叫到慈宁宫来,她被引入一喧曲折的迷阵似的栏杆,她弯来弯去走了许久才走出这个迷阵。前面是几十个大花坛...
    褚褚一阅读 509评论 2 4