Vite を使用して Vue3+TS プロジェクトを作成し、Element Plus フレームワークやその他のワンストップ サービスを統合します

Vite を使用して Vue3+TS プロジェクトを作成し、Element Plus フレームワークや、Less、Ponia、Vue-router、monaco-editor などのプラグインやコンポーネントを統合するための使用方法を記録します。

1. Vite を使用して Vue3+TS プロジェクトを作成する

ステップ 1: デスクトップに新しい一時フォルダーを作成し、それを VS Code で開き、ターミナルを開きます。

ステップ 2: Vite プロジェクトを作成する

npm create vite@latest

(1) 输入项目名,如: vue3_vite_ts_less_element_plus ,然后回车
? Project name: » vue3_vite_ts_less_element_plus

(2) 选择 Vue 框架,回车
? Select a framework: » - Use arrow-keys. Return to submit.
    Vanilla
>   Vue
    React
    Preact
    Lit
    Svelte
    Others

(3) 选择数据类型,回车
? Select a variant: » - Use arrow-keys. Return to submit.
    JavaScript
>   TypeScript
    Customize with create-vue ↗
    Nuxt ↗

(4) 创建完成,运行项目
Done. Now run: 

  cd vue3_vite_ts_less_element_plus
  npm install
  npm run dev

PS C:\Users\Administrator\Desktop\temp> 

2. @ エイリアスを設定する

ステップ 1: vite.config.ts 構成ファイルを変更する

修正する前に:

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
})

変更後:

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { resolve } from 'path'

/**
 * 详情见 vitejs 文档:https://vitejs.dev/config/
 */
export default defineConfig({
  plugins: [vue()],
  resolve: {
    alias: {
      '@': resolve(__dirname, './src')
    }
  }
})

ステップ 2: tsconfig.json 構成ファイルを変更する

修正する前に:

{
  "compilerOptions": {
    "target": "ESNext",
    "useDefineForClassFields": true,
    "module": "ESNext",
    "moduleResolution": "Node",
    "strict": true,
    "jsx": "preserve",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "esModuleInterop": true,
    "lib": ["ESNext", "DOM"],
    "skipLibCheck": true,
    "noEmit": true
  },
  "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
  "references": [{ "path": "./tsconfig.node.json" }]
}

変更後:

{
  "compilerOptions": {
    "target": "ESNext",
    "useDefineForClassFields": true,
    "module": "ESNext",
    "moduleResolution": "Node",
    "strict": true,
    "jsx": "preserve",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "esModuleInterop": true,
    "lib": ["ESNext", "DOM"],
    "skipLibCheck": true,
    "noEmit": true,
    "paths": {
      "@": ["src"],
      "@/*": ["src/*"]
    }
  },
  "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
  "references": [{ "path": "./tsconfig.node.json" }]
}

ステップ 3: 設定は成功しました。

3. Element Plus フレームワークを統合する

ステップ 1: 依存パッケージをインポートする

npm i element-plus

ステップ 2: プロジェクトの src ディレクトリに plugins フォルダーを作成し、その中に新しい element-plus.ts ファイルを作成し、次のコードを記述します

import ElementPlus from 'element-plus'
import 'element-plus/theme-chalk/index.css'
import zhCn from 'element-plus/es/locale/lang/zh-cn' // 汉化 element-plus 组件
 
export default (app: any) => {
  app.use(ElementPlus, {
    locale: zhCn,
  })
}

ステップ 3: プロジェクトの main.ts フォルダーにあるプラグインと登録アイコンをインポートして使用します。つまり、統合は完了し、main.ts ファイルは次のようになります。

import { createApp } from 'vue'
import App from './App.vue'
import './global.less' // 全局样式

const app = createApp(App)

// 引入 ElementPlus 插件(npm i element-plus)
import ElementPlusPlugin from '@/plugins/element-plus'

