Skip to content

1. BOM

1.1 JS的组成

  1. JS由几部分组成
  2. ECMAScript => JS的基础语法
  3. Web APIs => BOM + DOM
  4. BOM是什么?浏览器对象模型,定义了一套操作浏览器窗口的API
  5. window对象是什么?平时可以省略吗?
  • 是浏览器中的顶级对象,不能说是JS的顶级对象 => Node.js中顶级对象是 global
  • window对象下的属性和方法调用的时候可以省略window
javascript
// BOM browser object model 浏览器对象模型
// 把浏览器当做一个对象 
// window对象是浏览器的顶级对象,通常可以省略

// 1. 在全局作用域中, 用var声明的变量,会成为window的属性
var anum = 666
console.log(anum)
console.log(window.anum)
console.log(window)

const abc = 888
let acb = 999
console.log(window)

// 2. 全局作用域中,function 声明的函数,会成为window对象的方法
function afn(){
  console.log('建国说,你没睡醒吧')
}
afn()

const acb = function(){
  console.log(123)
}

console.log(window)

// 3. alert()  promt()  setInterval() 都是window对象的方法,可以省略window

1.2 定时器 setTimeout

javascript
// setTimeout()
// 语法:setTimeout(回调函数, 等待时间)
// setTimeout(fn, wait)

1. window可以省略,window.setTimeout()
2. wait 单位 ms 这个参数可以省略   ==> 4ms
3. cb可以写匿名函数,可以写函数名,`函数名()挨打`
4. 页面中可以有多个定时器,通常需要关闭的时候给定时器一个标记timerId 
5. setTimeout 只执行一次

// 书写方式
// 1. 直接写匿名函数
setTimeout(function(){
  console.log('桃桃说,建国说的对')
}, 1000)

// 2. 写函数名
const fn = function(){
  console.log('建国说,桃桃是谁')
}
function cb(){
  console.log('海霖说,他们都说的对')
}
setTimeout(fn, 2000)
setTimeout(cb, 3000)


// 3. 关掉定时器  clearTimeout(timerId)
let timerId = setTimeout(cb, 5000)
console.log(timerId)
clearTimeout(timerId)

eg.5s关闭广告

javascript
// 5秒钟之后自动关闭广告
const closeBtn = document.querySelector('.close')
closeBtn.addEventListener('click', function(){
  this.parentNode.style.display = 'none'
})

// 2. 定义个setTimeout
setTimeout(function(){
  closeBtn.click()
}, 5000)

1.3 location对象

javascript
// location 对象  
// location是一个对象,了解3个属性,一个方法。
// ==> 重点掌握  location.href


// 1. location.href 得到完整的url地址,还可以赋值跳转
console.log(location.href)
// location.href = 'http://www.baidu.com'

// 2. search 获取的是"?xxxx"
console.log(location.search)

// 3. hash 获取的是 "#xxxx"
console.log(location.hash)

// 4. reload() 方法,刷新页面
const btn = document.querySelector('.reload')
btn.addEventListener('click', function(){

  // 刷新页面 F5  /  Ctrl + R / cmd + R 
  // location.reload()
  // 强制刷新 Ctrl + shift + R  / cmd + shift + R 
  // 可以传true,表示强制刷新
  location.reload(true)
})

eg.5s跳转链接

javascript
// 1. 获取元素
const span = document.querySelector('span')

// 2. 开启定时器 setInterval(fn, wait)
let num = 5 
let timerId = setInterval(function(){
  num--
  span.innerHTML = num

  if(num === 0) {
    clearInterval(timerId)
    // 跳转到新的页面
    location.href = 'http://www.jd.com'
  }
}, 1000)

//  ==> 可以把回调函数挪出去
// 1. 获取元素
const span = document.querySelector('span')
// 2. 开启定时器 setInterval(fn, wait)
let num = 5 

const cb = function(){
  num--
  span.innerHTML = num
  if(num === 0) {
    clearInterval(timerId)
    // 跳转到新的页面
    location.href = 'http://www.jd.com'
  }
}

let timerId = setInterval(cb, 1000)

1.4 navigator对象

navigator.userAgent => 判断浏览器信息,设备信息等

javascript
  // 检测 userAgent(浏览器信息)
  (function () {
    const userAgent = navigator.userAgent
    // 验证是否为Android或iPhone
    const android = userAgent.match(/(Android);?[\s\/]+([\d.]+)?/)
    const iphone = userAgent.match(/(iPhone\sOS)\s([\d_]+)/)
    // 如果是Android或iPhone,则跳转至移动站点
    if (android || iphone) {
      location.href = 'http://m.itcast.cn'
    }
  })()

1.5 history对象

javascript

const back = document.querySelector('.back')
const forward = back.nextElementSibling
console.log(back, forward)

// 打开这一页,复制url地址,然后去到百度,将复制的地址放到url上
back.addEventListener('click', function(){
  // 后退一步
  console.log('我执行了吧')
  // history.back()
  history.go(-1)
})


