react学习笔记-8:登录页

创建登录页

在view下创建Login文件夹,新建index.tsx登录页

import { ChangeEvent, useEffect, useState } from "react";
import styles from "./login.module.scss"
import initLoginBg from "./init.ts";
import { Button,Input,Space } from 'antd';
import './login.less'

const view = ()=>{
    //加载完这个组件之后
    useEffect(()=>{
        initLoginBg();
        window.onresize = function(){initLoginBg};
    }
    )

    //获取用户名输入信息
    const [usernameVal,setUserNameVal] = useState("");  // 定义用户输入用户名信息这个变量
    const [passwdVal,setPasswdVal] = useState("");  // 定义用户输入密码信息这个变量
    const [captchaVal,setCaptchaVal] = useState("");  // 定义用户输入验证码信息这个变量
    const usernameChange = (e:ChangeEvent<HTMLInputElement>) => {
        //获取用户输入的用户名
        //console.log(e.target.value);
        //修改usernameVal变量为用户输入的用户名
        setUserNameVal(e.target.value);
    }
    const passwdChange = (e:ChangeEvent<HTMLInputElement>) => {
        //获取用户输入的密码
        //console.log(e.target.value);
        //修改usernameVal变量为用户输入的密码
        setPasswdVal(e.target.value);
    }
    const captchaChange = (e:ChangeEvent<HTMLInputElement>) => {
        //获取用户输入的验证码
        //console.log(e.target.value);
        //修改usernameVal变量为用户输入验证码
        setCaptchaVal(e.target.value);
    }
    //点击登录按钮事件
    const goToLogin = () => {
        console.log("用户输入的用户名,密码,验证码分别是:",usernameVal,passwdVal,captchaVal);   
    }

    return (
        <div className={styles.loginPage}>
            {/* 存放背景 */}
            <canvas id="canvas" style={{display:"block"}}></canvas>
            {/* 登录盒子 */}
            <div className={styles.loginBox+ " loginbox"}>
                {/* 标题部分 */}
                <div className={styles.title}>
                    <h1>通用后台</h1>
                    <p>Better Everday</p>
                </div>
                {/* 表单部分 */}
                <div className="form">
                <Space direction="vertical" size="large" style={{display:'flex'}} >
                    <Input placeholder="用户名" onChange={usernameChange}/>
                    <Input.Password placeholder="密码" onChange={passwdChange}/>
                    <div className="captchaBox">
                        <Input placeholder="验证码" onChange={captchaChange}/>
                        <div className="captchaImg">
                            <img height="38" src="data:image/png;base64,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" alt="" />
                        </div>
                    </div>
                    <Button className="loginBtn" type="primary" block onClick={goToLogin}>登录</Button>
                </Space>
                </div>
            </div>
        </div>
    )
}

export default view;

创建init.ts背景,星空效果背景页

export default function initLoginBg(){
  var windowWidth = document.documentElement.clientWidth || document.body.clientWidth;
  var windowHeight = document.documentElement.clientHeight || document.body.clientHeight;
  var canvas = document.getElementById('canvas') as HTMLCanvasElement,
  ctx = canvas.getContext('2d') as CanvasRenderingContext2D,
  w = canvas.width = windowWidth,
  h = canvas.height = windowHeight,
  
  hue = 217,
  stars:IntStart[] = [],
  count = 0,
  maxStars = 500;//星星数量
  
  var canvas2 = document.createElement('canvas') ,
  ctx2 = canvas2.getContext('2d') as CanvasRenderingContext2D;
  canvas2.width = 100;
  canvas2.height = 100;
  var half = canvas2.width / 2,
  gradient2 = ctx2.createRadialGradient(half, half, 0, half, half, half);
  gradient2.addColorStop(0.025, '#CCC');
  gradient2.addColorStop(0.1, 'hsl(' + hue + ', 61%, 33%)');
  gradient2.addColorStop(0.25, 'hsl(' + hue + ', 64%, 6%)');
  gradient2.addColorStop(1, 'transparent');
  
  ctx2.fillStyle = gradient2;
  ctx2.beginPath();
  ctx2.arc(half, half, half, 0, Math.PI * 2);
  ctx2.fill();
  
  // End cache
  
  function random(min:number, max=0) {
  if (arguments.length < 2) {
    max = min;
    min = 0;
  }
  
  if (min > max) {
    var hold = max;
    max = min;
    min = hold;
  }
  
  return Math.floor(Math.random() * (max - min + 1)) + min;
  }
  
  function maxOrbit(x:number, y:number) {
  var max = Math.max(x, y),
    diameter = Math.round(Math.sqrt(max * max + max * max));
  return diameter / 2;
  //星星移动范围,值越大范围越小,
  }
  interface IntStart{
  orbitRadius:number;
  radius:number;
  orbitX:number;
  orbitY:number
  timePassed:number;
  speed:number;
  alpha:number;
  draw:()=>void;
  }
  var Star = function(this: IntStart) {
  
  this.orbitRadius = random(maxOrbit(w, h));
  this.radius = random(60, this.orbitRadius) / 18; 
  //星星大小
  this.orbitX = w / 2;
  this.orbitY = h / 2;
  this.timePassed = random(0, maxStars);
  this.speed = random(this.orbitRadius) / 500000; 
  //星星移动速度
  this.alpha = random(2, 10) / 10;
  
  count++;
  stars[count] = this;
  }
  
  Star.prototype.draw = function() {
  var x = Math.sin(this.timePassed) * this.orbitRadius + this.orbitX,
    y = Math.cos(this.timePassed) * this.orbitRadius + this.orbitY,
    twinkle = random(10);
  
  if (twinkle === 1 && this.alpha > 0) {
    this.alpha -= 0.05;
  } else if (twinkle === 2 && this.alpha < 1) {
    this.alpha += 0.05;
  }
  
  ctx.globalAlpha = this.alpha;
  ctx.drawImage(canvas2, x - this.radius / 2, y - this.radius / 2, this.radius, this.radius);
  this.timePassed += this.speed;
  }
  
  for (var i = 0; i < maxStars; i++) {
  new Star.prototype.constructor();
  }
  
  function animation() {
  ctx.globalCompositeOperation = 'source-over';
  ctx.globalAlpha = 0.5; //尾巴
  ctx.fillStyle = 'hsla(' + hue + ', 64%, 6%, 2)';
  ctx.fillRect(0, 0, w, h)
  
  ctx.globalCompositeOperation = 'lighter';
  for (var i = 1, l = stars.length; i < l; i++) {
    stars[i].draw();
  };
  
  window.requestAnimationFrame(animation);
  }
  
  animation();
  }

