手写模板——前端总结

获取近一年时间

const dateFormat = 'YYYY-MM-DD';
const dateRange = {
    "6month": [moment().subtract(6, 'months'), moment()], //近6个月
    "1year": [moment().subtract(1, 'years'), moment()], // 近1年
    "3year": [moment().subtract(3, 'years'), moment()], // 近3年
    "5year": [moment().subtract(5, 'years'), moment()], // 近5年
    "start": [moment(prod_start_time, dateFormat), moment()] // 从某一特定时间至今
  } 

js获取最后一位

1.length-1
2.arr.slice(-1)[0]
3.arr.at(-1) ES2022兼容性不好
4. arr.concat().pop(); pop会改变原数组,所以要先复制一份副本

双波浪线

Math.floor() 方法:将数字向下舍入到最接近的整数,并返回结果。如果传递的参数是整数,则该值不会被舍入。
~~ 两个按位非操作符,作用是干掉数字的小数部分。和强制类型转换的结果基本一样

onfinish

antd 3 中的form表单提交时,有onSubmit事件,而antd 4中则换成了onFinish事件,并且当使用onfinish事件时,要注意不能同时给Button绑定onClick事件视图出发提交。因为会请求两次提交事件,并且第一次接收不到值会导致提交失败或异常。

<Form.Item className="login-item">
					<Button type="primary" htmlType="submit" className="login-form-button" style={{width: '100%'}}>登陆</Button>	
					<p style={{color: '#8f8f8f', fontSize: '12px', marginTop: '20px', textAlign: 'center'}}>用户名:admin,密码: admin</p>
				</Form.Item>

控制 表单数据域

antd 3中使用getFieldDecorator 结合 Form.create。

import { Form, Icon, Input, Button } from 'antd';

function hasErrors(fieldsError) {
  return Object.keys(fieldsError).some(field => fieldsError[field]);
}

class HorizontalLoginForm extends React.Component {
  componentDidMount() {
    // To disable submit button at the beginning.
    this.props.form.validateFields();
  }

  handleSubmit = e => {
    e.preventDefault();
    this.props.form.validateFields((err, values) => {
      if (!err) {
        console.log('Received values of form: ', values);
      }
    });
  };

  render() {
    const { getFieldDecorator, getFieldsError, getFieldError, isFieldTouched } = this.props.form;

    // Only show error after a field is touched.
    const usernameError = isFieldTouched('username') && getFieldError('username');
    const passwordError = isFieldTouched('password') && getFieldError('password');
    return (
      <Form layout="inline" onSubmit={this.handleSubmit}>
        <Form.Item validateStatus={usernameError ? 'error' : ''} help={usernameError || ''}>
          {getFieldDecorator('username', {
            rules: [{ required: true, message: 'Please input your username!' }],
          })(
            <Input
              prefix={<Icon type="user" style={{ color: 'rgba(0,0,0,.25)' }} />}
              placeholder="Username"
            />,
          )}
        </Form.Item>
        <Form.Item validateStatus={passwordError ? 'error' : ''} help={passwordError || ''}>
          {getFieldDecorator('password', {
            rules: [{ required: true, message: 'Please input your Password!' }],
          })(
            <Input
              prefix={<Icon type="lock" style={{ color: 'rgba(0,0,0,.25)' }} />}
              type="password"
              placeholder="Password"
            />,
          )}
        </Form.Item>
        <Form.Item>
          <Button type="primary" htmlType="submit" disabled={hasErrors(getFieldsError())}>
            Log in
          </Button>
        </Form.Item>
      </Form>
    );
  }
}

const WrappedHorizontalLoginForm = Form.create({ name: 'horizontal_login' })(HorizontalLoginForm);

ReactDOM.render(<WrappedHorizontalLoginForm />, mountNode);

我们推荐使用 Form.useForm 创建表单数据域进行控制。如果是在 class component 下,你也可以通过 ref 获取数据域。

这一点来看 antd 4 使用Form简单了很多。

