2024-08-11



// 导入必要的模块
const express = require('express');
const router = express.Router();
const { body, validationResult } = require('express-validator');
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
const User = require('../models/user');
 
// 注册接口
router.post('/register', 
  [
    body('username').isLength({ min: 5 }).withMessage('用户名至少5个字符'),
    body('password').isLength({ min: 5 }).withMessage('密码至少5个字符'),
    body('email').isEmail().withMessage('请输入有效的邮箱')
  ], 
  async (req, res) => {
    const errors = validationResult(req);
    if (!errors.isEmpty()) {
      return res.status(400).json({ errors: errors.array() });
    }
 
    const { username, password, email } = req.body;
 
    try {
      // 检查用户是否已存在
      const userExists = await User.findOne({ username });
      if (userExists) {
        return res.status(400).json({ message: '用户已存在' });
      }
 
      // 创建新用户
      const user = new User({
        username,
        password: bcrypt.hashSync(password, 10),
        email
      });
 
      await user.save();
      res.status(201).json({ message: '注册成功' });
    } catch (err) {
      res.status(500).json({ message: '服务器错误' });
    }
  }
);
 
// 登录接口
router.post('/login', 
  [
    body('username').not().isEmpty().withMessage('用户名不能为空'),
    body('password').not().isEmpty().withMessage('密码不能为空')
  ], 
  async (req, res) => {
    const errors = validationResult(req);
    if (!errors.isEmpty()) {
      return res.status(400).json({ errors: errors.array() });
    }
 
    const { username, password } = req.body;
 
    try {
      const user = await User.findOne({ username });
      if (!user) {
        return res.status(401).json({ message: '用户不存在' });
      }
 
      if (!bcrypt.compareSync(password, user.password)) {
        return res.status(401).json({ message: '密码错误' });
      }
 
      const token = jwt.sign({ userId: user.id }, process.env.JWT_SECRET, { expiresIn: '1h' });
      res.status(200).json({ token, userId: user.id, username: user.username });
    } catch (err) {
      res.status(500).json({ message: '服务器错误' });
    }
  }
);
 
module.exports = router;

这段代码实现了用户注册和登录的接口,使用了Express框架和express-validator中间件来处理请求验证,并使用bcryptjs进行密码散列,以及jsonwebtoken生成用户认证token。代码示例中包含了错误处理和用户存在性的检查,有助于理解如何在实际应用中处理用

2024-08-11

以下是一个简单的分页器实现,使用JavaScript和React。




import React, { useState } from 'react';
import PropTypes from 'prop-types';
 
const Pagination = ({ itemsCount, pageSize }) => {
  const [currentPage, setCurrentPage] = useState(1);
 
  const goToPage = (page) => {
    if (page < 1 || page > Math.ceil(itemsCount / pageSize)) return;
    setCurrentPage(page);
  };
 
  const handlePreviousClick = () => goToPage(currentPage - 1);
  const handleNextClick = () => goToPage(currentPage + 1);
 
  const pagesCount = Math.ceil(itemsCount / pageSize);
  const pages = Array.from({ length: pagesCount }, (_, i) => i + 1);
 
  return (
    <div>
      <button disabled={currentPage === 1} onClick={handlePreviousClick}>
        Previous
      </button>
      {pages.map((page) => (
        <button
          key={page}
          onClick={() => goToPage(page)}
          style={{ backgroundColor: currentPage === page ? 'blue' : 'white' }}
        >
          {page}
        </button>
      ))}
      <button disabled={currentPage === pagesCount} onClick={handleNextClick}>
        Next
      </button>
    </div>
  );
};
 
Pagination.propTypes = {
  itemsCount: PropTypes.number.isRequired,
  pageSize: PropTypes.number.isRequired,
};
 
export default Pagination;

在这个例子中,我们创建了一个名为Pagination的React组件,它接受itemsCount(总项目数)和pageSize(每页项目数)作为props。组件状态包含当前currentPage,并提供了goToPage方法来更新这个状态。handlePreviousClickhandleNextClick方法用来处理上一页和下一页的点击事件。最后,我们生成页面按钮并根据当前页设置样式。

