【Vue】脚手架的一些个介绍

脚手架

  • Vue CLI 是一个基于 Vue.js 进行快速开发的完整系统
  • 作用:快速生成 Vue 项目结构的基础框架

安装

  • 安装脚手架:npm i -g @vue/cli
  • 输入 vue -V 查看版本,以检查是否安装成功

创建项目

  1. 切换到要创建项目的目录,调出终端,输入命令:vue create project-name
    • cd 进项目目录、执行 npm run serve 运行项目
  2. 通过图形界面创建项目:vue ui

项目创建过程

  1. 输入 vue create demo 命令行创建 Vue 项目 demo
  2. Please pick a preset: (Use arrow keys) —— 选择预设
    1. Default ([Vue 2] babel, eslint) —— Vue2 的默认配置
      1. babel:浏览器只认识 ES5 语法,babel 能将代码中 ES6 语法转成 ES5 语法
      2. eslint:检查 JS 语法
    2. Default (Vue 3) ([Vue 3] babel, eslint) —— Vue3 的默认配置
    3. Manually select features —— 自定义配置 √
  3. Please pick a preset: Manually select features —— 选择需要的功能
    Check the features needed for your project: (Press space to select, a to toggle all, i to invert selection)
    1. Babel —— ES6 向下兼容 ES5 √
    2. TypeScript —— 是否支持 TS 语法
    3. Progressive Web App (PWA) Support —— 网页应用程序(应用的话,离线状态下也能访问网页,但兼容性较差)
    4. Router —— 路由 √
    5. Vuex —— 用于管理数据 √
    6. CSS Pre-processors —— CSS 预处理器 (less、sass、styuls) √
    7. Linter / Formatter —— 检查 JS 语法
    8. Unit Testing —— 单元测试模块
    9. E2E Testing —— 端测试模块
  4. Choose a version of Vue.js that you want to start the project with (Use arrow keys) —— 选择 Vue.js 版本
    • 2.x √
    • 3.x
  5. Use history mode for router? (Requires proper server setup for index fallback in production) —— 路由器使用 history 模式 n
  6. Pick a CSS pre-processor (PostCSS, Autoprefixer and CSS Modules are supported by default): —— 选择 CSS 预处理器
    1. Sass/SCSS (with dart-sass)
    2. Sass/SCSS (with node-sass)
    3. Less √
    4. Stylus
  7. Pick a linter / formatter config: (Use arrow keys)
    1. ESLint with error prevention only
    2. ESLint + Airbnb config
    3. ESLint + Standard config
    4. ESLint + Prettier √
  8. Pick additional lint features:
    1. Lint on save √
    2. Lint and fix on commit
  9. Where do you prefer placing config for Babel, ESLint, etc.? —— 配置存储位置
    1. In dedicated config files
    2. In package.json √
  10. Save this as a preset for future projects? (y/N) —— 是否存为默认预设 N

项目结构分析

  1. node_modules:项目依赖文件夹,可通过 npm i / yarn 下载
  2. public:存放静态资源;webpack 打包时,会将该文件夹中的静态资源 原封不动地打包到 dist 文件夹中
    1. favicon.ion:图标
    2. index.html:模板,可通过 webpack 配置修改
  3. src:源码目录
    1. assets:存放静态资源(一般放置多个组件共用的静态资源)
      webpack 打包时,会把该文件夹中的静态资源 当作一个模块,编译、打包到 JS 文件里面
    2. components:一般存放非路由组件。组件中的 name 属性应与文件名一样,方便后期维护;组件名使用大驼峰
    3. router:存放路由文件,主文件名为 index.js
    4. store:存放 Vuex 文件,主文件名为 index.js
    5. views:存放页面组件
    6. App.vue:根组件,是所有组件的父组件
    7. main.js:入口文件,是整个程序中最先执行的文件
  4. .gitignore:用于配置不需要被 Git 管理的文件(夹)
  5. babel.config.js:babel 的配置文件,用于处理 ES 语法的兼容问题
  6. jsconfig.json:配置 webpack 的文件
  7. package.json:应用包配置文件
  8. pack-lock.json:包版本控制文件。指定项目依赖包的版本号,保证其他人在执行 npm i 时下载的依赖包与原版本一致
  9. vue.config.js:脚手架配置文件(可选),需要和 package.json 同级 √