全屏

使用react-full-screen,但要注意的是,useFullScreenHandle必须在函数组件中使用

import { FullScreen, useFullScreenHandle } from "react-full-screen";
const handle = useFullScreenHandle();
<FullScreen
			            handle={handle}
			            style={{ background: "#ffffff" }}
			          >
					...
					{!this.props.fullScreen ? <FullscreenOutlined onClick={() => 					this.fullScreenHandle(true)} /> :
					 <FullscreenExitOutlined onClick={() => this.fullScreenHandle(false)}/>}
				</FullScreen>
fullScreenHandle = (tag) => {
	tag ? handle.enter() : handle.exit();
}

这里为了使用redux而使用redux,其实获取全屏状态可以直接从handle中获取handle.active 就是状态。

antd 4 动态渲染Icon

从4.0开始,antd 不在内置 Icon 组件,需要使用独立的 @ant-design/icons 包

import * as Icon from '@ant-design/icons';
const icon = React.createElement(
        Icon[item.icon],
        {
          style:{ fontSize: '16px'}
        }
      )

react中使用img标签

因为太不经常引入图片在项目中,所以忘记了引入标签的方法。
在react中使用img标签,使用相对路径引入不成功。所以需要用import from 导入图片,这样的好处是即使你打包到线上也不会出现路径丢失找不到文件的问题。

antd 换肤

想要在系统内写一个换肤功能,有多种配色方式。
基本配置:替换APP.css 中@import ‘~antd/dist/antd.min.css’; 为@import ‘~antd/dist/antd.variable.min.css’
使用:const theme_obj = {starBlue: '#1890ff', cutePink: '#ff8bba'}; ConfigProvider.config({ theme: { primaryColor: theme_obj[item]}, });
这里我使用的不是antd4文档中推荐的方法,我给public中的index.html的root盒子一个类名,给不同的类型设置不同的primaryColor。这样切换的时候就可以换肤了,不过没有做缓存,觉得没有必要,如果有必要也可以把切换的皮肤做一个缓存。

react 鼠标事件

onMouseDown 按下
onMouseMove 拖动
onMouseUp 抬起

withRouter

withRouter的作用是将一个组件包裹进Route里面, 然后react-router的三个对象history, location, match就会被放进这个组件的props属性中。仅仅是将一个不是Router但是想要通过路由跳转的组件包裹起来,变为可以路由跳转的组件,其余的路由如何配置跟它无关。
路由配置是另一个组件,HashRouter或者BrowserRouer包裹起来的配置好的Route组件。
不要将两者过于冗杂在一起思考会影响判断,也就是说路由页面可以定义在任何一个部分任何一个结构里,要使用这个路由也就是要跳转到这个路由页面,那么源头就要给一个LInk组件裹着或者使用withRouter包裹。

国际标准时间

2022-05-16T16:00:00.000+0000

装饰器 @修饰符

装饰器 decorator 是一种函数,是 Es6 的一个语法糖,是一种与类(class)相关的语法,用来注释或修改类和方法

装饰器本质上是一个函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能。
可以抽象出某些页面共同的特点,使用装饰器创建公共的模版,其他被装饰的页面只要实现自己独特的部分就可以了。
类似父类,但又不是父类。
这里引入一个新的包装模式:装饰器模式,引入装饰器模式之后又要引入一个概念,高阶组件(即传入的参数是组件,返回一个新的组件,高阶组件是react应用中很重要的一部分,最大的特点就是重用组件逻辑。)

⒈ 装饰器对类的行为的改变时代码编译时发生的,而不是在运行时,这意味着,装饰器能在编译阶段运行代码,它本身就是编译时执行的函数

⒉ 装饰器只能用于类和类的方法,不能用于函数,因为它存在函数提升

轮询

