webAPI
- 作用:使用JS去操作html和浏览器
- 分类:DOM,BOM
DOM树
作用:文档树直观的体现了标签与标签之间的关系
获取dom对象
<div>123</div>
<div>456</div>
<script>
let num=document.querySelector("div")
console.log(num)
console.dir(num)
</script>
- 获取方式:**document.querySelector(**选择器)
- 只能获取第一个满足条件的标签
- 找不到则返回null
- 想要输出dom元素,用console.dir,不再使用console.log
querySelectorAll
- 获取所有同名标签
- 能找到则返回dom元素
- 找不到则返回null
- 结果无论如何都是返回数组
设置文本内容方式(动态设置)
document.write()
- 只能在body标签中写,极少使用
innerText
- 只能设置文本,不能解析html字符串
innerHTML
- 可以设置文本,也可以解析html字符串
属性
刷新随机显示图片案例
<body>
<img src="" width="100%" alt="">
<script>
let image=document.querySelector('img')
let i=Math.round(Math.random()*8+2)
console.log(i)
image.src=`./wallpaper/${i}.jpg`
</script>
</body>
设置修改元素样式属性
-
修改样式通过style属性引出
-
属性有连接符-,需要转换为小驼峰命名法
-
赋值的时候,不要忘记加css单位
-
<body> <div>修改样式属性</div> <script> let div=document.querySelector('div') div.style.fontSize="50px" div.style.color="pink" div.style.backgroundColor="#000" </script> </body> -
这种方法只能修改行内式,麻烦
-
-
刷新页面随机颜色
-
let bd=document.querySelector('body') function getRandom(min,max){ return Math.round(Math.random()*max-min+min) } let c1=getRandom(0,255) let c2=getRandom(0,255) let c3=getRandom(0,255) bd.style.backgroundColor=`rgb(${c1},${c2},${c3})`
-
通过类名修改样式
- className:先清空原有的dom元素类名,再单独添加新类名
- 如果需要同时添加多个class,以空格分割
<style>
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}
.box{
width: 200px;
height: 200px;
background-color: red;
}
.radius{
border-radius: 50%;
background-color: yellow;
}
</style>
<body>
<div></div>
<script>
let div=document.querySelector("div")
div.className="box radius"
</script>
</body>
操作类
- 元素.classList.add('类名')——追加一个类
- 元素.classList.remove('类名')——删除一个类
- 元素.classList.toggle('类名')——切换一个类
- 操作多个类——('类名', '类名')
定时器
-
开启定时器
-
开启之后会返回一个定时器ID
-
同时开启多个定时器,关闭只会关闭最后一个定时器
-
此时要用到节流:开启一个定时器,不允许开启另外一个定时器
-
开启时按钮禁用,关闭时按钮启用
-
<body> <button class="start">开始点名</button> <button class="stop">停止点名</button> <h3></h3> <script> let start=document.querySelector(".start") let stop=document.querySelector(".stop") let h3=document.querySelector("h3") let arr=['沙煲粉','酸菜鱼','海底捞','麦当劳','吃草','烧烤','奶茶','果茶','饮茶'] let i let nameId start.addEventListener('click',function (){ start.disabled=true nameId=setInterval(function (){ i=Math.round(Math.random()*(arr.length-1)) console.log(i) h3.innerText=arr[i] },50) }) stop.addEventListener('click',function (){ clearInterval(nameId) start.disabled=false }) </script> </body> -
节流:先停止定时器
-
<body> <button class="start">开始点名</button> <button class="stop">停止点名</button> <h3></h3> <script> let start=document.querySelector(".start") let stop=document.querySelector(".stop") let h3=document.querySelector("h3") let arr=['沙煲粉','酸菜鱼','海底捞','麦当劳','吃草','烧烤','奶茶','果茶','饮茶'] let i let nameId start.addEventListener('click',function (){ if(nameId){ clearInterval(nameId) } nameId=setInterval(function (){ i=Math.round(Math.random()*(arr.length-1)) console.log(i) h3.innerText=arr[i] },50) }) stop.addEventListener('click',function (){ clearInterval(nameId) }) </script> </body> -
<script> function log() { console.log('你被强化了,快上') } //一秒钟调用一次log函数 setInterval(log,1000) </script>
-
-
关闭清除定时器
-
通过定时器ID
-
let i=0 let timeId=setInterval(function (){ i++ console.log('你好啊') if(i===30) clearInterval(timeId) },500)
-
设置表单属性
- 输入框内容——*.value=''
- 复选框选定状态——*.checked=true/false
- 按钮禁用状态——*.disabled=true/false
- 下拉框默认选中——*.selected=true
- 文本域
- 获取内容
- 原样获取内容——.value
- 获取html转义——.innerHTML
- js设置内容
- .value
- .innerText
- .innerHTML
- 获取内容
事件
-
单机一个按钮等就是事件
-
事件监听
- 程序检测事件产生,触发事件立即调用函数响应,也称为注册事件
-
语法
-
//获取元素 let btn=document.querySelector('button') //事件监听 btn.addEventListener('click',function(){ alert('被点击了') })
-
-
事件监听三要素
- 事件源:被触发的dom元素
- 事件:用什么方式出发,比如单击,鼠标经过等
- 事件调用的函数:要做什么
-
事件区别
- addEventListener——对一个事件类型,绑定多个处理函数(常用)
- on+事件——对一个事件类型,只能绑定一个处理函数
事件类型
- click——点击
- mouseenter——鼠标经过
- mouseover——鼠标经过
- mouseleave——鼠标离开
- mouseout——鼠标离开
- focus——获得焦点
- blur——失去焦点
- Keydown——键盘按下触发
- Keyup——键盘抬起触发
- input——用户输入事件
环境对象
环境对象指的是函数内部特殊的变量this,代表着当前函数运行时所处的环境
重点:弄清楚this的指向
- 函数的调用方式不同,this指代的对象也不同
- 粗略规则:谁调用,this就是谁
排他思想
实际开发经常运用的技巧
- 先让其他元素恢复原样
- 再把样式添加到需要的元素身上
<body>
<ul>
<li>NO.1</li>
<li>NO.2</li>
<li>NO.3</li>
<li>NO.4</li>
<li>NO.5</li>
<li>NO.6</li>
<li>NO.7</li>
<li>NO.8</li>
</ul>
<script>
let lis=document.querySelectorAll("li")
for (let index = 0; index < lis.length; index++) {
lis[index].addEventListener('click',function (){
for (let index = 0; index < lis.length; index++) {
lis[index].style.backgroundColor="#fff"
}
this.style.backgroundColor="pink"
})
}
</script>
</body>
DOM节点
DOM树当中每一个内容都称为一个节点
- 元素节点
- 属性节点
- 文本节点
查找节点
- *.parentNode
- 获取父元素
- *.children(重点)
- 获取所有子元素
- 返回的还是一个伪数组
- *.childNodes(了解)
- *.nextElementSibling
- *.previousElementSibling
增加节点
-
先创建一个内存当中的元素
-
// 创建一个li标签节点 let newLi=document.createElement('li') // 为新节点添加样式文字 newLi.innerText='你们好,我是新来的猪肉' newLi.style.backgroundColor='yellow'
-
-
再把元素插入页面当中
-
// 新节点插入到页面 let ul=document.querySelector('ul') ul.appendChild(newLi)
-
-
*.append(a,b,c,d)——可以插入多个元素节点
-
document.createTextNode("text")——创建文本节点
-
父元素.insertBefore(将要插入的节点,在谁之前)
-
功能类似appendChild
-
如果要插入元素已经存在,作用就是剪切粘贴
-
如果要插入元素是新创建,作用就是仅仅插入
-
即便父元素是空数组,也可以插入目标元素——*.insertBefore(待插入元素, null)
-
<body> <ul class="left"> <li>1</li> <li>2</li> <li>3</li> <li>4</li> </ul> <ul class="right"> <li>a</li> <li>b</li> <li>c</li> <li>d</li> </ul> <script> let three=document.querySelector(".left li:nth-child(3)") let b=document.querySelector(".right li:nth-child(2)") let right=document.querySelector(".right") right.insertBefore(three,b) </script> </body>
-
克隆节点
// 克隆一个已有的元素节点
元素.cloneNode(布尔值)
- cloneNode会克隆一个已有元素
- 括号内为true,代表连后代节点一起克隆——深拷贝
- 括号内为false,代表不克隆后代节点,只克隆本身——浅拷贝
- 默认值false
删除节点
-
// 元素自删 元素.remove() -
// 删除子节点 父元素.removeChild(要删除的元素) -
不存在父子关系则不成功
-
删除与隐藏节点的区别
- 隐藏节点:还存在节点
- 删除节点:从html中删除节点
时间对象方法
时间对象返回的数据不能直接使用,要转换为实际开发常用格式
实例化时间对象
- 代码中有new关键字,一般称为实例化
- 创建一个事件对象并获取时间
// 实例化
let date = new Date()
时间戳
1970年01月01日00时00分00秒起至现在的毫秒数,是一种特殊的计量时间方式
获取时间戳
-
let date=new Date() console.log(date.getTime()) -
// 隐式转换,只有事件对象可以转换为时间戳 console.log(+new Date()) -
// 语义化,时间戳*随机数==获取不会重复的数字 console.log(Date.now())
事件
事件对象
对象里有事件触发时的相关信息
获取事件对象
- 在事件绑定的回调函数的第一个参数就是事件对象
- 一般命名为event,ev,e
常见属性
event.cilentX, event.cilentYevent.offsetX, event.coffsetYkey,不推荐用keycode
事件流
事件流指的是事件完整执行过程中的流动路径
- 元素触发事件时,会经历两个阶段
- 捕获阶段
- 从父亲到儿子
- 冒泡阶段(默认)
- 从儿子到父亲
- 捕获阶段
修改事件流阶段
- 事件绑定最后传入
true或者falsetrue捕获阶段false冒泡阶段(默认)往后开发阶段一般都是用默认冒泡阶段,不需要传入false
阻止冒泡
event.stopPropagation()
<style>
.a{
width: 500px;
height: 500px;
background-color: red;
}
.b{
width: 300px;
height: 300px;
background-color: yellow;
}
.c{
width: 100px;
height: 100px;
background-color: blueviolet;
}
p{
width: 500px;
height: 500px;
}
</style>
</head>
<body>
<p></p>
<div class="a">grandfather
<div class="b">father
<div class="c">son</div>
</div>
</div>
<script>
const a=document.querySelector('.a')
const b=document.querySelector('.b')
const c=document.querySelector('.c')
const p=document.querySelector('p')
a.addEventListener("click", function (){
console.log('a')
p.style.backgroundColor="red"
})
b.addEventListener("click", function (){
p.style.backgroundColor="yellow"
console.log('b')
})
c.addEventListener("click", function (e){
p.style.backgroundColor="blueviolet"
console.log('c')
e.stopPropagation()
})
</script>
</body>
事件委托
把业务委托给父元素
-
简单粗暴法
e.target获取触发的最底层元素-
<body> <ul> <li>1</li> <li>2</li> <li>3</li> <li>4</li> </ul> <script> const ul=document.querySelector("ul") ul.addEventListener("click", function (e){ e.target.style.backgroundColor="red" }) </s
-
阻止标签默认行为
-
a标签具有点击默认跳转功能- 通过
e.preventDefault()阻止
- 通过
-
form
表单中type='submit'`默认有点击刷新行为- 阻止方法
- 给标签注册事件添加
e.preventDefault() - 给
button按钮添加type="button"属性 - 给
input按钮添加type="button"属性 - 把按钮移出
form表单
- 给标签注册事件添加
- 阻止方法
-
网页默认右键菜单
-
<style> *{ margin: 0; padding: 0; box-sizing: border-box; } body{ height: 100vh; } .menu{ list-style: none; border: 1px solid #999; width: 120px; position: fixed; display: none; font-size: 14px; } li{ padding: 8px; } </style> </head> <body> <ul class="menu"> <li>添加桌面</li><hr> <li>壁纸动态</li><hr> <li>炫酷桌面</li><hr> <li>清理内存</li> </ul> <script> const menu=document.querySelector(".menu") document.body.addEventListener('contextmenu', function (e){ e.preventDefault() menu.style.display='block' menu.style.top=e.clientY+'px' menu.style.left=e.clientX+'px' }) document.body.addEventListener('click', function(){ menu.style.display='none' }) </script> </body>
-
scroll事件
document.documentElement是根标签
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h1>1</h1>
// 省略一万个h1标签
<script>
window.addEventListener("scroll", function (){
console.log(document.documentElement.scrollTop)
})
</script>
</body>
</html>
加载事件
-
加载外部资源完毕时触发的事件
-
避免外部资源没有加载完,js代码找不到dom元素
-
事件名:
load -
给
window添加load事件-
// 页面加载事件 window.addEventListener('load', function (){ // 执行的操作 })
-
-
DOMContentLoaded事件(早期js代码写在head里面时用的) -
标签加载完毕就触发了
scroll家族
dom.scrollWidth包含可滚动的内容宽度(PC端不包括滚动条17px)dom.scrollHeight包含可滚动的内容高度(PC端不包括滚动条17px)dom.scrollTop元素上滚动距离dom.scrollLeft元素左滚动距离- 注意
- PC端的滚动条大小是17px
- 移动端的滚动条不占大小
offset家族
dom.offsetWidth获取自身宽度(包括滚动条17px)dom.offsetHeight获取自身高度(包括滚动条17px)dom.offsetTop获取自身顶部到有定位父元素的距离dom.offsetLeft获取自身左边到有定位父元素的距离
client家族
dom.clientWidth获取自身可视宽度(不包括滚动条17px)dom.clientHeight获取自身可视高度(不包括滚动条17px)dom.clientTop获取自身上边框宽度dom.clientLeft获取自身左边框宽度- 没有右边框和下边框的获取代码
undefined
第三方插件-swiper7-轮播图
- 官方网址:www.swiper.com.cn/
- 使用步骤(具体查看官方文档)
延时器
延迟时间后执行
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}
.box{
width: 300px;
height: 300px;
background-color: yellow;
display: flex;
justify-content: center;
align-items: center;
font-size: 12px;
}
</style>
</head>
<body>
<div class="box">
男人,就要健身keep fit
</div>
<script>
setTimeout(function () {
document.querySelector(".box").style.display="none"
},2000)
</script>
</body>
</html>
BOM
location
location.href="http:/www.baidu.com"——实现跳转页面location.href=location.href——页面刷新location.reload(true)——强制刷新!location.search获取url ? 后面一串字符location.hashvue阶段,获取#后面一串字符
navigator
navigator数据类型是对象,存放着浏览器自身的信息
本地存储(面试)
- 数据存储在用户浏览器中
- 设置,读取方便、甚至页面刷新不丢失数据
- 容量较大,
sessionStorage和localStorage约5M左右
localStorage
-
存储数据——
localStorage.setItem(key, value) -
获取数据——
localStorage.getItem(key) -
删除一条数据——
localStorage.remove(key) -
清空所有数据——
localStorage.clear() -
特点
- 生命周期永久生效,除非手动删除,否则关闭页面也会存在
- 可以多窗口**共享(**同一浏览器)
- 存储形式为键值对
- 存入复杂数据类型,引用数据类型会发生数据丢失
-
改变颜色小案例
-
<body> <input type="color" name="" id=""> <script> document.body.style.backgroundColor=localStorage.getItem('userColor') const inputColor=document.querySelector("input") inputColor.addEventListener("change", function () { document.body.style.backgroundColor=this.value localStorage.setItem('userColor', this.value) }) </script> </body>
-
localStorage复杂数据
- 转换为字符串——
JSON.stringify(),然后存入本地存储 - 拿到本地存储,再转换为原类型——
JSON.parse()
sessionStorage
- 特点
- 生命周期为关闭浏览器窗口
- 同一窗口共享数据
- 其他基本和
localStorage一致
元素属性
固有属性
标签固有属性通过dom.xxx可以获取到,也可以dom.getAttribute(属性名)
自定义属性
- 设置自定义属性
dom.setAttribute(属性名, 属性值)- H5建议方式
data-xxx——<a data-index="1" href=""></a>
- 获取自定义属性
dom.getAttribute(属性名)dom.dataset.xxx
- 最强大
Attribute()
高阶函数
一个函数被当作形参使用时,就形成高阶函数
重绘和回流
- 浏览器界面渲染
- 解析HTML,生成DOM树
- 同时解析CSS,生成样式规则
- 根据上述结果生成渲染树
- 进行布局layout(回流/重排):根据渲染树,得到节点几何信息(位置、大小尺寸)
- 渲染树元素大小结构布局改变时,浏览器会重新渲染文档,称为回流(重排)
- 进行绘制Painting(重绘):根据计算和获取的信息进行整个页面的绘制
- 由于节点(元素)的样式的改变并不影响它在文档流中的位置和文档布局时,称为重绘
- Display:展示在页面
- 重绘不一定引起回流,回流一定会引起重绘
事件解绑
dom.removeEventListener(事件名, 函数名)
不可以解绑注册了匿名函数的事件
字符串方法
-
转大写
-
const str="abc?defg" console.log(str.toUpperCase())
-
-
转小写
-
const str="abc?defg" console.log(str.toLowerCase())
-
-
字符分割(返回数组)
-
const str="abc?defg" console.log(str.split('')) console.log(str.split('?'))
-
数组方法
- 数组合并
arr1.concat(arr2)
- 数组转字符串
arr1.join()
正则表达式
检测字符串中是否含有所需字符
const str = '有梦想,我小时候的梦想是长大了一定要娶一个跟电影明星一样漂亮的老婆,后来变了,变成我长大后一定要考上军校,当一个大将军,后来随着高考成绩的出现,又变了,变成了要下海经商,变成有钱人,结果发现不会骗人,太实诚,没有做生意的天赋,梦想又变了,变成一个科学家,研究人类生命的起源,让人人可以长生,永远可以陪伴自己最亲密的人,结果每天都被柴米油盐,衣食住行给牵累,什么也干不成,只能找一个养家糊口的工作,老老实实的上班下班!'
// 正则表达式是对象,不是字符串
const reg=/长大/
console.log(reg.test(str))
元字符
- 边界符
^开头$结尾
- 量词
*——出现0次或多次+——出现1次或多次?——出现0次或1次{n}——出现n次{n,}——出现n次或多次{n, m}——出现n次到m次
- 字符
\d——匹配0-9之间的任一数字\D——匹配所有0-9之外的字符\w——匹配任意的字母、数字和下划线,相当于[A-Za-z0-9]\W——匹配所有字母、数字和下划线以外的字符,相当于[^A-Za-z0-9]\s——匹配空格(包括换行符、制表符、空格符等),相当于[\t\r\n\v\f]\S——匹配所有空格之外的字符,相当于[^\t\r\n\v\f]
[]- 中括号表示范围
[0-9] [a-z] [A-Z] [0-9a-zA-Z] [a-d]
微博发布案例
-
原始人做法(操作节点)
-
<!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>Document</title> <link rel="stylesheet" href="css/weibo.css" /> </head> <body> <div class="w"> <div class="controls"> <img src="images/tip.png" alt="" /><br /> <textarea placeholder="说点什么吧..." id="area" cols="30" rows="100" maxlength="200" ></textarea> <div> <span class="useCount">0</span> <span>/</span> <span>200</span> <button id="send">发布</button> </div> </div> <div class="contentList"> <ul> <!-- <li> <div class="info"> <img class="userpic" src="./images/9.5/06.jpg" /> <span class="username">张良</span> <p class="send-time">发布于 2022-4-7 15:12:23</p> </div> <div class="content">sdfdf</div> <span class="the_del">X</span> </li> --> </ul> </div> </div> <script> // 用户数组 let dataArr = [ { uname: '司马懿', imgSrc: './images/9.5/01.jpg' }, { uname: '女娲', imgSrc: './images/9.5/02.jpg' }, { uname: '百里守约', imgSrc: './images/9.5/03.jpg' }, { uname: '亚瑟', imgSrc: './images/9.5/04.jpg' }, { uname: '虞姬', imgSrc: './images/9.5/05.jpg' }, { uname: '张良', imgSrc: './images/9.5/06.jpg' }, { uname: '安其拉', imgSrc: './images/9.5/07.jpg' }, { uname: '李白', imgSrc: './images/9.5/08.jpg' }, { uname: '阿珂', imgSrc: './images/9.5/09.jpg' }, { uname: '墨子', imgSrc: './images/9.5/10.jpg' }, { uname: '鲁班', imgSrc: './images/9.5/11.jpg' }, { uname: '嬴政', imgSrc: './images/9.5/12.jpg' }, { uname: '孙膑', imgSrc: './images/9.5/13.jpg' }, { uname: '周瑜', imgSrc: './images/9.5/14.jpg' }, { uname: '老夫子', imgSrc: './images/9.5/15.jpg' }, { uname: '狄仁杰', imgSrc: './images/9.5/16.jpg' }, { uname: '扁鹊', imgSrc: './images/9.5/17.jpg' }, { uname: '马可波罗', imgSrc: './images/9.5/18.jpg' }, { uname: '露娜', imgSrc: './images/9.5/19.jpg' }, { uname: '孙悟空', imgSrc: './images/9.5/20.jpg' }, { uname: '黄忠', imgSrc: './images/9.5/21.jpg' }, { uname: '百里玄策', imgSrc: './images/9.5/22.jpg' }, ]; // 获取文本框 let text=document.querySelector("textarea") let useCount=document.querySelector(".useCount") // 获取发布按钮 let send=document.querySelector("#send") // 获取ul元素 let ul=document.querySelector("ul") // 文本框事件 text.addEventListener('input', function (){ useCount.innerText=text.value.length }) // let sum=0 // let timeId=setInterval(createLi,50) // 发布事件 send.addEventListener('click',function (){ // 判断是否有内容 if (text.value=='') { alert('内容为空不可发布') return false } createLi() useCount.innerText=0 text.value='' }) // 封装li创建节点函数 function createLi() { // 获取随机数 let getRan=Math.round(Math.random()*(dataArr.length-1)) // 重新获取lis数组 let lis=document.querySelectorAll("li") // 创建li标签 let li=document.createElement('li') // 头像,用户名,发布时间的盒子 let info=document.createElement('div') info.classList.add('info') // 头像 let img=document.createElement('img') img.classList.add('userpic') img.src=dataArr[getRan].imgSrc // 创建用户名 let username=document.createElement('span') username.classList.add('username') username.innerText=dataArr[getRan].uname // 发布时间标签 let send_time=document.createElement('p') send_time.classList.add('send-time') // 存放时间的变量 let nowTime=getTime() send_time.innerText=`发布于 ${nowTime}` // 发布内容 let content=document.createElement('div') content.classList.add('content') content.innerText=text.value // 删除按钮 let the_del=document.createElement('span') the_del.classList.add('the_del') the_del.innerText='×' // 合并所有节点 info.append(img,username,send_time) li.append(info,content,the_del) ul.insertBefore(li,lis[0]) // 同时注册关闭功能 the_del.addEventListener('click',function (){ this.parentNode.remove() }) } // 获取时间 function getTime() { // 获取时间所有代码封装 let date=new Date() let year=date.getFullYear() let month=date.getMonth()+1 let day=date.getDate() let hour=date.getHours() let min=date.getMinutes() let sec=date.getSeconds() return `${year}-${month}-${day} ${hour}:${min}:${sec}` } </script> </body> </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>Document</title> <link rel="stylesheet" href="css/weibo.css" /> </head> <body> <div class="w"> <div class="controls"> <img src="images/tip.png" alt="" /><br /> <textarea placeholder="说点什么吧..." id="area" cols="30" rows="100" maxlength="200" ></textarea> <div> <span class="useCount">0</span> <span>/</span> <span>200</span> <button id="send">发布</button> </div> </div> <div class="contentList"> <ul> <!-- <li> <div class="info"> <img class="userpic" src="./images/9.5/06.jpg" /> <span class="username">张良</span> <p class="send-time">发布于 2022-4-7 15:12:23</p> </div> <div class="content">sdfdf</div> <span class="the_del">X</span> </li> --> </ul> </div> </div> <script> // 用户数组 let dataArr = [ { uname: '司马懿', imgSrc: './images/9.5/01.jpg' }, { uname: '女娲', imgSrc: './images/9.5/02.jpg' }, { uname: '百里守约', imgSrc: './images/9.5/03.jpg' }, { uname: '亚瑟', imgSrc: './images/9.5/04.jpg' }, { uname: '虞姬', imgSrc: './images/9.5/05.jpg' }, { uname: '张良', imgSrc: './images/9.5/06.jpg' }, { uname: '安其拉', imgSrc: './images/9.5/07.jpg' }, { uname: '李白', imgSrc: './images/9.5/08.jpg' }, { uname: '阿珂', imgSrc: './images/9.5/09.jpg' }, { uname: '墨子', imgSrc: './images/9.5/10.jpg' }, { uname: '鲁班', imgSrc: './images/9.5/11.jpg' }, { uname: '嬴政', imgSrc: './images/9.5/12.jpg' }, { uname: '孙膑', imgSrc: './images/9.5/13.jpg' }, { uname: '周瑜', imgSrc: './images/9.5/14.jpg' }, { uname: '老夫子', imgSrc: './images/9.5/15.jpg' }, { uname: '狄仁杰', imgSrc: './images/9.5/16.jpg' }, { uname: '扁鹊', imgSrc: './images/9.5/17.jpg' }, { uname: '马可波罗', imgSrc: './images/9.5/18.jpg' }, { uname: '露娜', imgSrc: './images/9.5/19.jpg' }, { uname: '孙悟空', imgSrc: './images/9.5/20.jpg' }, { uname: '黄忠', imgSrc: './images/9.5/21.jpg' }, { uname: '百里玄策', imgSrc: './images/9.5/22.jpg' }, ]; // 获取文本框 let text=document.querySelector("textarea") let useCount=document.querySelector(".useCount") // 获取发布按钮 let send=document.querySelector("#send") // 获取ul元素 let ul=document.querySelector("ul") // 文本框事件 text.addEventListener('input', function (){ useCount.innerText=text.value.length }) // 发布事件 send.addEventListener('click',function (){ // 判断是否有内容 if (text.value=='') { alert('内容为空不可发布') return false } let user=getUser() let liHtml=` <li> <div class="info"> <img class="userpic" src=${user.imgSrc} /> <span class="username">${user.uname}</span> <p class="send-time">发布于 ${getTime()}</p> </div> <div class="content">${text.value}</div> <span class="the_del">×</span> </li> ` ul.innerHTML+=liHtml useCount.innerText=0 text.value='' }) // 封装获取随机用户对象函数 function getUser() { let index=Math.round(Math.random()*(dataArr.length-1)) return dataArr[index] } // 获取时间 function getTime() { // 获取时间所有代码封装 let date=new Date() let year=date.getFullYear() let month=date.getMonth()+1 let day=date.getDate() let hour=date.getHours() let min=date.getMinutes() let sec=date.getSeconds() return `${year}-${month}-${day} ${hour}:${min}:${sec}` } </script> </body> </html>