2024-08-11

报错解释:

这个错误表明Visual Studio Code (VSCode) 在尝试使用npm启动一个Vue项目时,无法找到npm的主要执行文件npm-cli.js。这通常是因为npm没有正确安装或者环境变量配置不正确导致的。

解决方法:

  1. 确认npm是否已经安装:在命令行中输入npm --version,如果返回版本号,则npm已安装。
  2. 如果npm未安装或版本号不显示,需要先安装npm。可以通过Node.js的安装程序来获取npm,因为Node.js也会自动安装npm。
  3. 确认环境变量配置:检查系统的环境变量,确保npm的安装路径已经添加到了PATH变量中。
  4. 重新安装npm:如果上述步骤都没有问题,尝试重新安装Node.js和npm。
  5. 使用VSCode内置终端:尝试在VSCode的内置终端中运行npm命令,有时候是因为外部终端的环境变量配置与VSCode不同。
  6. 检查项目的package.json文件:确认文件中的脚本是否正确,以及是否有正确的启动命令。

如果以上步骤都不能解决问题,可能需要重新安装VSCode或者检查是否有其他软件冲突导致环境变量问题。

2024-08-11

在JavaScript、Vue 3和React中获取鼠标位置的方法如下:

JavaScript:




document.addEventListener('mousemove', (event) => {
  const mouseX = event.clientX;
  const mouseY = event.clientY;
  console.log({ mouseX, mouseY });
});

Vue 3:




<template>
  <div @mousemove="getMousePosition">
    移动鼠标以获取位置
  </div>
</template>
 
<script>
export default {
  methods: {
    getMousePosition(event) {
      const mouseX = event.clientX;
      const mouseY = event.clientY;
      console.log({ mouseX, mouseY });
    }
  }
}
</script>

React:




import React, { useState } from 'react';
 
const MouseTracker = () => {
  const [mousePosition, setMousePosition] = useState({ x: 0, y: 0 });
 
  const handleMouseMove = (event) => {
    setMousePosition({
      x: event.clientX,
      y: event.clientY
    });
  };
 
  return (
    <div onMouseMove={handleMouseMove}>
      移动鼠标以获取位置 ({mousePosition.x}, {mousePosition.y})
    </div>
  );
};
 
export default MouseTracker;

以上代码片段展示了如何在不同的框架中获取鼠标位置,并在控制台中打印出来。

2024-08-11

在JavaScript中,可以使用forEach方法来遍历Map对象。

示例代码:




let myMap = new Map();
myMap.set('key1', 'value1');
myMap.set('key2', 'value2');
myMap.set('key3', 'value3');
 
myMap.forEach(function(value, key) {
    console.log(key + ' = ' + value);
});

输出将会是:




key1 = value1
key2 = value2
key3 = value3

forEach方法接受一个回调函数作为参数,该回调函数接受键(key)和值(value)作为参数。对于Map中的每个条目,会调用该回调函数。

2024-08-11

在JavaScript中,可以使用第三方库来读取和导出Excel文件。一个常用的库是xlsx,它可以处理多种格式的电子表格文件。

以下是使用xlsx库的示例代码:

安装xlsx库:




npm install xlsx

读取Excel文件内容:




const XLSX = require('xlsx');
 
// 读取Excel文件
const readExcel = (file) => {
  const reader = new FileReader();
  reader.onload = (e) => {
    const data = new Uint8Array(e.target.result);
    const workbook = XLSX.read(data, { type: 'array' });
    const firstSheetName = workbook.SheetNames[0];
    const worksheet = workbook.Sheets[firstSheetName];
    const json = XLSX.utils.sheet_to_json(worksheet);
    console.log(json);
  };
  reader.readAsArrayBuffer(file);
};
 
