1 Star 0 Fork 2

默默 / nuxt-project

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
README.md 11.00 KB
一键复制 编辑 原始数据 按行查看 历史
默默 提交于 2022-01-20 20:00 . 添加切片上传文档

项目创建与基本配置

nuxtjs app 创建

npx create-nuxt-app <项目名>

nuxtjs 中文官网

eggjs app 创建

mkdir egg-example && cd egg-example
npm init egg --type=simple
npm i

eggjs 官网

mongodb

  • 网上查找安装运行
  • 将目录下的mongodb.bat文件内容dbpath后面的路径指向数据库地址
  • 双击即可开启数据库

项目主要目录介绍

nuxtjs app

  • components : 项目组件
  • pages : 页面
  • plugins : 插件
  • static : 静态资源
  • test : 测试文件
  • nuxt.config.js : 主要配置文件
  • package.json : 包管理文件

eggjs app

egg-project
├── package.json
├── app.js (可选)
├── agent.js (可选)
├── app  接口等编写的主要文件夹
|   ├── router.js   路由(接口定义位置,与控制器组合为一个完整接口)
│   ├── controller  控制器(接口位置)
│   |   └── home.js
│   ├── service (可选)
│   |   └── user.js
│   ├── middleware (可选)
│   |   └── response_time.js
│   ├── schedule (可选)
│   |   └── my_task.js
│   ├── public (可选)
│   |   └── reset.css
│   ├── view (可选)
│   |   └── home.tpl
│   └── extend (可选)
│       ├── helper.js (可选)
│       ├── request.js (可选)
│       ├── response.js (可选)
│       ├── context.js (可选)
│       ├── application.js (可选)
│       └── agent.js (可选)
├── config  配置文件
|   ├── plugin.js  插件配置文件
|   ├── config.default.js 默认配置文件,返回的对象可以使用`this.app.config`获取
│   ├── config.prod.js
|   ├── config.test.js (可选)
|   ├── config.local.js (可选)
|   └── config.unittest.js (可选)
└── test  测试文件
    ├── middleware
    |   └── response_time.test.js
    └── controller
        └── home.test.js

项目配置

代理配置【只需要在 nuxtjs 项目中配置代理即可】

文件:nuxt.config.js

export default {
      modules: ["@nuxtjs/proxy"],
      proxy: {
            "/api/": {
                  target: "http://localhost:7001",
                  screen: false,
                  pathRewrite: {
                        "^/api": "",
                  },
            },
      },
};

【1】.如果运行的时候报@nuxtjs/proxy不存在?

 npm install @nuxtjs/proxy

【2】.配置后,访问还是显示未找到页面?

尝试重启前端项目

【3】.配置后,发现访问显示 404,与【2】情况不一样?

"^/api": ""这里是^/,如果没有问题,在检查一下配置

axios 拦截配置

import Vue from "vue";
import axios from "axios";

const $http = axios.create({
      baseURL: "/api",
});

// 请求拦截,所有请求前会通过这里,这里可以为请求添加参数
$http.interceptors.request.use((config) => {
      const token = localStorage.getItem("token");
      if (token) {
            config.headers.common["Authorization"] = "Bearer " + token;
      }

      return config;
});

// 响应拦截,所以请求响应都会走这里,这里可以处理返回的参数
$http.interceptors.response.use((response) => {
      const { data } = response;

      return data;
});

Vue.prototype.$http = $http;

ts 为 Vue 拓展属性添加类型注解

根目录下添加 shims-vue.d.ts 文件,内容如下

// 拓展Vue原型方法
import { AxiosInstance } from "axios";
declare module "vue/types/vue" {
      interface Vue {
            $http: AxiosInstance;
      }
}

配置别名(alise)

条件:

  • ts 项目: 配置别名在tsconfig.json
  • js 项目: 配置别名在nuxt.config.js文件中

tsconfig.json

{
      "compilerOptions": {
            "paths": {
                  "@type/*": ["./type/*"],
                  "@comp/*": ["./components/*"]
            }
      }
}

nuxt.config.js

export default {
      alias: {
            // ts type
            "@type": "./type/*",
      },
};

axios 读取请求进度

this.$http.post("/uploadfile", form, {
      onUploadProgress: (progress: any) => {
            this.uploadProgress = Number(
                  ((progress.loaded / progress.total) * 100).toFixed(2)
            );
      },
});

取消 post 请求 csrf 拦截【只需要在 eggjs 项目中配置即可】

这个拦截是必要的,但是项目在开发前期,没有使用登录系统的时候,这个拦截会让我们无法测试 post 请求,所以我们暂时取消 文件:config.default.js

return {
      security: {
            csrf: {
                  enable: false,
            },
      },
};

配置 mongodb

文件:config.default.js

return {
      mongoose: {
            client: {
                  url: "mongodb://127.0.0.1:<端口号:默认端口号为27017>/<databaseName>",
                  options: {},
            },
      },
};