// 在当前页url上,输入百度的地址,点击回退
forward.addEventListener('click', function(){
  // history.forward()
  history.go(1)
})

2. 本地存储

2.1 存储大小 ==> 5M

javascript
;(function() {
  var test = '0123456789';
  var add = function(num) {
      num += num;
      if(num.length == 10240) {;
          test = num;
          return;
      }
      add(num);
  }
  add(test);
  var sum = test;
  var show = setInterval(function(){
      sum += test;
      try {
         // localStorage
          window.localStorage.removeItem('test');
          window.localStorage.setItem('test', sum);
          console.log(sum.length / 1024 + 'KB');
      } catch(e) {
          alert(sum.length / 1024 + 'KB超出最大限制');
          clearInterval(show);
      }
  }, 0.1)
})()

2.1 localStorage

DANGER

localStorage 本地存储

  1. 生命周期: 生命周期永久生效(数据一直存在), 除非手动删除,否则刷新或者关闭页面,数据也在
  2. 数据共享: localStorage数据可以多窗口共享(同一个浏览器,同一个域名下)
javascript
生命周期:一个对象的创建到清除的过程,数据存在的周期

localStorage 本地存储
1. 生命周期: 生命周期永久生效(数据一直存在), 除非手动删除,否则刷新或者关闭页面,数据也在
2. 数据共享: localStorage数据可以多窗口共享(同一个浏览器,同一个域名下)

= 数据以键值对的形式存储, key / value , 存储的是字符串形式的数据!

// 1. 存数据  localStorage.setItem(key, value)
localStorage.setItem('user_name', '建国说不要cue我了')

// 2. 取数据 localStorage.getItem(key)
const res = localStorage.getItem('user_name')
console.log(res)
// 3. 删除数据 localStorage.removeItem(key)
localStorage.removeItem('user_name')

// 4. 清空数据 localStorage.clear()

存储复杂数据类型

复杂数据类型不能直接存储的,localStorage 只能存储字符串形式的数据

DANGER

JSON.stringify() : 将对象转换为JSON格式的字符串 JSON.parse() : 将JSON格式的字符串转为对象形式

javascript
const goods = {
  name: '小米',
  price: 1999
}

// 复杂数据类型不能直接存储的,localStorage 只能存储字符串形式的数据
localStorage.setItem('test_obj', goods)
console.log(localStorage.getItem('test_obj'))


// JSON格式:
// 属性和值,key和value都有引号,且统一是双引号,不可以是单引号
// 如果 value的值是 number 或者 null 等 可以不带双引号

// JSON.stringify() : 将对象转换为JSON格式的字符串 
const res = JSON.stringify(goods)
console.log(res)
console.log(typeof res)

localStorage.setItem('test_obj', res)

// JSON.parse() :  将JSON格式的字符串转为对象形式
const result = JSON.parse(localStorage.getItem('goods'))
console.log(result) 
console.log(result.name)
console.log(result.price)

2.2 sessionStorage

javascript
会话存储 了解

1. 生命周期: 关闭浏览器,数据清除
2. 数据共享: 在同一个窗口(页面)下数据可以共享

方法和localStorage一模一样
存数据  sessionStorage.setItem(key, value)
取数据  sessionStorage.getItem(key)
删数据  sessionStorage.removeItem(key)
清空数据  sessionStorage.clear()

// 面试题: 
// localStorage 和 sessionStorage的区别?  ==> 记下来
1. 生命周期
2. 数据共享

3. 方法学习

3.1 arr.map()

javascript
// arr.map()    map映射
// 1. 作用: map方法创建一个新数组
//          这个新数组由原数组每个元素都调用一次提供的函数后的返回值组成。
// (从数组第一个元素开始遍历的调用回调函数, 每次都返回一个值,最后组成一个新的数组)

// 2. 参数:  arr.map(cbFn) 接收一个函数cbFn
// cbFn的第一个参数  正在处理的当前的元素  item , el 变量自己命名, 最好语义化
// cbFn的第二个参数  正在处理的元素的索引号  index , i 

// 3. 返回值: 由原数组每个元素都调用回调函数的结果组成的新数组。
//    返回的数组是正经数组吗  --- 李小强 
//    是的, 很正经

// 4. 注意: map() 中传入的函数, 一般都需要写return

const arr = [10, 20, 30]
// 我想要得到一个新数组,这个新数组由原数组的每个元素 + 6 得到 
const resArr = arr.map(function(el){
  return el + 6 
})
console.log(resArr)

// map方法返回的是一个新数组, 注意,回调函数中一定要记得写return

const arr2 = ['red', 'green', 'skyblue']

const resArr3 = arr2.map(function(el, i){
  return el + '哈哈哈' + i
})
console.log(resArr3)

3.2 arr.join()

将数组转为字符串 => 用分隔符连接 常用 arr.join('')