// 全局注册 ElementPlus 图标组件(npm i @element-plus/icons-vue)
import * as ElementPlusIcons from '@element-plus/icons-vue'
for(const [key, component] of Object.entries(ElementPlusIcons)) {
  app.component(key, component)
}

app
.use(ElementPlusPlugin)
.mount('#app')

ステップ 4: 統合が成功したことを確認します。たとえば、プロジェクトの App.vue フォルダーにボタンのラベルを作成して保存し、効果を確認します。App.vue ファイルは次のとおりです。

<template>
  <el-button
    size="small"
    type="primary"
    icon="UploadFilled"
    @click="void(0)"
  >
    点击事件
  </el-button>
   
  <el-button size="small" type="primary" plain @click="void(0)">
    <el-icon :size="18">
      <UploadFilled />
    </el-icon>
    <span>点击事件</span>
  </el-button>
   
  <el-button
    size="small"
    type="primary"
    circle
  >
    <el-icon :size="18">
      <UploadFilled />
    </el-icon>
  </el-button>
   
  <el-icon
    :size="20"
    style="color: #5e7ce0; cursor: pointer"
    @click="void(0)"
  >
    <UploadFilled />
  </el-icon>
</template>
 
<style lang="less">
  * {
    margin: 0;
    padding: 0;
  }
 
  html, body {
    width: 100%;
    height: 100%;
    margin: 0;
    padding: 0;
    border: none;
  }
 
  #app {
    width: 100%;
    height: 100%;
    font-family: Avenir, Helvetica, Arial, sans-serif;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-align: center;
  }
</style>

4. vue-router、pinia、less などのプラグインを統合する

ステップ 1: vue-router のすべてのバージョンを表示し、インストールする新しいバージョンを指定します。使用方法は以前と同じです。

npm view vue-router versions --json
npm i [email protected]

ステップ 2: pinia をインストールする. Vuex は Pinia ほど良くない ts を採用していると聞きました. 詳細は公式 Web サイト ( Pinia 中国語ドキュメント) を参照してください

npm i pinia

srcディレクトリにストアフォルダを新規作成し、index.tsファイルを新規作成します。

import { createPinia } from 'pinia'
const store = createPinia()
export default store

次に、新しい ILoveYouStore ファイルを作成します。ファイルの内容は次のとおりです。

import { defineStore } from 'pinia'

/**
 * 爱老虎油状态管理仓库
 */
export const ILoveYouStore = defineStore({
  id: 'ILoveYouStore', // ID必填且唯一
  state: () => {
    return {
      xxx: 'Hello,World!',
      yyy: 520,
    }
  },
  getters: {

  },
  actions: {
    setXxx(xxx: string) {
      this.xxx = xxx
    },
  }
})

 以下は、vue ページで Pinia を使用する方法です。

<script>
// 引入爱老虎油状态管理仓库
import { ILoveYouStore } from '@/store/ILoveYouStore'
const useILoveYouStore = ILoveYouStore()
</script>

然后随便用Vue2、Vue3、Vue3+语法糖来定义数据
<!-- ^ Vue2 -->
<template>
  <div v-if="useILoveYouStore.$state.xxx != null">{
   
   { useILoveYouStore.$state.xxx }}</div>
  <div v-else>{
   
   { useILoveYouStore.$state }}</div>
</template>

<script>
export default {
  data: () => ({
    useILoveYouStore: useILoveYouStore,
  }),
}
</script>
<!-- / Vue2 -->

<!-- ^ Vue3 -->
<script>
import { ref } from 'vue';
export default {
  setup() {
    const useILoveYouStore = useILoveYouStore

    return { useILoveYouStore }
  },
}
</script>
<!-- / Vue3 -->

<!-- ^ Vue3+语法糖 -->
<script setup>
  const useILoveYouStore = useILoveYouStore
</script>
<!-- / Vue3+语法糖 -->

ステップ 3: 個人のインストール習慣に応じて、less/scss をインストールする

npm i less
npm i scss

4 番目のステップである他のプラグインの統合も同様で、別のパッケージで Axios プラグインが使用されます。