eggjs 开启文件上传

config.multipart = {
      mode: "file",
      whitelist: () => true,
};

eggjs 中间键编写与使用

文件创建

app目录下添加文件夹middleware,创建文件jwt.js,后期访问这个中间键使用app.middleware.jwt

编写

module.exports = ({ app }) => {
      return async function verify(ctx, next) {
            // 搞事情
            await next();
      };
};

注意点:next方法一定要记得await,否则相当于这个请求结束了,但是没有返回,前端接口报 404 错误

使用

module.exports = (app) => {
      const { router, controller } = app;
      const jwt = app.middleware.jwt({ app });
      router.post("/uploadfile", jwt, controller.util.uploadFile);
};

功能相关

文件读取与上传校验

浏览器读取 ·类文件对象· 并转为16进制

function blobToString(blob: Blob) {
      return new Promise(resolve => {
          	// 创建读取文件的对象
            const reader = new FileReader();
			// 二进制文件加载完成后
            reader.onload = function () {
                  const result = reader.result as string;
                  // 对读取到的内容进行处理
                  const res = result.split("")
                        .map(v => v.charCodeAt(0))
                        .map(v => v.toString(16).toUpperCase())
                        .join(" ");
                  resolve(res);
            }

			// 读取二进制文件
            reader.readAsBinaryString(blob);
      })
}

图片类型的16进制的不同

判断是否为gif

async function isGif(blob: Blob) {
      const res = await blobToString(blob.slice(0, 6))
      return (res === "47 49 46 38 39 61") || (res === "47 49 46 38 37 61");
}

gif图片特点是16进制数据前6位为47 49 46 38 39 61或者47 49 46 38 37 61

判断是否为png

async function isPng(blob: Blob) {
      const res = await blobToString(blob.slice(0, 8))
      console.log(res)
      return (res == "89 50 4E 47 0D 0A 1A 0A")  || (res === "89 50 4E 47 D A 1A A");
}

png图片特点是16进制数据前8位为89 50 4E 47 0D 0A 1A 0A, 因为有时候读出来开头0省略,所以添加了后面这个

判断是否为jpg

async function isJpg(blob: Blob) {
      let len = blob.size;
      const start = await blobToString(blob.slice(0, 2))
      const tail = await blobToString(blob.slice(-2, len))
      return (start === "FF D8") && (tail === "FF D9");
}

jpg图片特点是16进制数据前两位为FF D8并且后两位为FF D9

总结

  • 其实在二进制文件中还保存着图片的大小信息,所以其实可以通过这个来进行图片的大小判断
  • 通过十六进制的判断,可以防止别人上传的文件不符合要求,比如:将pdf文件后缀改成png文件然后上传
  • 当然也可以用这个方法判断其他文件上传时候正常

切片上传

切片上传

拖拽功能

事件名称 触发条件
drag 拖动元素或选择文本时触发此事件
dragstart 当用户开始拖动元素或选择文本时触发此事件
dragend 当拖动操作结束时(释放鼠标按钮或按下退出键),会触发此事件
dragenter 当拖动的元素或选择文本输入有效的放置目标时,会触发此事件
dragexit 当元素不再是拖动操作的选择目标时触发此事件
dragover 当将元素或文本选择拖动到有效放置目标(每几百毫秒)上时,会触发此事件
dragleave 当拖动的元素或文本选择离开有效的放置目标时,会触发此事件
drop 拖拽物品放下时触发

MDN Drag

MDN dragEvent

编写技巧

基础 Controller

问题: 我们返回的内容应该保持一致性,这样前端处理时才会更加方便

我们可以编写一个公共的 Controller,并且提供一些公共的方法,然后让其他的 Controller 集成这个公共的,保证返回的一致性

basic.js

"use strict";

const Controller = require("egg").Controller;

class BasicController extends Controller {
      success(data) {
            const { ctx } = this;
            ctx.body = {
                  code: 0,
                  data,
            };
      }

      error(code = -1, message, errors) {
            const { ctx } = this;
            ctx.body = {
                  code,
                  message,
                  errors,
            };
      }

      message(message) {
            const { ctx } = this;
            ctx.body = {
                  code: 0,
                  message,
            };
      }
}
module.exports = BasicController;

user.js

"use strict";

const BasicController = require("./basic");

const registerRule = {
      password: { type: "string" },
      username: { type: "string" },
      email: { type: "email" },
      captcha: { type: "string" },
};

class UserController extends BasicController {
      async register() {
            const num = parseInt(Math.random() * 10, 10);

            if (num % 2 === 0) {
                  return this.error("参数校验失败", -1, "其他消息");
            }
            this.success("注册成功");
      }
}

module.exports = UserController;
JavaScript
1
https://gitee.com/wangzhaoyv/nuxt-project.git
git@gitee.com:wangzhaoyv/nuxt-project.git
wangzhaoyv
nuxt-project
nuxt-project
master

搜索帮助