jsconfig.json

  • 用于配置 webpack 的文件
  • 与其他 JSON 文件不同的是,该 JSON 文件可以写注释
{
    "compilerOptions": { // 编译配置
        "target": "es5",
        "module": "esnext",
        "baseUrl": "./",
        "moduleResolution": "node",
        "paths": {
            "@/*": ["src/*"] // 设置路径简写 `@` → `src/`
        },
        "lib": ["esnext", "dom", "dom.iterable", "scripthost"]
    }
}
  • 在 CSS 中也可以使用 @,但是要在前面加 ~
background: url('~@/assets/1.jpg');

package.json

  1. npm run serve:开启服务器;这里其实是在 script 字段中配置了 "serve": "vue-cli-service serve"
    "scripts": {
        "serve": "vue-cli-service serve",
        "build": "vue-cli-service build",
        "lint": "vue-cli-service lint"
    },

main.js

  • main.js 是整个项目的入口文件
  • render 为渲染函数,接收 createElement 方法作为第 1 参数,以创建 VNode
  • 若 render 函数存在,则 Vue 构造函数不会从 template / el 选项指定的挂载元素中提取出的 HTML 模板编译渲染函数
// 引入 vue,默认为残缺版的 Vue:dist/vue.runtime.common.js,里面没有 [模板解析器]
// 完整版的 Vue 在 vue/dist/vue.js
// 可以在 package.json 文件中设置默认项
import Vue from 'vue'

// 引入 App.vue 组件
import App from './App.vue'

// 关闭生产版本的提示
Vue.config.productionTip = false

// 创建 Vue 实例
new Vue({
    // 引入完整版的 Vue 才能使用 template,因为需要 [模板解析器]
    // template: ``,
    // components: { App }

    // 残缺版的 Vue 可使用 render 渲染模版
    // render: h => h(App) // 简写

    render(createElement) { // 标准写法
        // return createElement("h1", "大哥好") // 使用方法1:渲染节点
        return createElement(App) // 使用方法2:渲染组件
    }
}).$mount('#app')

/*
    使用残缺版 Vue 的理由:
    因为 [模版解析器] 的体积非常大,使用阉割版的 Vue 可以使项目打包后体积小一些
        假设我需要铺地砖,现有两种方法:
        第一种:买 100 块地砖 + 买 3 个工人 => 得到:完整的装修 + 3 个工人
        第二种:买 100 块地砖 + 雇 3 个工人 => 得到:完整的装修
    render 的使用就像好比第二种,使用完工人(模版解析器)后即可抛弃
*/

vue.config.js

  • vue.config.js 是一个可选的脚手架配置文件,会更新 webpack.config.js 中对应的配置项
  • 修改完成后需要重新执行 npm run serve
  • vue inspect > 文件名.js - 可以输出 vue 的 webpack 配置,供用户查看

该文件会导出一个 [包含了各种配置选项的] 对象:

module.exports = {}

可以使用 @vue/cli-service 提供的 defineConfig 帮手函数,以获得更好的类型提示:

const { defineConfig } = require('@vue/cli-service');
module.exports = defineConfig({});

一些个基本配置

const { defineConfig } = require('@vue/cli-service');

module.exports = defineConfig({
    transpileDependencies: true, // 是否将所有文件都编译一遍(通过 babel 编译文件:ES6+ → ES5)
    pages: {
        index: {
            // page 的入口
            entry: 'src/index/main.js',
            // 模板来源
            template: 'public/index.html',
            // 在 dist/index.html 的输出
            filename: 'index.html',
            // 当使用 title 选项时,
            // template 中的 title 标签需要是 <%= htmlWebpackPlugin.options.title %>
            title: 'Index Page',
            // 在这个页面中包含的块,默认情况下会包含
            // 提取出来的通用 chunk 和 vendor chunk
            chunks: ['chunk-vendors', 'chunk-common', 'index']
        },
        // 当使用只有入口的字符串格式时,
        // 模板会被推导为 `public/subpage.html`
        // 并且如果找不到的话,就回退到 `public/index.html`。
        // 输出文件名会被推导为 `subpage.html`。
        subpage: 'src/subpage/main.js'
    }
});