Vue Cli を使用して Vue3+TS プロジェクトを作成し、Element Plus フレームワークを統合し、Axios プラグインをパッケージ化する - Shuailongzhilong のブログ - CSDN ブログ

5. Microsoft のオンライン コード エディターの monaco-editor プラグインを統合します。このプラグインは簡単に実装できます。オンラインでの 1 ページの閲覧だけで 300,000 行のコードまたはログを超える場合があり、強調表示されたテキストを取得することなく迅速にレンダリングする機能を提供します。立ち往生

ステップ 1: monaco エディターのバージョンを表示する

npm view monaco-editor versions --json

ステップ 2: 指定されたバージョンの monaco-editor をインストールする

npm i [email protected]

ステップ 3: App.vue を次のコードに変更します。

<template>
  <div class="m-e" id="m-e-id">
    <div class="m-e-main">
      <div class="m-e-main_toolbar" :style="isThemeLightOrBlack ? 'background-color: #fff; box-shadow: 0px 2px 5px #ddd;' : 'background-color: #1e1e1e; box-shadow: 0px 2px 5px #111;'">
        <div class="m-e-main_toolbar_left">
          <span>日志 - {
   
   { title }}</span>
        </div>
        
        <div class="m-e-main_toolbar_right" :style="isThemeLightOrBlack ? 'color: #000' : 'color: #fff'">
          <a title="查找" @click="findByKeyword"><i class="fa fa-search"/></a>
          <a title="回到顶部" @click="scrollToTop"><i class="fa fa-chevron-circle-up"/></a>
          <a title="回到底部" @click="scrollToBottom"><i class="fa fa-chevron-circle-down"/></a>
          <a title="是否截断换行" @click="setEditorWordWrap"><i class="fa fa-bars"/></a>
          <a title="切换白天或暗夜模式" @click="setEditorTheme"><i class="fa fa-adjust"/></a>
          <a :title="fullScreen ? '退出全屏' : '全屏显示'" @click="handleFullScreenClick"><i :class="fullScreen ? 'fa fa-compress' : 'fa fa-expand'"/></a>
          <a title="下载日志" @click="handleDownloadLogClick"><i class="fa fa-cloud-download" style="position: relative; top: 0px"/></a>
        </div>
      </div>
      <div :id="id" class="m-e-main_container" :style="'height: calc(100% - 40px)'"></div>
    </div>
  </div>
</template>

<script>
// 引入获取原始数据组件
import { toRaw } from 'vue'

// 引用 font-awesome 资源(npm i font-awesome)
import 'font-awesome/css/font-awesome.min.css';

// 引入 monaco-editor 组件
import * as me from 'monaco-editor'