// 假设你有一个input元素来上传文件
const input = document.getElementById('input-excel');
input.addEventListener('change', (e) => {
  const file = e.target.files[0];
  readExcel(file);
});

导出JSON数据到Excel文件:




const writeExcel = (data, fileName) => {
  const worksheet = XLSX.utils.json_to_sheet(data);
  const workbook = XLSX.utils.book_new();
  XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1');
  
  const wbout = XLSX.write(workbook, { bookType: 'xlsx', type: 'binary' });
  function s2ab(s) {
    const buf = new ArrayBuffer(s.length);
    const view = new Uint8Array(buf);
    for (let i = 0; i !== s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
    return buf;
  }
  
  saveAs(new Blob([s2ab(wbout)], { type: 'application/octet-stream' }), fileName + '.xlsx');
};
 
// 示例数据
const jsonData = [
  { name: 'Alice', email: 'alice@example.com' },
  { name: 'Bob', email: 'bob@example.com' }
];
 
// 导出数据到Excel文件
writeExcel(jsonData, 'data');

在上面的代码中,readExcel函数用于读取用户通过<input>元素上传的Excel文件,并将其内容转换为JSON。writeExcel函数则将JSON数据导出为Excel文件,你可以通过修改jsonData变量来导出不同的数据。

注意:saveAs函数来自于file-saver库,需要单独安装:




npm install file-saver

这些代码示例假设你正在使用一个HTML页面,并且已经有相应的<input>元素来上传文件。如果你在浏览器环境中运行这些代码,请确保服务是通过HTTPS提供的,因为现代浏览器限制了从非HTTPS来源读取文件。

2024-08-11

在Node.js中切换版本通常有两种方法:

  1. 使用nvm(Node Version Manager):

    • 安装nvm:访问https://github.com/nvm-sh/nvm 并按照说明安装。
    • 安装特定版本的Node.js:nvm install <version>
    • 切换到特定版本:nvm use <version>
  2. 使用n

    • 安装n:在终端中运行npm install -g n
    • 切换到特定版本:n <version>

以下是使用nvm切换Node.js版本的示例代码:




# 安装nvm(如果尚未安装)
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash
 
# 在新的终端会话中,安装Node.js的特定版本
nvm install 14.17.0
 
# 切换到该版本
nvm use 14.17.0

使用n的示例代码:




# 安装n
npm install -g n
 
# 切换到特定版本
n 14.17.0

选择使用nvm还是n取决于个人喜好和环境配置。nvm提供了更多的灵活性,允许你在不同项目之间切换不同的Node.js版本,而n更简单一些,它更适合于快速切换到最新的稳定版本。

2024-08-11

在Webpack中,自动tree-shaking节省代码体积的一个主要方法是通过UglifyJsPlugin插件在生产模式下移除死代码。为了在开发模式下也能实现类似的效果,可以使用webpackMode配置以及相关的插件如terser-webpack-plugin

以下是一个简单的配置示例,展示了如何在webpack中启用tree-shaking:




const TerserPlugin = require('terser-webpack-plugin');
 
module.exports = (env, argv) => {
  return {
    // 设置模式
    mode: argv.mode === 'development' ? 'development' : 'production',
    optimization: {
      minimize: true,
      minimizer: [
        new TerserPlugin({
          terserOptions: {
            compress: {
              // 启用内联函数
              inline: 2,
            },
          },
        }),
      ],
    },
    // 其他webpack配置...
  };
};

在这个配置中:

  • mode 设置为 'development''production' 来指定当前的构建环境。
  • optimization.minimize 设置为 true 来启用压缩和优化。
  • optimization.minimizer 数组中包含了 TerserPlugin 实例,它会在构建过程中被调用来压缩和 mangle 代码。

确保你已经安装了 terser-webpack-plugin,如果没有,可以通过以下命令安装:




npm install terser-webpack-plugin --save-dev

在实际的项目中,Webpack 会自动识别 importexport 语法并进行适当的tree-shaking,无需手动介入。但是,为了确保在开发模式下也能获得类似效果,可以手动启用更加强大的压缩选项,例如内联函数的优化等。

2024-08-11



<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>购物平台特惠</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            margin: 0;
            padding: 20px;
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            background-color: #f7f7f7;
        }
        .box {
            background-color: #fff;
            padding: 20px;
            box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
        }
        img {
            max-width: 100%;
            height: auto;
        }
    </style>