javascript
// arr.join(分割符)
// 作用: 把数组的所有元素连接成一个字符串, 并返回这个字符串。
// ===> 把数组转换为字符串
// 参数:可以传一个分割符, 也可以省略

const arr = ['red', 'green', 'yellow']

// 1. 如果参数省略, 默认使用逗号分隔
console.log(arr.join())

// 2. 传空的字符串, 直接将数组中的元素无间隙的连接在一起  ==> 重点记住
console.log(arr.join(''))

// 3. 传一个其他字符串分隔符 分隔符可以自己定义
console.log(arr.join('💩'))

4. 综合案例

4.1 学生就业统计表

todo01 渲染业务,录入数据

javascript
// 1. 渲染业务
// 1.1 先读取本地存储的数据
// (1). 本地存储有数据则记得转换为对象然后存储到变量里面,后期用于渲染页面
const arr = JSON.parse(localStorage.getItem('stu-data')) || []
console.log(arr)
// (2). 如果没有数据,则用 空数组来代替

todo02 利用map+join渲染表格

javascript
// 2. 利用map+join方法渲染数据
const tbody = document.querySelector('tbody')
const render = function(){
 const trArr = arr.map(function(el){
    return `
        <tr>
        <td>${el.stuId}</td>
        <td>${el.uname}</td>
        <td>${el.age}</td>
        <td>${el.gender}</td>
        <td>${el.salary}</td>
        <td>${el.city}</td>
        <td>${el.time}</td>
        <td>
          <a href="javascript:">
            <i class="iconfont icon-shanchu"></i>
            删除
          </a>
        </td>
      </tr>
    `
  })
  // 数组可以放到tbody中吗?
  // 将生成的带有tr结构的数组,转为字符串,最后放到tbody中
  tbody.innerHTML = trArr.join('')
  // 显示剩余多少条数据
  document.querySelector('.title span').innerHTML = arr.length
}
render()

todo03 form表单提交事件,阻止默认行为

javascript
// 3. 给form表单注册提交事件submit,但是要阻止默认行为
const form = document.querySelector('.info')
const username = document.querySelector('.uname')
const age = document.querySelector('.age')
const salary = document.querySelector('.salary')
form.addEventListener('submit', function(e){
    e.preventDefault() // 阻止提交表单的时候默认提交跳转的行为

    // 3.1 非空判断
    if (username.value === '' || age.value === '' || salary.value === ''){
        return alert('输入的内容不能为空')
    }
    console.log('123')
    // 当username.value等于空字符串的时候,!username.value ==> true 
    // if (!username.value || !age.value || !salary.value){
    //     return alert('输入的内容不能为空')
    // }
    // age.value === ''   ===> !age.value
})

todo04 新增业务,完整

javascript
// 3. 给form表单注册提交事件submit,但是要阻止默认行为
const form = document.querySelector('.info')
const username = document.querySelector('.uname')
const age = document.querySelector('.age')
const salary = document.querySelector('.salary')

const gender = document.querySelector('.gender')
const city = document.querySelector('.city')
console.log(gender.value)
form.addEventListener('submit', function(e){
    e.preventDefault() // 阻止提交表单的时候默认提交跳转的行为
    // 3.1 非空判断
    if (username.value === '' || age.value === '' || salary.value === ''){
        return alert('输入的内容不能为空')
    }
    // 3.2 给arr追加新的数据,
    arr.push({
        stuId: arr.length + 1,
        uname: username.value,
        age: age.value,
        salary: salary.value,
        gender: gender.value,
        city: city.value,
        time: new Date().toLocaleString()
    })
    // 3.3 再调用一个render函数
    render()
    // 3.4 form表单重置,清空内容
    this.reset()
    // 3.5 每次添加完,我们要把数据存到本地存储
    localStorage.setItem('stu-data', JSON.stringify(arr))
})

todo05 删除功能的实现

javascript
// 4. 删除功能的实现
// 4.1 遍历数据的时候,给每个a添加自定义属性
// 4.2 给tbody绑定点击事件,事件委托
tbody.addEventListener('click', function(e){
    if (e.target.tagName === 'A') {
        // 删除之前,再次确认一下 confirm
        const res = confirm('你真的要删除我吗?')
        if (res) {
            // 4.3 从数组中删除元素
            arr.splice(e.target.dataset.id, 1)
            // 4.4 重新渲染数据
            render()
            // 4.5 把最新的arr存到本地
            localStorage.setItem('stu-data', JSON.stringify(arr))
        }
    } // end if 
})

todo06 stuId的处理

javascript
// 取数组中最后一位元素的id,加1. 
// stuId: arr.length + 1,
// ==> // arr[arr.length - 1].stuId + 1
// 如果原数组没有长度,长度为0。
// if (arr.length === 0)  stuId  ==> 1 
// else {
//     arr[arr.length - 1].stuId + 1
// }
stuId: arr.length ? arr[arr.length - 1].stuId + 1 : 1,