Javascript高阶运用|青训营笔记

108 阅读5分钟

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%
          
        }
    }  
    }      
 `
  • 实现效果:

    k29yl-6sgo6.gif

四、参考文献::

五、心得体会:

今天的学习过后,我尝试了书写高级函数,月影老师有由浅入深的讲法让我认识到了怎样的js代码才算优雅的代码。js代码不仅仅要做到入门还要做到精湛。必须通过项目经验来优化代码,从中总结收获。我发现自己还是很有差距,只是懂得皮毛是不够的,希望努力弄通js。