transpileDependencies

  • 默认情况下 babel-loader 会忽略所有 node_modules 中的文件

    为避免构建后的代码中出现未转译的第三方依赖,可以设置 transpileDependencies: true

    不过,对所有的依赖都进行转译会降低构建速度

const { defineConfig } = require('@vue/cli-service');
module.exports = defineConfig({ transpileDependencies: true });
  • 如果对构建性能有所顾虑,可以只转译部分依赖:
    传入一个 数组 作为属性值,列出需要转译的 [第三方包名] / [正则表达式] 即可

lintOnSave

  • 在开发环境下,是否在每次保存时使用 eslint-loader 检查代码格式
  • 这个值会在 @vue/cli-plugin-eslint 被安装之后生效
  • Type:boolean | 'warning' | 'default'(默认) | 'error'
    true / 'warning':将错误输出为警告,不会影响编译
    'default':将错误输出,会影响编译
    'error':把警告也输出为错误,会影响编译
module.exports = { lintOnSave: false } // 关掉检查
  • 可以配置 devServer.overlay 字段,让浏览器同时显示警告和错误
module.exports = {
    devServer: { overlay: { warnings: true, errors: true } }
}
  • lintOnSave 是一个 truthy 的值时,eslint-loader 在 [开发环境] 和 [生产环境] 下都会被启用
    如果想要在 [生产环境] 下禁用 eslint-loader,可以如下配置
module.exports = { lintOnSave: process.env.NODE_ENV !== 'production' }
  • webpack 在不同环境下的配置文件:[.env.development]-开发环境、 [.env.production]-生产环境、 [.env.staging]-测试环境
    我们可以通过变量 process.env 得知当前环境,并获取对应配置文件内的数据

使用 @vue/cli-service 提供的 defineConfig 帮手函数

const { defineConfig } = require('@vue/cli-service');
module.exports = defineConfig({ lintOnSave: false }); // 关闭 eslint 检验

devServer.proxy

  • vue-cli 提供了代理服务器,我们可以在 vue.config.js 中配置 devServer.proxy,以解决跨域问题
  • 代理服务器所处的 [位置] 与前端页面的 [位置] 一样,所以没有跨域问题
  • 服务器之间使用传统的 HTTP 请求交互,不需要 Ajax,所以也没有跨域问题
  • 前后端交互过程:
    ① 前端 → 代理服务器(请求)、 ② 代理服务器 → 服务器(请求)
    ③ 服务器 → 代理服务器(响应)、 ④ 代理服务器 → 前端(响应)

devServer.proxy 的 String 写法:值为 [需要代理的服务器地址]

const { defineConfig } = require('@vue/cli-service');

module.exports = defineConfig({
    devServer: { proxy: "http://127.0.0.1:5000" /* 需要代理的服务器地址 */ }
});

此时,前端通过 http://127.0.0.1:8080/url路径 获取数据即可
代理服务器就会向 http://127.0.0.1:5000url路径 发请求,以获取数据

