vue3+ts+vant4+pinia+axios+scss プロジェクト作成の基本的な流れ
自我记录
記事ディレクトリ
- 1. pnpmの導入&インストール&使い方(スキップ可能)
- 2. プロジェクトの作成
- 3. Vscode プラグインのインストールと eslint のプレハブ構成
- 4. ディレクトリ構造の調整とルーティングの解釈
- 5. Ponia& をインストールし、ローカル ストレージを使用する
- 6. scss をインストールする
- 7. Vant をインストールして使用する
- 8. 二次パッケージングの軸
- 9. アイコンコンポーネントにパッケージ化された SVG マップ
1. pnpmの導入&インストール&使い方(スキップ可能)
1 はじめに
本質的にはパッケージ管理ツールであり、npm/yarn と変わりません。主な利点は次のとおりです。
- パッケージのインストールは非常に高速です
- ディスクスペースの効率的な利用
- pnpm は効率的なパッケージ管理ツールであり、その使用法は基本的に npm や Yarn と同じです。
2.インストール
npm i pnpm -g
3.用途
npmコマンド | pnpm相当 |
---|---|
npmインストール | pnpmインストール |
npm i axios | pnpm 追加 axios |
npm i webpack -D | pnpm add webpack -D |
npm 実行開発 | pnpm add webpack -D |
2. プロジェクトの作成
1.create-vue
スキャフォールディングを使用してプロジェクトを作成する
create-vue 参照アドレス: https://github.com/vuejs/create-vue
2. 手順
2.1 コマンドを使用します:
pnpm create vue
# or
npm init vue@latest
# or
yarn create vue
下の写真はpnmp
デモ用です(記事と同じです)
2.2 プロジェクトの依存関係を選択します。
✔ Project name: … czbk-h5-test
✔ Add TypeScript? … No / `Yes`
✔ Add JSX Support? … `No` / Yes
✔ Add Vue Router for Single Page Application development? … No / `Yes`
✔ Add Pinia for state management? … No / `Yes`
✔ Add Vitest for Unit Testing? … `No` / Yes
✔ Add an End-to-End Testing Solution? › `No`
✔ Add ESLint for code quality? … No / `Yes`
✔ Add Prettier for code formatting? … No / `Yes`
Scaffolding project in /Users/sougewang/test/test/czbk-h5-test...
Done. Now run:
cd czbk-h5-test
pnpm install
pnpm format
pnpm dev
1. プロジェクト名
2. TS をサポートするかどうか是
3. JSX をサポートするかどうか否
4. ルーティング単一ファイル パッケージを使用するかどうか是
5. 状態管理に Pinia を使用するかどうか是
6. 単体テストが必要かどう否
か 7. エンドツー終了テストが必要かどうか否
8. ESLint 検証チェックが必要か是
どうか 9. Prettier フォーマットツールが必要かどうか是
2.3 依存関係をインストールして実行する
如下图
通常の合計は、5173
すでにウィンドウを開いているため、5174
これは無視するか、後で設定できます。
注: 以下はczbk-h5
例です。すべて同じです。スクリーンショットの作成プロセスを実行したところです5174
。czbk-h5-test
3. Vscode プラグインのインストールと eslint のプレハブ構成
1. 取り付け:extensions.json
内部に取り付ける必要があります。
Ps
: vscode がインストールされていない場合は、プロジェクトを開いたときに右下隅にインストールを求めるプロンプトが表示されます。
- Vue 言語機能 (Volar) vue3 構文のサポート
- TypeScript Vue プラグイン (Volar) vue3 のより良いヒント
- Eslint コード スタイルの検証
注意
: インストール後Prettier
、eslint
プロジェクトとの競合を避けるために無効にしてください。
了解
: 大規模および中規模のプロジェクトの場合、入力プロンプトをより適切かつ高速に表示するために、TS ホスティング モードをオンにすることをお勧めします。
2.eslintプレハブ構成
eslint のプレハブ構成を使用し、構成機能を理解します (会社ごとに異なり、個人に依存します)
共通ルールhttps://prettier.io/docs/en/options.html
.eslintrc.cjs
_の追加
/* eslint-env node */
require('@rushstack/eslint-patch/modern-module-resolution')
module.exports = {
root: true,
extends: [
'plugin:vue/vue3-essential',
'eslint:recommended',
'@vue/eslint-config-typescript',
'@vue/eslint-config-prettier/skip-formatting'
],
parserOptions: {
ecmaVersion: 'latest'
},
rules: {
'prettier/prettier': [
// 格式:单引号,没有分号,行宽度100字符,没有对象数组最后一个逗号,换行字符串自动(系统不一样换行符号不一样)
'warn',
{
singleQuote: true,
semi: false,
printWidth: 80,
trailingComma: 'none',
endOfLine: 'auto'
}
],
'vue/multi-word-component-names': [
//vue 组件需要大驼峰命名,除去 index 之外,App 是默认支持的
'warn',
{
ignores: ['index']
}
],
'vue/no-setup-props-destructure': ['off'] //允许对 props 进行解构,我们会开启解构保持响应式的语法糖
}
}
プロジェクト ファイルには多くのエラーが含まれますが、今のところは心配する必要はありません。
3. ファイル修復フォーマットの問題
コマンドを実行してすべてのファイルのフォーマットを修復したり、各ファイルを自分で保存したりすることもできます。
pnpm format
or
pnpm lint
4. ディレクトリ構造の調整とルーティングの解釈
1. ディレクトリの調整
./src
├── assets `静态资源,图片...`
├── components `通用组件`
├── composable `组合功能通用函数`
├── icons `svg图标`
├── router `路由`
│ └── index.ts
├── services `接口服务API`
├── stores `状态仓库`
├── styles `样式`
│ └── main.scss
├── types `TS类型`
├── utils `工具函数`
├── views `页面`
├── main.ts `入口文件`
└── App.vue `根组件`
対応するフォルダーを作成し、冗長なファイルを削除します。
2.ルーティングの解釈
import {
createRouter, createWebHistory } from 'vue-router'
// vue2的路由
// 1.import VueRouter from 'vue-router'
// 2.const router = new VueRouter({ routes: [ // 路由规则 ] })
// 3.选择路由模式 hash /#/user history /user
// 现在vue3的路由
// 1.创建路由实例 createRouter({ //配置对象 })
// 2.配置选项中 routes: [ // 路由规则 ]
// 3.createWebHistory 使用路由history 模式
// 4.createWebHashHistory(), //使用路由hash模式
// 5.import.meta.env.BASE_URL 路由的基准路由 create-vue 脚手架提供的环境变量 ps:在vite.config.ts 文件可以配置base: '/',
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: []
})
export default router
3. ルーティングとガードを使用する
NProgress
別の記事をお読みください.主な目的は、ページ読み込み時のプログレスバー機能の実装と、
ルートを先頭と最後に配置することと、タイトルを修正することです。
import {
useUserStore } from '@/stores'
import {
createRouter, createWebHistory } from 'vue-router'
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
{
path: '/login',
component: () => import('@/views/Login/index.vue'),
meta: {
title: '登录' }
},
{
path: '/',
redirect: '/home',
component: () => import('@/views/Layout/index.vue'),
children: [
{
path: '/home',
component: () => import('@/views/Home/index.vue'),
meta: {
title: '首页' }
},
{
path: '/user',
component: () => import('@/views/User/index.vue'),
meta: {
title: '我的' }
}
]
}
]
})
// 修改进度条插件的配置
NProgress.configure({
showSpinner: false
})
// 前置首位 访问权限控制
router.beforeEach((to) => {
// 开启页面进度条
NProgress.start()
// 用户仓库
const store = useUserStore()
// 用户白名单
const wihteList = ['/login']
// 没有token 并且 不再白名单 则跳转登录页
if (!store.user?.token && !wihteList.includes(to.path)) return '/login'
// 放行 return true 可以不用写
})
// 后置守卫
router.afterEach((to) => {
// 设置页面标题
document.title = to.meta.title || '奔跑的代码!'
NProgress.done()
})
export default router
5. Ponia& をインストールし、ローカル ストレージを使用する
詳細については、別の記事を参照してください: 20 分で Vue3+Pinia+データ永続化をすぐに始めましょう
6. scss をインストールする
プロジェクトは sass プリプロセッサを使用します。sass をインストールして scss 構文をサポートします。
pnpm add sass -D
ファイルの使用法:
<style scoped lang="scss"></style>
7. Vant をインストールして使用する
1. Vantをインストールする
# Vue 3 项目,安装最新版 Vant
npm i vant
# 通过 yarn 安装
yarn add vant
# 通过 pnpm 安装
pnpm add vant
2.グローバルでの導入と活用
src/main.ts
後で vant コンポーネント スタイルを上書きしやすくするために、グローバル スタイル ファイルを一番下に置く必要があることに注意してください。
import {
createApp } from 'vue'
import App from './App.vue'
import router from './router'
// 引入 pinia
import pinia from './stores'
// 样式全局使用
import 'vant/lib/index.css'
import './styles/main.scss'
const app = createApp(App)
// vue使用pinia插件,use(pinia的插件)
app.use(pinia)
app.use(router)
app.mount('#app')
コンポーネントはオンデマンドで手動で導入され、利用可能かどうかをテストします。
<script setup lang="ts">
// 组件按需手动引入测试是否可用
import {
Button as VanButton } from 'vant'
</script>
<template>
<van-button>按钮</van-button>
</template>
<style scoped lang="scss"></style>
3.Vant は vw を使用するモバイル端末に適応します
3.1 プラグインのインストールpostcss-px-to-viewport
npm install postcss-px-to-viewport -D
# or
yarn add -D postcss-px-to-viewport
# or
pnpm add -D postcss-px-to-viewport
3.2 プラグインの使用を設定する
czbk-h5/postcss.config.js
3.3 エラー報告の問題を解決する
3.3.1 エディターのエラー [plugin:vite:css] (エラーが報告されない場合はスキップできます)
エラー:[vite] Internal server error: Failed to load PostCSS config
解決策:postcss.config.js
ファイル名を に変更します。postcss.config.cjs
つまり、.js
ファイルのサフィックスを に変更します。.cjs
3.3.2 コンソールエラー報告 (使用には影響しません)
解決策: 無視することも、postcss-px-to-viewport-8-plugin
現在のプラグインの代わりに使用することもできます。
4. オンデマンドでコンポーネントを自動的にロードする
コンポーネントをオンデマンドで手動で使用するのは面倒なので、最初にインポートする必要があります。設定機能はオンデマンドで自動的にインポートされ、直接使用されます。公式文書
4.1 インストール
# 通过 npm 安装
npm i unplugin-vue-components -D
# 通过 yarn 安装
yarn add unplugin-vue-components -D
# 通过 pnpm 安装
pnpm add unplugin-vue-components -D
4.2 構成
vite.config.ts
import {
fileURLToPath, URL } from 'node:url'
import {
defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
// 引入按需导入插件
import Components from 'unplugin-vue-components/vite'
// 各种组件库的解析器 //里面还有 ElementUiResolver,ElementPlusResolverOptions,AntDesignVueResolver等常见的组件库
import {
VantResolver } from 'unplugin-vue-components/resolvers'
// https://vitejs.dev/config/
export default defineConfig({
// 默认'/' 是基准地址
base: '/',
plugins: [
// 解析单文件组件的插件
vue(),
//使用按需导入插件 默认自动加载 components 下的组件,通用级别组件.
Components({
// 默认是true 开启自动生成组件的类型声明文件,vant的组件已经有类型声明文件,只要导入了就会使用类型声明.
dts: false,
// 在main.ts 已经引入了所有的组件样式,不需要自动导入样式,只需要自动导入组件即可
resolvers: [VantResolver({
importStyle: false })]
})
],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
}
}
})
ご利用の際は導入の必要はございません。
<script setup lang="ts"></script>
<template>
<van-button>按钮</van-button>
</template>
<style scoped lang="scss"></style>
5. CSS変数を使用してテーマをカスタマイズする
src/App.vue
デフォルトのスタイル
CSS 変数を使用してプロジェクトのテーマをカスタマイズし、vant テーマの公式ドキュメントを変更します
src/styles/main.scss
// 项目共用的样式文件
:root {
--cz-primary: #16C2A3;
--cz-text1: red;
--cz-text2: pink;
// 覆盖vant主体色
--van-primary-color: var(--cz-primary);
}
src/App.vue
使用
<script setup lang="ts">
import {
Button as VanButton } from 'vant'
</script>
<template>
<!-- 验证vant颜色被覆盖 -->
<van-button type="primary">按钮</van-button>
<a href="#">测试</a>
</template>
<style scoped lang="scss">
// 使用css全局变量
a {
color: var(--cz-text1);
}
</style>
效果
6. パブリック タイトルを実装するための NavBar コンポーネントの二次カプセル化
6.1 レイアウトと機能と使い方
src/components/CpNavBar.vue
<script setup lang="ts">
import {
useRouter } from 'vue-router'
// 拿路由实例
const router = useRouter()
const props = defineProps<{
title?: string
rightText?: string
back?: () => void
}>()
const emit = defineEmits<{
(e: 'click-right'): void }>()
const onClickLeft = () => {
// 扩展 back 属性,如果有就执行 back 对应的函数。
// 给全屏弹出层使用
if (props.back) {
return props.back()
}
// TODO 点击左侧返回按钮
// 实现返回 如果有当前网站的上一次历史记录 就执行back返回
// 没有历史记录则跳转到 首页
if (history.state?.back) {
router.back()
} else {
router.push('/home')// 为了测试功能时否正常 后续需要换成 '/'
}
}
const onClickRight = () => {
// TODO 点击右侧文字按钮
emit('click-right')
}
</script>
<template>
<van-nav-bar
left-arrow
fixed
:title="title"
:right-text="rightText"
@click-left="onClickLeft"
@click-right="onClickRight"
/>
</template>
<style lang="scss" scoped>
:deep() {
.van-nav-bar {
&__arrow {
font-size: 18px;
color: var(--cz-text1);
}
&__text {
font-size: 15px;
}
}
}
</style
コンポーネントを
src/views/Login/index.vue
導入せずに利用できるのは、内部の設定項目のコメントを確認できるためです。<Cp-nav-bar />
4. 自动按需加载组件
<script setup lang="ts">
const fn = () => {
console.log('点击了右侧')
}
</script>
<template>
<div class="login-page">
<cp-nav-bar title="登录" right-text="注册" @click-right="fn" />
</div>
</template>
<style lang="scss" scoped>
.login {
&-page {
padding-top: 46px;
}
}
</style>
效果
6.2 コンポーネントクラスをセカンダリカプセル化コンポーネントに追加する
プロパティやイベントを書くときにプロンプトが出るようにコンポーネントに型を追加する(TSが識別できる) これもVantコンポーネントを模倣したソースコードの書き方です。
src/types/components.d.ts
// 给components 下的全局组件设置类型
// 1. 导入组件实例
import CpNavBar from '@/components/CpNavBar.vue'
// 2. 声明 vue 类型模块
declare module 'vue' {
// 3. 给 vue 添加全局组件类型,interface 和之前的合并
interface GlobalComponents {
// 指定组件类型,typeof(从一个JS对象中得到他对应的TS类型) 从组件对象得到类型,设置给全局组件 CpNavBar
CpNavBar: typeof CpNavBar
}
}
8. 二次パッケージングの軸
1. axios のインストールと設定
npm install axios
or
yarn add axios
or
pnpm add axios
src/utils/rquest.ts
// 二次封装axios
import router from '@/router'
import {
useUserStore } from '@/stores'
import axios, {
type Method } from 'axios'
import {
showToast } from 'vant'
// 1. axios的配置
// 1.1 创建一个新的axios实例,配置基准地址,配置响应超时时间
// 1.2 添加请求拦截器,在请求头携带token
// 1.3 添加响应拦截器,判断业务是否成功,剥离无效的数据,401错误拦截去登录页面(删除当前用户信息),
const baseURL = 'xxxxxxxxx'
const instance = axios.create({
baseURL,
timeout: 10000
})
// 请求拦截器
instance.interceptors.request.use(
(config) => {
// 修改config,比如:修改请求头
// 获取token===>就是获取user
const store = useUserStore()
if (store.user?.token && config.headers) {
config.headers.Authorization = `Bearer ${
store.user.token}`
}
return config
},
(err) => Promise.reject(err)
)
// 响应拦截器
// 将来 axios.get()
// .then(res=>{ // res 就是后台的数据,之前的res.data })
// .catch(e=>{ // 200+10001这种情况,e就是res.data , 如果是状态吗的错误 401 403 404 e 就错误对象 })
instance.interceptors.response.use(
(res) => {
// status 是200是响应成功的,res.data.code 是10000业务成功
// 如果不是 10000 呢,使用 vant 的轻提示,报错阻断程序
if (res.data.code !== 10000) {
showToast(res.data.message || '网络异常')
return Promise.reject(res.data)
}
// 剥离无效数据
return res.data
},
// 401处理
(err) => {
// 请求报错,响应出错
// 遇见401跳转登录
// 1. 现在在 /user/patient 页面下,发起一个获取用户信息的请求,但是此时token失效
// 2. 跳转登录页面,登录成功之后,需要跳转回 /user/patient 页面 (默认跳转 /user 首页)
// vue2 $router 路由实例,提供路由相关函数操作 $route 路由相关信息,query params path 。。。
if (err.response.status === 401) {
// 需要删除用户信息
const store = useUserStore()
store.delUser()
// /user/patient?id=1000
// path /user/patient 不带查询参数
// fullPath /user/patient?id=1000 完整路径
// currentRoute 是一个 ref 创建的数据,需要.value
router.push(`/login?returnUrl=${
router.currentRoute.value.fullPath}`)
}
return Promise.reject(err)
}
)
// obj = { name: 'jack', age: 100 } obj['name'] ===> const name = 'name' obj[name]
// 2. 请求工具函数
// 2.1 参数:url method submitData
// 2.2 返回:instance 调用接口的promise对象
// const request = (url: string, method: string, submitData?: object) => {
// return instance.request({
// url,
// method,
// // 区分get和其他请求post
// // get 提交数据,选项:params
// // 其他请求post 提交数据,选项:data
// [method.toLowerCase() === 'get' ? 'params' : 'data']: submitData
// })
// }
// res响应数据类型
type Data<T> = {
code: string
message: string
data: T
}
const request = <T>(
url: string,
method: Method = 'get', // 默认是get
submitData?: object // 可以不传
) => {
// 泛型的第二个参数,可以自定义响应数据类型
return instance.request<T, Data<T>>({
url,
method,
// 区分get和其他请求post
// get 提交数据,选项:params
// 其他请求post 提交数据,选项:data // toLowerCase 将字符串转换为小写字母
[method.toLowerCase() === 'get' ? 'params' : 'data']: submitData
})
}
// baseURL 基准地址
// instance 是配置好的axios
// request 用来调用接口
export {
baseURL, instance, request }
簡単な使用テストsrc/App.vue
<script setup lang="ts">
import {
useUserStore } from './stores'
import type {
User } from './types/user'
import {
request } from './utils/rquest'
const store = useUserStore()
const login = () => {
// 接口地址(去除基准路径之后的地址), 请求方式 , 请求参数
request<User>('login/password', 'POST', {
mobile: '12345678900',
password: '111111'
})
.then((res) => {
// 存储到本地
store.setUser(res.data)
})
.catch((e) => {
// 异常捕获
console.log(e)
})
}
</script>
<template>
<van-button type="primary" @click="login">登录</van-button>
</template>
9. アイコンコンポーネントにパッケージ化された SVG マップ
実装: アイコン ファイルに従って svg イメージをプロジェクトにパックし、コンポーネントを通じてアイコンを使用します。
1.インストールと設定
参考ドキュメント:https://github.com/vbenjs/vite-plugin-svg-icons
icons ファイルパッケージ化された製品ですか?すべてのアイコンを含む svg 構造 (js によって作成) が生成され、次のように理解されます。精灵图
安装
yarn add vite-plugin-svg-icons -D
# or
npm i vite-plugin-svg-icons -D
# or
pnpm install vite-plugin-svg-icons -D
パッケージ化された SVG アイコンを構成するvite.congfig.ts
import {
fileURLToPath, URL } from 'node:url'
import {
defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
// 引入按需导入插件
import Components from 'unplugin-vue-components/vite'
// 各种组件库的解析器 //里面还有 ElementUiResolver,ElementPlusResolverOptions,AntDesignVueResolver 等常见的组件库
import {
VantResolver } from 'unplugin-vue-components/resolvers'
// 配置svg精灵图插件
+import {
createSvgIconsPlugin } from 'vite-plugin-svg-icons'
+import path from 'path'
// https://vitejs.dev/config/
export default defineConfig({
// 默认'/' 是基准地址
base: '/',
plugins: [
// 解析单文件组件的插件
vue(),
//使用按需导入插件 默认自动加载 components 下的组件,通用级别组件.
Components({
// 默认是true 开启自动生成组件的类型声明文件,vant的组件已经有类型声明文件,只要导入了就会使用类型声明.
dts: false,
// 在main.ts 已经引入了所有的组件样式,不需要自动导入样式,只需要自动导入组件即可
resolvers: [VantResolver({
importStyle: false })]
}),
+ // 打包svg图标目录
+ createSvgIconsPlugin({
+ // 指定需要缓存的图标文件夹 (打包指定svg图标的目录) //路径转换为绝对路径
+ iconDirs: [path.resolve(process.cwd(), 'src/icons')]
+ })
],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
}
}
})
src/main.ts
引用で
import {
createApp } from 'vue'
import App from './App.vue'
import router from './router'
// 引入 pinia
import pinia from './stores'
// 使用svg精灵图
+import 'virtual:svg-icons-register'
// 样式全局使用
import 'vant/lib/index.css'
import './styles/main.scss'
const app = createApp(App)
// vue使用pinia插件,use(pinia的插件)
app.use(pinia)
app.use(router)
app.mount('#app')
2.使いやすい
存在するsrc/views/Login/index.vue
例: src/icons/user/add.svg
'icon-[dir]-[name]'
#
は固定されており、icon-
先頭、dir
アイコンが配置されているディレクトリ、name
およびアイコンの名前が固定されています。
<script setup lang="ts">
const fn = () => {
console.log('点击了右侧')
}
</script>
<template>
<div class="login-page">
<cp-nav-bar title="登录" right-text="注册" @click-right="fn" />
<!-- 测试svg -->
<svg aria-hidden="true">
<!-- src/icons/user/add.svg -->
<!-- 'icon-[dir]-[name]' # 是固定的 icon- 固定开头 dir 图标所在目录 name 图标的名称 -->
<use href="#icon-user-add" />
</svg>
</div>
</template>
<style lang="scss" scoped>
.login {
&-page {
padding-top: 46px;
}
}
</style>
效果
3. SVG コンポーネントをカプセル化して使用する
作成するsrc/components/CpIcon.vue
<script setup lang="ts">
// 提供一个props 属性 确定使用哪个图标 使用的规则: 文件夹名称+图片名称 user-add
defineProps<{
name: string }>()
</script>
<template>
<svg aria-hidden="true" class="cp-icon">
<!-- src/icons/user/add.svg -->
<!-- 'icon-[dir]-[name]' # 是固定的 icon- 固定开头 dir 图标所在目录 name 图标的名称 #icon-user-add -->
<use :href="`#icon-${name}`" />
</svg>
</template>
<style lang="scss" scoped>
.cp-icon {
// 通过font-size 控制图片的大小(和字体一样大)
width: 1em;
height: 1em;
}
</style>
タイプを定義するsrc/types/components.d.ts
// 给components 下的全局组件设置类型
// 1. 导入组件实例
import CpNavBar from '@/components/CpNavBar.vue'
+import CpIcon from '@/components/CpIcon.vue'
// 2. 声明 vue 类型模块
declare module 'vue' {
// 3. 给 vue 添加全局组件类型,interface 和之前的合并
interface GlobalComponents {
// 指定组件类型,typeof(从一个JS对象中得到他对应的TS类型) 从组件对象得到类型,设置给全局组件 CpNavBar
CpNavBar: typeof CpNavBar
+ CpIcon: typeof CpIcon
}
}
使用src/views/Login/index.vue
<script setup lang="ts">
const fn = () => {
console.log('点击了右侧')
}
</script>
<template>
<div class="login-page">
<cp-nav-bar title="登录" right-text="注册" @click-right="fn" />
<cp-icon name="user-add" />
<div style="font-size: 40px; color: red">
<cp-icon name="user-add" />
</div>
</div>
</template>
<style lang="scss" scoped>
.login {
&-page {
padding-top: 46px;
}
}
</style>
效果
アイコンによっては、スタイルの色の値に応じて色を設定できるものもありますが、この機能があるかどうかは、画像作成時にUIがオンになっているかどうかによって異なります。
今後も更新していきます!