普通轮询:
原理:每隔一段时间发一次请求来获取最新数据。setTimeout或者setTimeInterval发送ajax请求,DOM操作更新页面数据
缺陷:不稳定而且对服务器造成的压力比较大,耗费资源。而且实时性不高,可能你看到的跟别人看到的数据不一致。
优点:后端接口正常写就好,不需要做特殊对待。前端用定时器就好,而且即使换页面也可以一直请求,可以做到全局弹窗弹出消息的效果。

长轮询:
原理:浏览器发出请求。服务器资源如果没有就绪,不立即返回,而是在一个时间范围内,不断的去查询资源是否就绪,如果就绪返回资源,如果超时了还没有就绪就返回超时。
后端实现方式见后端总结
前端实现方式:

function test() {
        axios.request({
            url: "/test_apis",
            method: "POST"
        }).then(function (res) {
            //如果返回数据
            if (res.data != "") {
                // 拿到数据
                ......
            }
            // 立即再发起一个请求,等着获取最新数据
            get_votes()
        })
    }

长连接
websocket 是H5的一个新协议(格式: ‘ws://xxxx’),和HTTP是同层级的协议,让客户端与服务端建立长连接。

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>测试长连接</title>
</head>
<body>
    <button onclick="test_send()">点击测试</button>
    <button onclick="test_close()">点击关闭</button>
    <script>
        // Create WebSocket connection.
        const socket = new WebSocket('ws://121.40.165.18:8800'); //连接
        // 发送函数
        function test_send() {
            // Connection opened
            socket.send('Hello Server!');
        }
        //关闭函数
        function test_close() {
            socket.onclose = function () {
                // 关闭 websocket
                alert("连接已关闭...");
            };
            socket.onclose();
        }
        //连接成功时
        socket.addEventListener('open', function (event) {
            socket.send('Hello Server!');
        });
        // 服务器推送过来的消息
        socket.addEventListener('message', function (event) {
            console.log('Message from server ', event.data);
        });
         
        var readyState = socket.readyState; //状态
        console.log(readyState)
    </script>
</body>
</html>

git使用

git stash 非常好用,但是一个不注意代码就没了,很可怕。
这里要注意的是git stash 之后 切出去分支,再切回来,然后没有第一时间使用恢复stash 而是选择git pull ,覆盖代码,这样再git stash list 就看不到上次提交的记录了。
这时使用git stash pop就可以了。但是要注意的是这种场景下的git stash pop好像只能恢复文件中更改的代码,新增的文件不会缓存,git stash pop之后新增的文件就没有了。巨坑!!!!

html使用import

路由懒加载

使用@loadable/component
也可以 import {Suspense,lazy} from ‘react’
Suspense,配合 lazy使用

基于react写一个滚动事件(滚动懒加载和滚动到顶部表头固定)

 listenDomClick = () => {
        const {head_fixed} = this.state;
        if (this.state.active_tab != '3') {
            scrollTop = 0;
            document.getElementById('win-main').removeEventListener('scroll', this.listenDomClick); //移除滚动事件监听
        } else {
            document.getElementById('win-main').addEventListener('scroll', this.listenDomClick); //添加滚动事件监听
            // 监听表头
            if (!document.getElementById('table-head')) return false;
            if ((!head_fixed) && (document.getElementById('table-head').offsetTop < document.getElementById('win-main').scrollTop || 
            document.getElementById('table-head').offsetTop == document.getElementById('win-main').scrollTop)) {
                // 如果表头滚动到头了
                this.setState({head_fixed: true})
            } else if (head_fixed && document.getElementById('table-head').offsetTop > document.getElementById('win-main').scrollTop) {
                this.setState({head_fixed: false})
            }
            let clientHeight = document.documentElement.clientHeight || document.body.clientHeight; //窗口高度
            let scrollHeight = document.getElementById('win-main').scrollHeight; //滚动条的总高度
            if (scrollTop - document.getElementById('win-main').scrollTop > 0) return; // 向上滚动,不做判断
            scrollTop = document.getElementById('win-main').scrollTop; //滚动区域到头部的距离
            if ((Math.ceil(clientHeight) + Math.ceil(scrollTop) + 100 > scrollHeight || Math.ceil(clientHeight) + Math.ceil(scrollTop) + 100 == scrollHeight) && flag) {
                flag = false;
                timer = setTimeout(async () => {
                    let res = await this.IncomeAnalysisService.getList({reqPageNum: this.state.pageNum + 1, number: 10});
                    this.setState({dataSource: [...this.state.dataSource, ...res.data.list], pageNum: this.state.pageNum + 1});
                    clearInterval(timer);
                    flag = true; //规定时间到达后,将开关设置为true
                }, 300)
            }
        }
    }

About Babel

Babel是一个工具集,主要用于将ES6版本的JS代码转为ES5等向后兼容的JS代码,从而可以运行在低版本浏览器或其它环境中。
作用:语法转换,补齐API(提供垫片:polyfill,垫平差异)

向已有react 项目中引入ts

网上大多数都是从头开始创建一个使用ts的react 项目,这对已经成型的项目来说并不友好。
步骤:
(1) 命令行安装ts

npm install --save typescript @types/node @types/react @types/react-dom @types/jest

(2) 创建tsconfig.json配置文件,并进行配置(我的项目配置,可以针对自己代码习惯做配置)

{
    "compilerOptions":{
        "noImplicitAny": false, // 不需要显示地声明变量的类型any
        "target": "es5", // 定义了编译后的js目标版本,可选项ES5,ES6/ES2015,ES2016,ES2017,ES2018,ES2019,ES2020,ESNext
        "lib": [ // 列出了所有编译期间需要包含进来的库文件,通过这些库文件我们能够告诉ts编译器哪些功能能够使用
           "dom", // document.getElementById("root")
           "dom.iterable",
           "esnext"
        ],
        "allowJs": true,// 允许混合编译JavaScript文件
        "skipLibCheck": true,
        "esModuleInterop": true, // 允许我们使用commonjs的方式import默认文件, import React from 'react';
        //  "esModuleInterop": false, // import * as React from 'react';

        "allowSyntheticDefaultImports": true,
        "strict": true,
        "forceConsistentCasingInFileNames": true,
        "noFallthroughCasesInSwitch": true,
        "module": "esnext", // 配置的是代码的模块系统,Node.js的CommonJS、ES6标准的esnext、requireJS的AMD
        "moduleResolution": "node",  // 决定了编译器的工作方式,
        "resolveJsonModule": true,// "resolveJsonModule"如果为false,那么将无法识别.json后缀名文件.而且它必须和"moduleResolution"::"node"连用
        "isolatedModules": true, // 编译器会将每个文件作为单独的模块来使用
        "noEmit": true, // 表示当发生错误的时候,编译器不要生成JavaScript代码
        "jsx": "react-jsx" // 允许编译器支持编译react代码,
    }
}

(3) 将app.js index.js 改为tsx格式。这里可能会遇到报错

  1. Could not find a required file.
    Name: index.js

找不到index.js文件,是因为你把后缀改成了tsx格式。
【解决方式】
在package.json下添加 : “main”: “src/index.tsx” 告诉他找的是Index.tsx文件而不是Index.js文件

  1. An import path cannot end with a ‘.ts’ extension.
    引入app.tsx时报错,【解决方式】引入时直接引入src/app即可,将后缀名去掉。
  2. index.tsx 中报错 Argument of type ‘HTMLElement | null‘ is not assignable to parameter of type ‘HTMLElement‘.
    这就是ts的语法问题了,但如果你对ts还不了解,想要启动项目,那就做以下处理:
    【解决】使用类型断言(Type Assertion)
    const elem : HTMLElement = document.getElementById(‘root’) as HTMLElement;
    以上都配置完之后你的react项目就可以在使用js的基础上使用ts了。

启动任务时端口号占用了怎么办

我这里没有 用react的脚手架,所以是node 启动

 "start": "set PORT=9002 && node scripts/start.js",

axios使用delete 的点

如果使用axios的delete方法调用接口成功但是没有删除数据,那十分有可能是因为axios 的delete的传参与post 的传参不同,一定要注意啊~~~~~呜呜呜呜
不同点:
如果服务端将参数当做 对象

var param={name:'jack',age:20}
axios
          .delete("/test", {data: param})
          .then(function(response) {
            }

如果服务端将参数当做url 参数 接收

l例如:http:www.XXX.com?a=…&b=…

var param={name:'jack',age:20}
axios
          .delete("/test", {params: param})
          .then(function(response) {
            }

less 与calc

less中常规使用calc函数不生效,less的运算方式和calc起了冲突,写法改为(这里注意空格也要加)

calc(~“100% - 250px”)

### 前端开发学习路线图 #### 学习目标概述 前端开发的学习路径通常分为几个阶段,从基础技能到高级框架的应用。以下是基于已有资料和行业标准整理的一套完整的前端学习路线[^1]。 --- #### **阶段一:基础知识** 此阶段的目标是掌握前端开发的核心技术——HTML、CSS 和 JavaScript。 - **HTML (HyperText Markup Language)** HTML 是构建网页结构的基础语言。需要熟悉语义化标签以及常见的布局方式。 - **CSS (Cascading Style Sheets)** CSS 负责页面样式设计。重点学习盒模型、Flexbox、Grid Layout 等现代布局方法,以及响应式设计理念。 - **JavaScript** JavaScript 是实现交互功能的关键工具。初学者应熟练掌握 ES6+ 的语法特性,如箭头函数、模板字符串、解构赋值等。 ```javascript // 示例代码:ES6 特性演示 const user = { name: 'Alice', age: 25 }; const { name, age } = user; // 解构赋值 console.log(`${name} is ${age} years old.`); // 模板字符串 ``` --- #### **阶段二:进阶技能** 在掌握了基础技能后,可以进一步深入学习以下内容: - **DOM 操作与事件处理** 学习如何通过原生 JavaScript 对 DOM 进行动态操作,并绑定各种事件监听器。 - **浏览器兼容性和性能优化** 理解不同浏览器之间的差异及其解决方案;同时关注加载速度、渲染效率等问题。 - **版本控制系统 Git** 使用 Git 来管理项目源码变更历史记录是非常重要的实践环节之一[^2]。 --- #### **阶段三:框架/库应用** 当前主流的前端框架包括 React、Vue.js 和 Angular。建议根据个人兴趣选择其中一个作为主要方向进行深入研究。 - **React** Facebook 开发维护的一个用于构建用户界面的开源 JavaScript 库。它采用组件化的编程模式,使得复杂的 UI 可以被拆分成多个独立的小部件组合而成。 - **Vue.js** Vue 提供了一种简单易用的方式来创建动态 Web 页面。其双向数据绑定机制让开发者无需手动同步视图层的状态变化。 - **Angular** Google 推出的一款全栈型 MVVM 架构平台,适用于大型企业级应用程序开发场景下使用。 --- #### **阶段四:工程化能力提升** 随着项目的规模增大,单纯依赖手写的脚本文件已经无法满足需求了。因此还需要具备一定的软件工程技术素养。 - **模块打包工具Webpack/Rollup** 将零散分布于各个目录下的静态资源文件按需组装成最终产物交付给客户端运行时环境消费掉。 - **状态管理模式Redux/MobX/Vuex** 当单页应用越来越庞大复杂的时候就需要引入专门用来集中存储全局共享的数据容器类插件来帮助我们更好地组织逻辑流程控制流走向等等[^1]。 --- #### **阶段五:综合实战演练** 最后一步就是参与真实世界的工程项目积累实际工作经验啦!可以通过贡献开源社区或者参加Hackathon等活动形式快速提高自己的技术水平哦! --- ### 总结 以上便是从前端新手成长为资深工程师所需要经历的主要历程概览表。当然每个人的具体情况都不尽相同所以可以根据实际情况灵活调整进度安排计划表即可达成预期效果[^3]。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值