Javascript运用|青训营笔记
这是我参与「第四届青训营 」笔记创作活动的的第4天。 学习了今天的课程,对Javascript的理解更加深入了,先总结完向大家分享。
一、本节课重点内容:
今天的课由JS大佬月影老师主讲,课程分为上下部分,上半部分简单复习完js基础后,就直入主题,月影老师用优化代码的角度,将一般的代码和简介优秀的代码作对比,给人JS开发启发。 上半场的重点包括:JS元素DOM操作、组件封装、高阶函数、异步函数等。
二、课堂知识点纪要:
-
前端结构表现形式各司其职:
HTML控制结构、css负责表现、JS表示行为,以便代码维护修改。必要时才采用class来表示元素状态,尽量不用js操作样式。
//直接操作class演示 const button = document.getElementById('handle'); btn.addEventListener('click', (e) => { const body = document.body; if(body.className !== 'black') { body.className = 'black'; } else { body.className = 'white'; } }); -
将元素行为封装为抽象函数,可以用class类来封装,便于管理维护:
class slider{ constructor(props){ this.data = document.getElementById(id); } getSelect(){...} getItem(){...} sliderTo(){...} sliderNext(){...} } ### 行为:控制流 - 使用自定义事件来解耦。 -
JS组件封装的原则:
- 重构代码时应该将做解耦,将控制元素抽取成插件,注入依赖建立父子联系。
- 搭建组件之前应该抽象出组件的框架:
- 组件设计原则:封装性、正确性、扩展性、复用性
- 构建组件步骤:结构设计、展现效果、行为设计
- 组件重构步骤:插件化、模板化、抽象化
- 组件构建时应该考虑过程的抽象
-
高阶函数:
- 高阶函数指的是为了满足复杂逻辑需求构造等自调用、递归、闭包等函数。
function once(props) { return function(...args) { if(props) { const tmp = props.apply(this, args); props = null; return tmp; } } } - 注意函数编程范式:采用命令式还是声明式
- 常用高阶函数有:Once、Throttle(节流)、Debounce(防抖)、Consumer、ireratice
- 高阶函数指的是为了满足复杂逻辑需求构造等自调用、递归、闭包等函数。
-
JS代码不一定为了简便使用遍历,有时为了实现效果可以写死逻辑:
- JS代码思维不能限制死
- JS代码书写应该先考虑使用场景,其次有风格、效率、约定、使用场景等。
-
异步函数嵌套(以setTimeout为例):
- 过程抽象:交通灯代码优化可以队代码进行抽象,将红绿黄等封装为状态列表,定时取出下一项的state中的class样式即可
- 异步+函数:
function setState(state){ light.className = state; } async function start(){ //noprotect while(1){ setState('wait'); await wait(1000); setState('stop'); await wait(3000); setState('pass'); await wait(3000); } }
三、实践练习案例:
基于React和TS实现一个记事本的封装:
- TS函数封装代码:
//Authored by iiru
//powerby styled.js
import React from "react";
import { MainContain,Tarbar,Notice} from "./note";
import { Input} from "antd";
import { CheckOutlined, CloseOutlined } from "@ant-design/icons";
export function Notebook(){
class noteData {
notice:string
status:number
key:string
constructor(notice:string,
status:number,
key:string) {
this.notice = notice ;
this.status = status ;
this.key = key
}
} //database类
// const detele=(sort:number)=>{
// let temp = this.state.dataList.splice(sort,1)
// this.setState({dataList:temp})
// }
const Notices:any =(props:any)=>{
switch(props.status){
case 0: return (
<>
<Notice>
<div className={"notethen"} >
<span className={"check"}>
</span>
<span className={"notice"} onClick={props.onOver(props.sort)}>
{props.notice}
</span>
<CloseOutlined className={"delete"} onClick={props.onDel(props.sort)}>
</CloseOutlined>
</div>
</Notice>
</>
)
case 1: return (
<>
<Notice>
<div className={"notefirst"}>
<span className={"check"}>
</span>
<span className={"notice"} onClick={props.onOver(props.sort)}>
{props.notice}
</span>
<CloseOutlined className={"delete"} onClick={props.onDel(props.sort)}>
</CloseOutlined>
</div>
</Notice>
</>
)
case 2: return (
<>
<Notice>
<div className={"noteover"}>
<CheckOutlined className={"check"} >
</CheckOutlined>
{/*<span className={"notice"} onClick={props.onOver(props.sort)}>*/}
<span className={"notice"} >
{props.notice}
</span>
<CloseOutlined className={"delete"} onClick={props.onDel(props.sort)}>
</CloseOutlined>
</div>
</Notice>
</>
)
default:break;
}
} //笔记条样式 及逻辑
class Notes extends React.Component<any, {dataList:noteData[],temp:string}>{
constructor(props:any) {
super(props);
this.state = {
dataList:[
{notice: '今天去吃饭', status:0 ,key:"sub-0-1"}, //状态码0 未完成
{notice: '吃完吃雪糕', status:1 ,key:"sub-0-2"}, //状态码1 亟待完成
{notice: '吃完吃雪糕', status:2 ,key:"sub-0-3"}, //状态码2 已完成
],
temp:' '
}
}
handlerDel=(sort:any)=>{
return ()=>{
let tempList = this.state.dataList.slice(0, parseInt(sort)).concat(this.state.dataList.slice(parseInt(sort) + 1, this.state.dataList.length))
this.setState({dataList:tempList})
}
}
handleOver=(sort:any)=>{
let tempL = this.state.dataList;
if(this.state.dataList[sort].status === 0){
tempL[sort].status = 1;
console.log(tempL)
return ()=>{
this.setState({dataList:tempL})
}
}
else if(this.state.dataList[sort].status === 1){
tempL[sort].status = 2;
return ()=>{
this.setState({dataList:tempL})
}
}
else if(this.state.dataList[sort].status === 2){
tempL[sort].status = 0;
return ()=>{
this.setState({dataList:tempL})
}
}
}
inputRender=(e:any)=>{
this.setState({dataList:this.state.dataList,temp:e.target.value})
}
addNote=()=>{
if (this.state.temp === ' ') {
return
}
this.state.dataList.push( new noteData(this.state.temp,0,"sub-1-"+(this.state.dataList.length+1)))
this.setState({temp : ' '} )// 把input框清空;
}
render() {
return(
<>
<MainContain>
<div className={"tarbar"}>
<Tarbar>
<div className={"title"}>My To Do List</div>
<div className={"inputbox"}>
<Input className={"input"} type="text" placeholder={"记录一下"} value={this.state.temp} onChange={(e)=>this.inputRender(e)}/>
<button onClick={() =>{
this.addNote()
}} className={'submit'}>Add</button>
</div>
</Tarbar>
</div>
<div className={"content"}>
{this.state.dataList.map((item,noteid)=>{
return (
<Notices key={item.key}
notice={item.notice}
status={item.status}
sort={String(noteid)}
onDel={this.handlerDel}
onOver={this.handleOver}>
</Notices>
)
})}
</div>
</MainContain>
</>
)
}
}
return (
<>
<Notes></Notes>
</>
);
};
- 基于Style-Component的ts样式代码:
//Authored by iiru
//powerby styled.js
import { Input, Space } from 'antd';
import styled from "styled-components";
export const MainContain =styled.div`
width:600px;
height:780px;
background:#efefef;
.tarbar{
height:25%;
border-radius:24px 24px 0 0 ;
background:#ffc0cb;
}
.content{
height:70%;
border-radius:0 0 24px 24px;
background:#efefef;
}
`
export const Tarbar =styled.div`
.title{
padding:10% 35% 0 35%;
text-align:center;
font-size:28px;
font-weight:584;
color:#fff
}
.inputbox{
padding:2% 12% 0 12%;
width:100%
float:left;
.input{
width:80%;
height:54px;
border-radius:12px 0 0 12px
}
.submit{
width:20%;
height:54px;
border-radius:0 12px 12px 0;
border:none;
background:#e77689;
font-size:20px;
color:#8e5d60;
}
}
`
export const Notice =styled.div`
height:10%;
width:100%;
.noteover{
background:#e4c2c2;
color:#fff;
height:100%;
width:100%;
display:flex;
.check{
width:10%;
font-size:24px;
position: relative;
top: 25%
}
.notice{
font-size:18px;
text-decoration:line-through;
width:70%;
position: relative;
top: 25%
}
.delete{
font-size:24px;
width:20%;
position: relative;
top: 25%
}
}
}
.notefirst{
background:#eeeeee;
height:100%;
width:100%;
display:flex;
.check{
width:10%;
font-size:24px;
position: relative;
top: 25%
}
.notice{
font-size:18px;
width:70%;
position: relative;
top: 25%
}
.delete{
font-size:24px;
width:20%;
position: relative;
top: 25%
}
}
.notethen{
background:#f9f9f9;
height:100%;
width:100%;
display:flex;
.check{
width:10%;
font-size:24px;
position: relative;
top: 25%
}
.notice{
font-size:18px;
width:70%;
position: relative;
top: 25%
}
.delete{
font-size:24px;
width:20%;
position: relative;
top: 25%
}
}
}
`
-
实现效果:
四、参考文献::
- JS元旦倒计时:JavaScript倒计时牌_Han_Zhou_Z
- React记事本 我的记事本React实例
五、心得体会:
今天的学习过后,我尝试了书写高级函数,月影老师有由浅入深的讲法让我认识到了怎样的js代码才算优雅的代码。js代码不仅仅要做到入门还要做到精湛。必须通过项目经验来优化代码,从中总结收获。我发现自己还是很有差距,只是懂得皮毛是不够的,希望努力弄通js。