</head>
<body>
    <div class="box">
        <h1>特惠</h1>
        <img src="coupon.png" alt="特惠券" />
        <p>
            购买任意金额商品<br>
            立即得 into 现金<br>
            <strong>立即领取</strong>
        </p>
        <button onclick="claimCoupon()">领取</button>
    </div>
    <script>
        function claimCoupon() {
            alert('特惠券已发送至您的账户,请查收!');
            // 这里可以添加发送特惠券到用户账户的逻辑
        }
    </script>
</body>
</html>

这个简易的HTML页面包含了一个模拟的特惠券领取页面,点击领取按钮会触发一个简单的 alert 弹窗提示用户特惠券已发送。在实际应用中,你需要替换样式和图片资源,并且添加后端逻辑来处理特惠券的发放。

2024-08-11

Promise 是 JavaScript 中进行异步编程的一个API。它是一个代理对象,代表了一个异步操作的最终结果。

Promise 对象有以下两个特点:

  1. 对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:Pending(进行中)、Resolved(已完成)和 Rejected(已失败)。只有异步操作的结果可以决定这个状态,任何其他操作都无法改变这个状态。
  2. 一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变只有两种可能:从Pending变为Resolved和从Pending变为Rejected。

基本用法:




// 创建一个Promise
let promise = new Promise(function(resolve, reject) {
    // 异步操作
    let result = "success";
    if (/* 异步操作成功 */) {
        resolve(result);
    } else {
        reject("failure");
    }
});
 
// 使用then方法添加回调函数
promise.then(function(successMessage) {
    // success 回调
    console.log(successMessage);
}, function(errorMessage) {
    // error 回调
    console.log(errorMessage);
});

Promise 的 then 方法可以接受两个参数,第一个参数是 Promise 对象的状态变为 Resolved 时调用的函数,第二个参数是 Promise 对象的状态变为 Rejected 时调用的函数。

catch 方法用于处理 Promise 的异常情况:




promise.then(function(successMessage) {
    // success 回调
    console.log(successMessage);
}).catch(function(errorMessage) {
    // 如果 then 中没有指定错误处理,错误会传递到 catch 中
    console.log(errorMessage);
});

finally 方法不管 Promise 对象最后的状态如何,都会执行:




promise.then(function(successMessage) {
    // success 回调
    console.log(successMessage);
}).catch(function(errorMessage) {
    // error 回调
    console.log(errorMessage);
}).finally(function() {
    // 不管 Promise 最后的状态如何,都会执行这里的代码
    console.log("The operation completed!");
});

Promise.all 方法用于将多个 Promise 实例包装成一个新的 Promise 实例:




let promise1 = Promise.resolve(3);
let promise2 = 42;
let promise3 = new Promise((resolve, reject) => {
  setTimeout(resolve, 100, 'foo');
});
 
Promise.all([promise1, promise2, promise3]).then(values => {
  console.log(values); // [3, 42, "foo"]
});

Promise.race 方法同样用于包装多个 Promise 实例,但是只要有一个实例变为 Resolved 或 Rejected,包装的 Promise 就会立即改变状态:




let promise1 = new Promise((resolve, reject) => {
  setTimeout(resolve, 100, 'promise1');
});
let promise2 = new Promise((resolve, reject) => {
  setTimeout(resolve, 200, 'promise2');
});
 
Promise.race([promise1, promise2]).then(value => {
  console.log(value); // "promise1",因为它是第一个变为 Resolved 的
});

以上是对 Promise 的基本介绍和常用方法,实际使用中还会涉及到更复杂的异步流程控制。