如此,我们获取数据时,如果前端 ( public 文件夹 ) 有该数据资源,则直接获取前端资源
如果前端没有该数据资源,则发送请求给 [被代理的服务器] 获取数据(优先匹配前端资源

这种写法只能代理一台服务器!

devServer.proxy 的 Object 写法:通过 [请求前缀] 配置需要代理的多台服务器

const { defineConfig } = require('@vue/cli-service');

module.exports = defineConfig({
    devServer: {
        proxy: {
            // 通过 [请求前缀] 设置需要代理的多台服务器
            '/students': { target: 'http://localhost:5000' },
            '/books': { target: 'http://localhost:5001' },
        }
    }
});

该写法中,[请求前缀] 既是区分服务器的标识,也是要请求的路径
即:前端仍通过 http://127.0.0.1:8080/url路径 获取数据
获取数据时,仍是优先获取前端资源;前端没有该资源,才发送请求给 [被代理的服务器] 获取数据

  • 也可以设置 [请求前缀] 仅为服务器的标识:
const { defineConfig } = require('@vue/cli-service');

module.exports = defineConfig({
    devServer: {
        proxy: {
            '/api1': {
                target: 'http://localhost:5000',
                pathRewrite: { '^/api1': '' } // 隐藏 [请求前缀],保证请求地址能正确使用
            },
            '/api2': {
                target: 'http://localhost:5001',
                pathRewrite: { '^/api2': '' } // 隐藏 [请求前缀],保证请求地址能正确使用
            },
        }
    }
});

上例写法中,[请求前缀] 仅为服务器的标识,只要带上 [请求前缀] 就不会匹配前端资源
此时,我们发送请求时,就需要带上 [请求前缀] 以选择发送请求的服务器 http://127.0.0.1:8080/api1/url路径

devServer.proxy 的其他配置项

  1. changeOrigin:用于控制请求头中的 host 值

    true 时,服务器收到的请求头中的 host 为 localhost:3000(默认)

    false 时,服务器收到的请求头中的 host 为 localhost:8080

  2. ws:为 true 时,表示支持 webSocket(默认)

productionSourceMap

项目打包后,代码都是经过压缩加密的。如果运行时报错,输出的错误信息无法准确得知是哪里的代码出错
有了 map 文件就可以准确输出是哪里出错;如果项目不需要,可以不对其打包

const { defineConfig } = require('@vue/cli-service');
module.exports = defineConfig({ productionSourceMap: false }); // 不打包

关于基础模版

  • 安装插件 Vetur 后,输入 即会弹出基础模版提示,回车即可补全基础模版
<template> template>

<script>
export default {}; // 创建 Vue 实例,并暴露出去(使用默认暴露)
script>

<style> style>

data 必须为函数式声明

  • 当一个组件被定义,data 必须为函数式声明
    因为组件可能被用来创建多个实例。如果 data 仍然是一个纯粹的对象,则所有的实例将共享同一个数据对象!
<template> template>

<script>
export default {
    name: "componentName",
    data() {
        return { msg: "superman" };
    }
}
script>

<style lang="less" scoped> style>

scoped 属性

  • 默认情况下,组件之间的样式是共享的;后面引入的样式会覆盖前面引用的样式

  • style 标签设置了 scoped 属性,表示其 CSS 只作用于当前组件中的元素

    使用 scoped 后,父组件的样式将不会渗透到子组件中

其原理是,给当前组件的元素添加了 data-v-XXX 属性;应用样式时,也使用属性选择器,实现指定样式的应用

  • 子组件的根节点会同时受其父组件的 scoped 和子组件的 scoped 影响!!!

  • 如果希望 scoped 样式中的一个选择器可以作用得更深,可以使用 >>>

    有些预处理器无法正确解析 >>>,此时我们可以使用 /deep/ / ::v-deep 代替

<style scoped>
	.a >>> .b { /* ... */ }
style>
  • 通过 v-html 创建的 DOM 不受 scoped 样式影响,但仍能通过深度作用选择器设置其样式

一般情况下,我们不会给 App.vue 设置 scoped。因为 App.vue 是根组件,在这里设置的样式,一般都是需要全局应用的

lang="less"

lang="less" 表示使用 Less 编写样式,需要下载插件 less

<style lang="less"> /* 不设置 lang 则默认为 CSS */ style>

浏览器无法解析 less 语法,所以我们需要下载插件 less-loader 将 less 转换为 css

注意:less-loader 依赖于 webpack,需要下载对应的版本
webpack@4 → less-loader@7;webpack@5 → less-loader@8/9

我们可以查看 XXX 的所有版本:npm view XXX versions

打包

  1. 执行 npm run build:打包并生成 dist 文件夹
  2. 若使用 node.js 启动项目,只需将 dist 内的文件拷到 public 文件夹下即可
  • 当 Vue-Router 的 modehistory 时,需要下载、配置 connect-history-api-fallback,以解决路由跳转时出现的兼容问题:
    npm i connect-history-api-fallback、 ② 配置 connect-history-api-fallback
const express = require('express');
const app = express();
app.listen(3000);

// 配置 connect-history-api-fallback,否则页面刷新后无法正常显示
const history = require('connect-history-api-fallback');
app.use(history());

app.use(express.static("./public"));

你可能感兴趣的:(Vue,vue.js,javascript,node.js,ajax)