新增login.module.scss样式文件

.loginPage{
    position: relative;
    .loginBox{
        width: 450px;
        position: absolute;
        left: 50%;
        top: 50%;
        transform: translate(-50%,-50%);
        color:#fff;
  
        h1{
            font-weight: bold;
            font-size: 22px;
            text-align: center;
            color:#fff;
        }
        p{
            text-align: center;
            margin: 20px 0;
        }
        .title{
            margin-bottom: 40px;
            position: relative;
            &:before,&:after{
                content:"";
                width: 100px;
                height: 2px;
                position: absolute;
                background: linear-gradient(to right,rgba(255,255,255,0),#1976D2);
                left: -20px;
                top:18px;
            }
            &:after{
                left: auto;
                background: linear-gradient(to left,rgba(255,255,255,0),#1976D2);
                right: -20px;
            }
        }
    }
  }

新增login.less自定义样式文件

.loginbox{
    //控制表单元素
    .ant-input, .ant-input-password {
        background-color: rgba(255,255, 255, 0);
        border-color:#1677ff;
        color:#fff;
        height:38px;
    }

    //控制输入框中提示文字
    .ant-input::-webkit-input-placeholder{
        //color:#1677ff;
        color:rgba(22,119,255, 0.5)
    }

    //控制password组件中的输入框
    .ant-input-password {
        .ant-input{
            height:28px;
        }
    }

    // 控制眼睛图标
    .ant-input-password-icon.anticon {
        color:#1677ff;
    }

    //控制验证码盒子
    .captchaBox{
        display: flex;
        .captchaImg{
            margin-left: 20px;
            cursor: pointer;
        }
    }

    //控制登录按钮
    .loginBtn{
        height:38px;
    }
}

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
引用:react-router-dom是一个用于React应用程序的路由库。它提供了一种管理应用程序中不同面之间导航的方式。react-router-dom有几个相关的模块,包括react-router-native、react-router-redux和react-router-config等。其中,react-router-native是用于React Native应用程序的绑定,react-router-redux是与Redux结合使用的模块,而react-router-config则是一个用于静态路由配置的助手。 引用:在使用react-router-dom的v6版本时,可以通过使用useRoutes函数来绑定路由配置。在一个App组件中,可以导入routes文件,并在App组件中使用useRoutes函数将路由配置渲染到面上。 引用:在v6版本中,可以选择使用BrowserRouter或HashRouter来包裹整个应用程序的组件。BrowserRouter和HashRouter的作用都是为了管理地址栏的URL,但BrowserRouter使用的是正常的URL路径,而HashRouter修改的是地址栏的hash值。另外,在v6版本中,可以使用<Routes>和<Route>来进行路由配置,其中<Routes>用于包含多个<Route>组件,每个<Route>对应一个面。 所以,如果你想了解react-router-dom v6的更多内容,可以参考官方文档或查看相关示例代码。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [react-router:react-router 中文文档](https://download.csdn.net/download/weixin_42166261/18230223)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [react-router-dom V6 中文文档教程总结](https://blog.csdn.net/xm1037782843/article/details/127454966)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [React学习笔记_React Router 6](https://blog.csdn.net/qq_20470063/article/details/123361115)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

snipercai

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值