export default {
  data: () => ({
    editor: null,// 编辑器对象
    id: null,// 编辑器DOM节点ID
    title: '',// 编辑器标题
    content: '',// 编辑器内容
    height: 'auto',// 编辑器高度
    readOnly: false,// 编辑器是否禁用
    isScrollToBottom: false, // 是否滚动到底部

    // 其他配置项...
    fullScreen: false,// 是否全屏状态
    wordWrap: false,// 当单行文本太长时截断换行,true 为换行,false 为不换行
    isThemeLightOrBlack: false,// 明亮或暗夜模式,true 为白天模式,false 为暗夜模式
    
  }),
  mounted() {
    this.newME()

    /**
     * 监听全屏显示状态
     */
    let that = this;
    window.onresize = function() {
      if (!document.fullscreenElement) {
        that.fullScreen = false;
      } else {
        that.fullScreen = true;
      } 
    }
  },
  watch: {

  },
  methods: {
    /** */
    newME() {
      this.id = 'me_czq' // 随便起一个DOM节点ID名称
      this.title = '帅龍之龍' // 随便起一个编辑器标题
      this.content = 'Hello,World!' // 随便写入一点编辑器内容
      this.initMonacoEditor(this.id, this.content, this.readOnly)
    },

    /**
     * 实例化在线代码编辑器
     * 
     * 文档地址:https://microsoft.github.io/monaco-editor/api/index.html
     */
    async initMonacoEditor(id, content, readOnly) {
      try {
        // 异步获取节点,确保 Dom 节点已经渲染完成,不可删
        await document.getElementById(this.id);
        this.editor = me.editor.create(document.getElementById(id), {
          value: content,// 编辑器内容
          language: 'python',// 选择支持语言
          automaticLayout: true,// 是否自动布局
          theme: 'vs-dark',// 官方自带三种主题:vs、hc-black、vs-dark
          readOnly: readOnly,// 设置是否只读
          wordWrap: this.wordWrap ? 'on' : 'off',// 设置启用截断功能
          scrollBeyondLastLine: false,// 滚动完最后一行后再滚动一屏幕

          // 滚动条
          // scrollbar: {
          //   verticalScrollbarSize: 15,
          //   horizontalScrollbarSize: 15
          // },

          // 是否开启小地图
          minimap: {
            enabled: true
          },
        });
      } catch (e) {
        console.error(e)
      }
      

      // 设置编辑器滚动到最底部
      // this.scrollToBottom();
    },

    /**
     * 设置编辑器的内容且滚动到最底部
     */
    setEditorContent(val) {
      toRaw(this.editor).setValue(val);
      this.scrollToBottom();
    },

    /**
     * 获取编辑器的内容
     */
    getEditorContent() {
      toRaw(this.editor).getValue();
    },

    /**
     * 打开编辑器查找功能
     */
    findByKeyword() {
      try {
        // 先聚焦编辑器
        toRaw(this.editor).focus();

        // 从模型中获取要查找的字符串范围 new Range(startLineNumber, startColumn, endLineNumber, endColumn)
        toRaw(this.editor).setSelection(new me.Range(1, 9999, 1, 10000));

        // 触发查找操作
        // toRaw(this.editor).getAction('actions.find').run();// 查找方式一
        toRaw(this.editor).trigger('', 'actions.find');// 查找方式二
      } catch(error) {
        console.log(error);
      }
    },

    /**
     * 设置编辑器从只读变成可写
     */
    setEditorRW() {
      toRaw(this.editor).updateOptions({readOnly: false});
    },

    /**
     * 设置编辑器开关截断功能
     */
    setEditorWordWrap() {
      this.wordWrap = this.wordWrap ? false : true;
      if (this.wordWrap) {
        toRaw(this.editor).updateOptions({wordWrap: 'on'});
      } else {
        toRaw(this.editor).updateOptions({wordWrap: 'off'});
      }
    },

    /**
     * 设置编辑器明亮或暗夜模式
     */
    setEditorTheme() {
      this.isThemeLightOrBlack = this.isThemeLightOrBlack ? false : true;
      if (this.isThemeLightOrBlack) {
        toRaw(this.editor).updateOptions({theme: 'vs'});
      } else {
        toRaw(this.editor).updateOptions({theme: 'vs-dark'});
      }
    },

    /**
     * 设置编辑器滚动到最顶部
     */
    scrollToTop() {
      toRaw(this.editor).setScrollPosition({scrollTop: 0});
    },

    /**
     * 设置编辑器滚动到最底部
     */
    scrollToBottom() {
      toRaw(this.editor).revealLine(toRaw(this.editor).getModel().getLineCount());
    },

    /**
     * 全屏显示句柄
     */
    handleFullScreenClick () {
			const element = document.getElementById('m-e-id');
      if (!document.fullscreenElement) {
        element.requestFullscreen();
      } else {
        document.exitFullscreen();
      } 
    },

    /**
     * 下载日志句柄
     */
    handleDownloadLogClick() {
      this.exportFile(this.title, this.content);
    },

    /**
     * 下载日志
     */
    exportFile(name, data) {
      let url = window.URL || window.webkitURL || window;
      let blob = new Blob([data]);
      let event = document.createEvent("MouseEvents");
      event.initMouseEvent("click", true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
      let link = document.createElementNS("http://www.w3.org/1999/xhtml", "a");
      link.href = url.createObjectURL(blob);
      link.download = name;
      link.dispatchEvent(event);
    }
  },
  /**
   * 销毁在线代码编辑器
   */
  beforeDestroy() {
    if (toRaw(this.editor)) {
      toRaw(this.editor).dispose()
    }
  },
}
</script>
 
<style lang="less" scoped>
  .m-e {
    width: 100%;
    height: 100%;

    .m-e-main {
      width: 100%;
      height: 100%;

      .m-e-main_toolbar {
        width: 100%;
        height: 40px;
        box-shadow: 0px 2px 5px #000;
        display: flex;
        position: relative;
        z-index: 99;
    
        .m-e-main_toolbar_left {
          flex: 1;
          overflow: hidden;
    
          span {
            color: #fff;
            display: block;
            font-size: 15px;
            padding-left: 10px;
            line-height: 26px;
            line-height: 40px;
            white-space:nowrap;/* 不换行 */
            overflow:hidden;/* 内容超出宽度时隐藏超出部分的内容 */
            text-overflow:ellipsis;/* 当对象内文本溢出时显示省略标记(...) ;需与overflow:hidden;一起使用。*/
            // user-select: none;
          }
        }
    
        .m-e-main_toolbar_right {
          margin-right: 15px;
          display: flex;
    
          a {
            width: 16px;
            height: 16px;
            line-height: 16px;
            transition: ease all 0.3s ;
            text-align: center;
            display: inline-block;
            padding: 5px;
            cursor: pointer;
            border-radius: 2px;
            margin: 7px 0 7px 5px;
    
            i {
              font-size: 15px;
            }
    
            &:hover {
              background-color: rgba(255, 255, 255, 0.1);
            }
          }
        }
      }
    }
  }
</style>

6. サーバーインターフェイスアドレスを設定します。

ステップ 1: サーバー構成を vite.config.ts ファイルに追加します。完全な内容は次のとおりです。

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { resolve } from 'path'

/**
 * 详情见 vitejs 文档:https://vitejs.dev/config/
 */
export default defineConfig({
  plugins: [vue()],
  base: '/xxx/', // 配置相对地址或绝对地址,此处应为绝对地址,若将 Web 部署到 Nginx 所在的目录为 nginx-1.17.8/html/xxx ,则这个 base 的值就为 /xxx/
  resolve: {
    alias: {
      '@': resolve(__dirname, './src'),
      assets: resolve(__dirname, './src/assets'),
    }
  },
  server: {
    host: '', // 主机
    port: 5173, // 端口
    proxy: {
      // 项目 v1 的服务端接口地址
      '/v1/api': {
        target: 'http://127.0.0.1:8091/',
        changeOrigin: true,
        secure: false,
        ws: true
      },

      // 项目 v2 的服务端接口地址
      '/v2/api': {
        target: 'http://127.0.0.1:8092/',
        changeOrigin: true,
        secure: false,
        ws: true
      },

      // 项目 v3 的服务端接口地址
      '/v3/api': {
        target: 'http://127.0.0.1:8093/',
        changeOrigin: true,
        secure: false,
        ws: true
      },

      // // 默认服务端接口地址
      // '/': {
      //   target: 'http://127.0.0.1:8090/',
      //   changeOrigin: true,
      //   secure: false,
      //   ws: false
      // }
    }
  }
})

ヒント: vite のバージョンを下げるにはどうすればよいですか?

ステップ1: プロジェクト内のnode_modulesディレクトリを削除します。

ステップ 2: プロジェクト内の package-lock.json ファイルを削除する

ステップ 3: 指定されたバージョンの vite をインストールする

npm i [email protected] -D

ステップ 4: 指定されたバージョンの @vitejs/plugin-vue をインストールする

npm i @vitejs/[email protected] -D

ステップ 5: import dependency コマンドを再実行します。vite バージョン エラーが 2 つある場合は、ステップ 1 とステップ 2 を繰り返して、依存関係を再インポートします。

npm i

ステップ 6: プロジェクトを開始して通常どおり実行する

npm run dev

エラー報告の問題の概要

問題 1: 名前「__dirname」が見つかりませんでした。

理由: path モジュールは、node.js の組み込みモジュールであり、node.js はデフォルトでは ts ファイルをサポートしません。

解決策: @type/node 依存関係パッケージをインストールします。 npm install @types/node --save-dev

vue3+vite+ts が @ を構成すると、vscode は __dirname が見つからないと報告します_vite __dirname_yuhaiyang11 のブログ - CSDN ブログ

問題 2: 「baseUrl」が設定されていない場合、非相対パスは許可されません。先頭の「./」を忘れていませんか?

解決策: tsconfig.json ファイルに BaseUrl 構成を追加します。

{
  "compilerOptions": {
    ...
    "baseUrl": ".",    // 未设置 "baseUrl" 时,不允许使用非相对路径。
    "paths": {
      "@": ["src"],
      "@/*": ["src/*"]
    }
  },
  ...
}

問題 3: モジュール './App.vue' またはそれに対応する型宣言が見つかりませんでした。

解決策: src ディレクトリに新しい shims-vue.d.ts ファイルを作成します。ファイルの内容は次のコードです。

/* eslint-disable */
declare module '*.vue' {
  import type { DefineComponent } from 'vue'
  const component: DefineComponent<{}, {}, any>
  export default component
}

質問 4: Vite プロジェクトの相対アドレスまたは絶対アドレスを設定する方法

解決策: vite.config.ts ファイルに Base 属性を追加します。値は相対アドレス './' または絶対アドレス '/xxx/' にすることができます。

export default defineConfig({
  plugins: [vue()],
  base: '/xxx/', // 配置相对地址或绝对地址,此处应为绝对地址,若将 Web 部署到 Nginx 所在的目录为 nginx-1.17.8/html/xxx ,则这个 base 的值就为 /xxx/
  resolve: {
    alias: {
      '@': resolve(__dirname, './src'),
      assets: resolve(__dirname, './src/assets'),
    }
  },
})

質問 5: npm run build がパッケージ化されると、エラーが報告され、「'allowJs' オプションを有効にするつもりですか?」というプロンプト メッセージが表示されます。

解決策: tsconfig.json ファイルにallowJs構成を追加します。

{
  "compilerOptions": {
    "allowJs": true, // xxx.vue is a JavaScript file. Did you mean to enable the 'allowJs' option?
    // ...
  }
}

質問 6: プロジェクトでは ESlint パーサーが指定されていないため、いくつかの構文解析エラーが発生します。

解決策: 新しい .eslintrc.js ファイルを作成し、ファイル名の先頭のドットに注意すると、完全に解決されます。

module.exports = {
  env: {
    browser: true,
    es2022: true,
    node: true,
  },
  extends: ["plugin:vue/vue3-recommended", "plugin:prettier/recommended"],
  parserOptions: {
    ecmaVersion: "latest",
    parser: "@typescript-eslint/parser", // 指定ESlint的解析器
    sourceType: "module",
  },
  plugins: ["vue", "@typescript-eslint", "prettier"],
  rules: {
    "prettier/prettier": "error",
  },
}

问题七: >>> および /deep/ コンビネータは非推奨になりました。代わりに:deep() を使用してください。

解決策: /deep/ を deep() に置き換えます。

修改前:
/deep/ .el-table {
  // ...
}

修改后:
:deep(.el-table) {
  // ...
}

プロジェクトアドレス

vue3_vite_ts_less_element_plus: これは、学習参照のみを目的として、TS+Less+Element Plus+Pinia+iconic およびその他のフレームワークまたはプラグインのサンプル プロジェクトを統合する Vite+Vue3 によって構築されたプロジェクトです。

おすすめ

転載: blog.csdn.net/Cai181191/article/details/129269078