create-vite-vue 1.3.1 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/index.js +150 -52
- package/package.json +1 -1
- package/template/base-js/README.md +32 -19
- package/template/base-js/package.json.tpl +2 -2
- package/template/base-ts/README.md +32 -19
- package/template/base-ts/package.json.tpl +2 -2
- package/template/router-js/src/App.vue +3 -0
- package/template/router-js/src/router/index.js +1 -1
- package/template/router-ts/src/App.vue +3 -0
- package/template/router-ts/src/router/index.ts +1 -1
- /package/template/router-js/src/views/{Home.vue → home/index.vue} +0 -0
- /package/template/router-ts/src/views/{Home.vue → home/index.vue} +0 -0
package/bin/index.js
CHANGED
|
@@ -11,7 +11,7 @@ const __dirname = path.dirname(__filename)
|
|
|
11
11
|
; (async () => {
|
|
12
12
|
// 1️⃣ 输入项目名
|
|
13
13
|
let projectName
|
|
14
|
-
while
|
|
14
|
+
while(true) {
|
|
15
15
|
const res = await prompts({
|
|
16
16
|
type: 'text',
|
|
17
17
|
name: 'projectName',
|
|
@@ -19,10 +19,10 @@ const __dirname = path.dirname(__filename)
|
|
|
19
19
|
validate: v => v ? true : '项目名不能为空'
|
|
20
20
|
})
|
|
21
21
|
projectName = res.projectName
|
|
22
|
-
if
|
|
22
|
+
if(!projectName) process.exit(1)
|
|
23
23
|
|
|
24
24
|
const targetDir = path.resolve(process.cwd(), projectName)
|
|
25
|
-
if
|
|
25
|
+
if(fs.existsSync(targetDir)) {
|
|
26
26
|
console.log('❌ 目录已存在,请重新输入')
|
|
27
27
|
continue
|
|
28
28
|
}
|
|
@@ -31,6 +31,7 @@ const __dirname = path.dirname(__filename)
|
|
|
31
31
|
|
|
32
32
|
const targetDir = path.resolve(process.cwd(), projectName)
|
|
33
33
|
|
|
34
|
+
// 选择语言
|
|
34
35
|
const { language } = await prompts({
|
|
35
36
|
type: 'select',
|
|
36
37
|
name: 'language',
|
|
@@ -73,7 +74,21 @@ const __dirname = path.dirname(__filename)
|
|
|
73
74
|
}
|
|
74
75
|
])
|
|
75
76
|
|
|
76
|
-
//
|
|
77
|
+
// 询问是否开启自动路由
|
|
78
|
+
let autoRoute = false
|
|
79
|
+
if(features.router) {
|
|
80
|
+
const { enableAutoRoute } = await prompts({
|
|
81
|
+
type: 'toggle',
|
|
82
|
+
name: 'enableAutoRoute',
|
|
83
|
+
message: '是否开启自动配置路由(vite-plugin-pages)?',
|
|
84
|
+
initial: false,
|
|
85
|
+
active: '是',
|
|
86
|
+
inactive: '否'
|
|
87
|
+
})
|
|
88
|
+
autoRoute = enableAutoRoute
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// ========== 新增:增强插件配置 ==========
|
|
77
92
|
let extraPlugins = []
|
|
78
93
|
|
|
79
94
|
const { wantExtra } = await prompts({
|
|
@@ -85,7 +100,7 @@ const __dirname = path.dirname(__filename)
|
|
|
85
100
|
inactive: '否'
|
|
86
101
|
})
|
|
87
102
|
|
|
88
|
-
if
|
|
103
|
+
if(wantExtra) {
|
|
89
104
|
const pluginOptions = [
|
|
90
105
|
{ title: 'VueUse(实用 Composition API)', value: 'vueuse' },
|
|
91
106
|
{ title: 'Lodash(实用工具库)', value: 'lodash' },
|
|
@@ -101,7 +116,7 @@ const __dirname = path.dirname(__filename)
|
|
|
101
116
|
instructions: false
|
|
102
117
|
})
|
|
103
118
|
|
|
104
|
-
if
|
|
119
|
+
if(selectedPlugins?.length) {
|
|
105
120
|
extraPlugins = selectedPlugins
|
|
106
121
|
}
|
|
107
122
|
}
|
|
@@ -123,21 +138,21 @@ const __dirname = path.dirname(__filename)
|
|
|
123
138
|
{ recursive: true }
|
|
124
139
|
)
|
|
125
140
|
|
|
126
|
-
//
|
|
141
|
+
// 替换 index.html 的 title
|
|
127
142
|
const indexPath = path.join(targetDir, 'index.html')
|
|
128
|
-
if
|
|
143
|
+
if(fs.existsSync(indexPath)) {
|
|
129
144
|
const indexContent = fs.readFileSync(indexPath, 'utf-8')
|
|
130
145
|
fs.writeFileSync(
|
|
131
146
|
indexPath,
|
|
132
147
|
indexContent.replace(/<title>.*<\/title>/, `<title>${projectName}</title>`)
|
|
133
148
|
)
|
|
134
149
|
}
|
|
150
|
+
|
|
135
151
|
// 追加 Tailwind CSS 导入
|
|
136
|
-
if
|
|
152
|
+
if(extraPlugins.includes('tailwind')) {
|
|
137
153
|
const stylePath = path.join(targetDir, 'src/style.css')
|
|
138
154
|
const original = fs.readFileSync(stylePath, 'utf-8')
|
|
139
|
-
|
|
140
|
-
if (!original.startsWith('@import "tailwindcss";')) {
|
|
155
|
+
if(!original.startsWith('@import "tailwindcss";')) {
|
|
141
156
|
fs.writeFileSync(stylePath, `@import "tailwindcss";\n${original}`)
|
|
142
157
|
}
|
|
143
158
|
}
|
|
@@ -150,68 +165,56 @@ const __dirname = path.dirname(__filename)
|
|
|
150
165
|
features.pinia && copy(language === 'ts' ? 'pinia-ts' : 'pinia-js')
|
|
151
166
|
features.axios && copy(language === 'ts' ? 'axios-ts' : 'axios-js')
|
|
152
167
|
|
|
153
|
-
//
|
|
154
|
-
for
|
|
168
|
+
// 拷贝增强插件模板
|
|
169
|
+
for(const plugin of extraPlugins) {
|
|
155
170
|
const templateName = `${plugin}-${language === 'ts' ? 'ts' : 'js'}`
|
|
156
171
|
const templatePath = path.resolve(__dirname, `../template/${templateName}`)
|
|
157
|
-
if
|
|
172
|
+
if(fs.existsSync(templatePath)) {
|
|
158
173
|
fs.cpSync(templatePath, targetDir, { recursive: true })
|
|
159
174
|
}
|
|
160
175
|
}
|
|
161
|
-
// ========== 增强插件模板拷贝结束 ==========
|
|
162
176
|
|
|
163
|
-
// 6️⃣ 生成 main.js
|
|
177
|
+
// 6️⃣ 生成 main.js / main.ts
|
|
164
178
|
const mainFile = language === 'ts' ? 'main.ts' : 'main.js'
|
|
165
179
|
const mainTplPath = path.join(targetDir, `src/${mainFile}.tpl`)
|
|
166
180
|
let main = fs.readFileSync(mainTplPath, 'utf-8')
|
|
167
181
|
|
|
168
182
|
const replacements = {
|
|
169
|
-
// import
|
|
170
|
-
// vue-router
|
|
171
183
|
'/* __ROUTER_IMPORT__ */': features.router ? "import router from './router'" : '',
|
|
172
|
-
// pinia
|
|
173
184
|
'/* __PINIA_IMPORT__ */': features.pinia
|
|
174
185
|
? "import { createPinia } from 'pinia'\nimport persistedstate from 'pinia-plugin-persistedstate'"
|
|
175
186
|
: '',
|
|
176
|
-
// element-plus
|
|
177
187
|
'/* __ELEMENT_IMPORT__ */': features.ui === 'element'
|
|
178
188
|
? `import ElementPlus from 'element-plus'
|
|
179
189
|
import zhCn from 'element-plus/es/locale/lang/zh-cn'
|
|
180
190
|
import 'element-plus/dist/index.css'
|
|
181
191
|
import * as ElementPlusIconsVue from '@element-plus/icons-vue'`
|
|
182
192
|
: '',
|
|
183
|
-
// vant
|
|
184
193
|
'/* __VANT_IMPORT__ */': features.ui === 'vant'
|
|
185
194
|
? `import Vant from 'vant'
|
|
186
195
|
import 'vant/lib/index.css'`
|
|
187
196
|
: '',
|
|
188
|
-
// use
|
|
189
|
-
//router
|
|
190
197
|
'/* __ROUTER_USE__ */': features.router ? 'app.use(router)' : '',
|
|
191
|
-
// pinia
|
|
192
198
|
'/* __PINIA_USE__ */': features.pinia
|
|
193
199
|
? 'app.use(createPinia().use(persistedstate))'
|
|
194
200
|
: '',
|
|
195
|
-
// element-plus
|
|
196
201
|
'/* __ELEMENT_USE__ */': features.ui === 'element'
|
|
197
202
|
? `app.use(ElementPlus, { locale: zhCn })
|
|
198
203
|
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
|
|
199
204
|
app.component(key, component)
|
|
200
205
|
}`
|
|
201
206
|
: '',
|
|
202
|
-
// vant
|
|
203
207
|
'/* __VANT_USE__ */': features.ui === 'vant'
|
|
204
208
|
? 'app.use(Vant)'
|
|
205
209
|
: ''
|
|
206
210
|
}
|
|
207
|
-
// ========== 增强插件占位符结束 ==========
|
|
208
211
|
|
|
209
212
|
function escapeRegExp (str) {
|
|
210
213
|
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
|
|
211
214
|
}
|
|
212
215
|
|
|
213
|
-
for
|
|
214
|
-
if
|
|
216
|
+
for(const [placeholder, content] of Object.entries(replacements)) {
|
|
217
|
+
if(content) {
|
|
215
218
|
main = main.replace(placeholder, content)
|
|
216
219
|
} else {
|
|
217
220
|
const re = new RegExp(`^\\s*${escapeRegExp(placeholder)}\\s*$\\n?`, 'gm')
|
|
@@ -222,42 +225,37 @@ for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
|
|
|
222
225
|
main = main.replace(/(\s*)const app = createApp\(App\)/, '\n\n$1const app = createApp(App)')
|
|
223
226
|
main = main.replace(/\n{3,}/g, '\n\n')
|
|
224
227
|
|
|
225
|
-
fs.writeFileSync(
|
|
226
|
-
path.join(targetDir, `src/${mainFile}`),
|
|
227
|
-
main
|
|
228
|
-
)
|
|
228
|
+
fs.writeFileSync(path.join(targetDir, `src/${mainFile}`), main)
|
|
229
229
|
fs.unlinkSync(mainTplPath)
|
|
230
230
|
|
|
231
231
|
// 7️⃣ 生成 package.json
|
|
232
232
|
const pkgTpl = path.join(targetDir, 'package.json.tpl')
|
|
233
|
-
if
|
|
233
|
+
if(fs.existsSync(pkgTpl)) {
|
|
234
234
|
let pkg = fs.readFileSync(pkgTpl, 'utf-8')
|
|
235
235
|
|
|
236
236
|
const optionalDeps = {}
|
|
237
|
-
if
|
|
238
|
-
if
|
|
237
|
+
if(features.router) optionalDeps['vue-router'] = '^4.4.0'
|
|
238
|
+
if(features.pinia) {
|
|
239
239
|
optionalDeps['pinia'] = '^2.2.2'
|
|
240
240
|
optionalDeps['pinia-plugin-persistedstate'] = '^3.2.1'
|
|
241
241
|
}
|
|
242
|
-
if
|
|
243
|
-
if
|
|
242
|
+
if(features.axios) optionalDeps['axios'] = '^1.7.7'
|
|
243
|
+
if(features.ui === 'element') {
|
|
244
244
|
optionalDeps['element-plus'] = '^2.8.8'
|
|
245
245
|
optionalDeps['@element-plus/icons-vue'] = '^2.3.1'
|
|
246
246
|
}
|
|
247
|
-
if
|
|
247
|
+
if(features.ui === 'vant') {
|
|
248
248
|
optionalDeps['vant'] = '^4.9.22'
|
|
249
249
|
}
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
if
|
|
253
|
-
if
|
|
254
|
-
if
|
|
255
|
-
|
|
256
|
-
// ========== 增强插件依赖结束 ==========
|
|
250
|
+
// 增强插件依赖
|
|
251
|
+
if(extraPlugins.includes('vueuse')) optionalDeps['@vueuse/core'] = '^14.1.0'
|
|
252
|
+
if(extraPlugins.includes('dayjs')) optionalDeps['dayjs'] = '^1.11.19'
|
|
253
|
+
if(extraPlugins.includes('lodash')) optionalDeps['lodash'] = '^4.17.23'
|
|
254
|
+
if(autoRoute) optionalDeps['vite-plugin-pages'] = '^0.33.3'
|
|
257
255
|
|
|
258
256
|
let depsStr = ''
|
|
259
257
|
const keys = Object.keys(optionalDeps)
|
|
260
|
-
if
|
|
258
|
+
if(keys.length > 0) {
|
|
261
259
|
depsStr = ',\n' + keys.map(k => ` "${k}": "${optionalDeps[k]}"`).join(',\n')
|
|
262
260
|
}
|
|
263
261
|
|
|
@@ -269,18 +267,118 @@ for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
|
|
|
269
267
|
fs.unlinkSync(pkgTpl)
|
|
270
268
|
}
|
|
271
269
|
|
|
272
|
-
// 8️⃣
|
|
270
|
+
// 8️⃣ 配置自动路由
|
|
271
|
+
if(autoRoute) {
|
|
272
|
+
const viteConfigPath = path.join(targetDir, `vite.config.${language === 'ts' ? 'ts' : 'js'}`)
|
|
273
|
+
if(fs.existsSync(viteConfigPath)) {
|
|
274
|
+
let viteConfig = fs.readFileSync(viteConfigPath, 'utf-8')
|
|
275
|
+
if(!viteConfig.includes("import fs from 'fs'")) {
|
|
276
|
+
viteConfig = `import fs from 'fs'\n${viteConfig}`
|
|
277
|
+
}
|
|
278
|
+
// 确保顶部 import Pages
|
|
279
|
+
if(!viteConfig.includes("import Pages from 'vite-plugin-pages'")) {
|
|
280
|
+
viteConfig = viteConfig.replace(/(import .*?from .*?\n)/, `$1import Pages from 'vite-plugin-pages'\n`)
|
|
281
|
+
}
|
|
282
|
+
viteConfig = viteConfig.replace(/plugins:\s*\[/, `plugins: [
|
|
283
|
+
Pages({
|
|
284
|
+
dirs: 'src/views',
|
|
285
|
+
extensions: ['vue'],
|
|
286
|
+
exclude: ['**/_*.vue'],
|
|
287
|
+
async extendRoute(route) {
|
|
288
|
+
const componentPath = path.resolve(process.cwd(), route.component.slice(1))
|
|
289
|
+
const dirPath = path.dirname(componentPath)
|
|
290
|
+
const metaFile = path.resolve(dirPath, 'meta.json')
|
|
291
|
+
if(fs.existsSync(metaFile)) {
|
|
292
|
+
try {
|
|
293
|
+
const metaContent = fs.readFileSync(metaFile, 'utf-8')
|
|
294
|
+
const meta = JSON.parse(metaContent)
|
|
295
|
+
route.meta = { ...(route.meta || {}), ...meta }
|
|
296
|
+
} catch(err) {
|
|
297
|
+
console.warn(\`加载 \${metaFile} 失败:\`, err)
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
return { ...route }
|
|
301
|
+
}
|
|
302
|
+
}),`)
|
|
303
|
+
fs.writeFileSync(viteConfigPath, viteConfig)
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// 创建 Home/meta.json
|
|
307
|
+
const homeMetaPath = path.join(targetDir, 'src/views/home/meta.json')
|
|
308
|
+
if(!fs.existsSync(homeMetaPath)) {
|
|
309
|
+
fs.writeFileSync(homeMetaPath, JSON.stringify({ title: '首页' }, null, 2))
|
|
310
|
+
}
|
|
311
|
+
if(language === 'ts') {
|
|
312
|
+
// 生成 types 目录
|
|
313
|
+
const typesDir = path.join(targetDir, 'src/types')
|
|
314
|
+
if(!fs.existsSync(typesDir)) fs.mkdirSync(typesDir, { recursive: true })
|
|
315
|
+
|
|
316
|
+
// 创建 vite-plugin-pages.d.ts
|
|
317
|
+
const vitePagesDtsPath = path.join(typesDir, 'vite-plugin-pages.d.ts')
|
|
318
|
+
const vitePagesDtsContent = `declare module '~pages' {
|
|
319
|
+
import type { RouteRecordRaw } from 'vue-router'
|
|
320
|
+
const routes: RouteRecordRaw[]
|
|
321
|
+
export default routes
|
|
322
|
+
}
|
|
323
|
+
`
|
|
324
|
+
fs.writeFileSync(vitePagesDtsPath, vitePagesDtsContent)
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
// 9️⃣ 替换 router/index.js
|
|
330
|
+
if(features.router) {
|
|
331
|
+
const routerIndexPath = path.join(targetDir, `src/router/index.${language === 'ts' ? 'ts' : 'js'}`)
|
|
332
|
+
if(autoRoute) {
|
|
333
|
+
fs.writeFileSync(
|
|
334
|
+
routerIndexPath,
|
|
335
|
+
`import { createRouter, createWebHistory } from 'vue-router'
|
|
336
|
+
import routes from '~pages'
|
|
337
|
+
|
|
338
|
+
routes.unshift({
|
|
339
|
+
path: '/',
|
|
340
|
+
redirect: '/home'
|
|
341
|
+
})
|
|
342
|
+
|
|
343
|
+
export default createRouter({
|
|
344
|
+
history: createWebHistory(),
|
|
345
|
+
routes
|
|
346
|
+
})
|
|
347
|
+
`
|
|
348
|
+
)
|
|
349
|
+
} else {
|
|
350
|
+
fs.writeFileSync(
|
|
351
|
+
routerIndexPath,
|
|
352
|
+
`import { createRouter, createWebHistory } from 'vue-router'
|
|
353
|
+
|
|
354
|
+
const routes = [
|
|
355
|
+
{
|
|
356
|
+
path: '/',
|
|
357
|
+
component: () => import('@/views/home/index.vue')
|
|
358
|
+
}
|
|
359
|
+
]
|
|
360
|
+
|
|
361
|
+
export default createRouter({
|
|
362
|
+
history: createWebHistory(),
|
|
363
|
+
routes
|
|
364
|
+
})
|
|
365
|
+
`
|
|
366
|
+
)
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
// 1️⃣0️⃣ 安装依赖
|
|
273
371
|
console.log('📦 安装依赖中...')
|
|
274
372
|
execSync('npm install', { cwd: targetDir, stdio: 'inherit' })
|
|
275
|
-
if
|
|
373
|
+
if(extraPlugins.includes('tailwind')) {
|
|
276
374
|
execSync('npm install tailwindcss @tailwindcss/postcss postcss', { cwd: targetDir, stdio: 'inherit' })
|
|
277
375
|
}
|
|
278
376
|
|
|
279
|
-
//
|
|
280
|
-
if
|
|
377
|
+
// 1️⃣1️⃣ 运行 dev
|
|
378
|
+
if(runDev) {
|
|
281
379
|
console.log('🚀 启动开发服务器...')
|
|
282
380
|
execSync('npm run dev', { cwd: targetDir, stdio: 'inherit' })
|
|
283
381
|
} else {
|
|
284
382
|
console.log(`\n✅ 项目创建完成\n👉 cd ${projectName}\n👉 npm run dev\n`)
|
|
285
383
|
}
|
|
286
|
-
})()
|
|
384
|
+
})()
|
package/package.json
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
- ⚡ 基于 Vite + Vue 3,启动快、构建快
|
|
11
11
|
- 📜 支持 JavaScript / TypeScript 自由选择
|
|
12
|
-
- 🧭 可选集成 Vue Router
|
|
12
|
+
- 🧭 可选集成 Vue Router(支持动态参数路由)
|
|
13
13
|
- 🗂️ 可选集成 Pinia(含持久化)
|
|
14
14
|
- 📡 内置 Axios 请求方案
|
|
15
15
|
- 🖥️ / 📱 支持 Element Plus / Vant
|
|
@@ -70,6 +70,11 @@ project-name
|
|
|
70
70
|
│ ├─ types/ —— 类型声明文件
|
|
71
71
|
│ ├─ utils/ —— 工具方法、请求封装
|
|
72
72
|
│ ├─ views/ —— 页面级组件(路由页面)
|
|
73
|
+
│ │ └─ home/ —— 示例页面文件夹
|
|
74
|
+
│ │ ├─ index.vue —— 默认首页 /home
|
|
75
|
+
│ │ ├─ meta.json —— 页面 meta 信息
|
|
76
|
+
│ │ └─ [id]/ —— 动态参数路由示例
|
|
77
|
+
│ │ └─ [name].vue —— 路由 /home/:id/:name
|
|
73
78
|
│ ├─ App.vue —— 根组件
|
|
74
79
|
│ ├─ main.js / main.ts —— 项目启动入口
|
|
75
80
|
│ └─ style.css —— 全局样式文件
|
|
@@ -125,18 +130,18 @@ npm run dev
|
|
|
125
130
|
## 🌐 技术栈官网链接
|
|
126
131
|
|
|
127
132
|
- [Vite](https://vitejs.dev/)
|
|
128
|
-
- [Vue 3](https://vuejs.org/)
|
|
133
|
+
- [Vue 3](https://vuejs.org/)
|
|
129
134
|
- [JavaScript](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript)
|
|
130
135
|
- [TypeScript](https://www.typescriptlang.org/)
|
|
131
|
-
- [Vue Router](https://router.vuejs.org/)
|
|
132
|
-
- [Pinia](https://pinia.vuejs.org/)
|
|
133
|
-
- [Axios](https://axios-http.com/)
|
|
136
|
+
- [Vue Router](https://router.vuejs.org/)
|
|
137
|
+
- [Pinia](https://pinia.vuejs.org/)
|
|
138
|
+
- [Axios](https://axios-http.com/)
|
|
134
139
|
- [Element Plus](https://element-plus.org/)
|
|
135
140
|
- [Vant](https://vant-contrib.gitee.io/vant/)
|
|
136
141
|
- [VueUse](https://vueuse.org/)
|
|
137
142
|
- [Lodash](https://lodash.com/)
|
|
138
143
|
- [Day.js](https://day.js.org/)
|
|
139
|
-
-
|
|
144
|
+
- [Tailwind CSS](https://tailwindcss.com/)
|
|
140
145
|
|
|
141
146
|
---
|
|
142
147
|
|
|
@@ -189,33 +194,41 @@ export default defineConfig({
|
|
|
189
194
|
|
|
190
195
|
---
|
|
191
196
|
|
|
192
|
-
### 3️⃣
|
|
197
|
+
### 3️⃣ 路由结构(支持动态参数)
|
|
193
198
|
|
|
194
199
|
文件:`src/router/index.ts` `src/router/index.js`
|
|
195
200
|
```ts
|
|
196
|
-
import { createRouter, createWebHistory } from 'vue-router'
|
|
197
|
-
import
|
|
198
|
-
|
|
199
|
-
const routes = [
|
|
200
|
-
{ path: '/', name: 'Home', component: Home },
|
|
201
|
-
{ path: '/about', name: 'About', component: () => import('../views/About.vue') },
|
|
202
|
-
];
|
|
201
|
+
import { createRouter, createWebHistory } from 'vue-router'
|
|
202
|
+
import routes from '~pages' // 自动生成的路由
|
|
203
203
|
|
|
204
204
|
const router = createRouter({
|
|
205
205
|
history: createWebHistory(),
|
|
206
|
-
routes
|
|
207
|
-
})
|
|
206
|
+
routes
|
|
207
|
+
})
|
|
208
|
+
|
|
209
|
+
export default router
|
|
210
|
+
```
|
|
208
211
|
|
|
209
|
-
|
|
212
|
+
> 🔹 页面文件夹结构示例:
|
|
213
|
+
```text
|
|
214
|
+
src/views/home/
|
|
215
|
+
├─ index.vue -> /home
|
|
216
|
+
└─ [id]/[name].vue -> /home/:id/:name
|
|
210
217
|
```
|
|
211
218
|
|
|
212
|
-
> 🔹
|
|
219
|
+
> 🔹 获取路由参数:
|
|
220
|
+
```ts
|
|
221
|
+
import { useRoute } from 'vue-router'
|
|
222
|
+
const route = useRoute()
|
|
223
|
+
console.log(route.params.id)
|
|
224
|
+
console.log(route.params.name)
|
|
225
|
+
```
|
|
213
226
|
|
|
214
227
|
---
|
|
215
228
|
|
|
216
229
|
### 4️⃣ 页面内容与样式
|
|
217
230
|
|
|
218
|
-
文件示例:`src/views/
|
|
231
|
+
文件示例:`src/views/home/index.vue`
|
|
219
232
|
```vue
|
|
220
233
|
<template>
|
|
221
234
|
<div class="home-container">
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
- ⚡ 基于 Vite + Vue 3,启动快、构建快
|
|
11
11
|
- 📜 支持 JavaScript / TypeScript 自由选择
|
|
12
|
-
- 🧭 可选集成 Vue Router
|
|
12
|
+
- 🧭 可选集成 Vue Router(支持动态参数路由)
|
|
13
13
|
- 🗂️ 可选集成 Pinia(含持久化)
|
|
14
14
|
- 📡 内置 Axios 请求方案
|
|
15
15
|
- 🖥️ / 📱 支持 Element Plus / Vant
|
|
@@ -70,6 +70,11 @@ project-name
|
|
|
70
70
|
│ ├─ types/ —— 类型声明文件
|
|
71
71
|
│ ├─ utils/ —— 工具方法、请求封装
|
|
72
72
|
│ ├─ views/ —— 页面级组件(路由页面)
|
|
73
|
+
│ │ └─ home/ —— 示例页面文件夹
|
|
74
|
+
│ │ ├─ index.vue —— 默认首页 /home
|
|
75
|
+
│ │ ├─ meta.json —— 页面 meta 信息
|
|
76
|
+
│ │ └─ [id]/ —— 动态参数路由示例
|
|
77
|
+
│ │ └─ [name].vue —— 路由 /home/:id/:name
|
|
73
78
|
│ ├─ App.vue —— 根组件
|
|
74
79
|
│ ├─ main.js / main.ts —— 项目启动入口
|
|
75
80
|
│ └─ style.css —— 全局样式文件
|
|
@@ -125,18 +130,18 @@ npm run dev
|
|
|
125
130
|
## 🌐 技术栈官网链接
|
|
126
131
|
|
|
127
132
|
- [Vite](https://vitejs.dev/)
|
|
128
|
-
- [Vue 3](https://vuejs.org/)
|
|
133
|
+
- [Vue 3](https://vuejs.org/)
|
|
129
134
|
- [JavaScript](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript)
|
|
130
135
|
- [TypeScript](https://www.typescriptlang.org/)
|
|
131
|
-
- [Vue Router](https://router.vuejs.org/)
|
|
132
|
-
- [Pinia](https://pinia.vuejs.org/)
|
|
133
|
-
- [Axios](https://axios-http.com/)
|
|
136
|
+
- [Vue Router](https://router.vuejs.org/)
|
|
137
|
+
- [Pinia](https://pinia.vuejs.org/)
|
|
138
|
+
- [Axios](https://axios-http.com/)
|
|
134
139
|
- [Element Plus](https://element-plus.org/)
|
|
135
140
|
- [Vant](https://vant-contrib.gitee.io/vant/)
|
|
136
141
|
- [VueUse](https://vueuse.org/)
|
|
137
142
|
- [Lodash](https://lodash.com/)
|
|
138
143
|
- [Day.js](https://day.js.org/)
|
|
139
|
-
-
|
|
144
|
+
- [Tailwind CSS](https://tailwindcss.com/)
|
|
140
145
|
|
|
141
146
|
---
|
|
142
147
|
|
|
@@ -189,33 +194,41 @@ export default defineConfig({
|
|
|
189
194
|
|
|
190
195
|
---
|
|
191
196
|
|
|
192
|
-
### 3️⃣
|
|
197
|
+
### 3️⃣ 路由结构(支持动态参数)
|
|
193
198
|
|
|
194
199
|
文件:`src/router/index.ts` `src/router/index.js`
|
|
195
200
|
```ts
|
|
196
|
-
import { createRouter, createWebHistory } from 'vue-router'
|
|
197
|
-
import
|
|
198
|
-
|
|
199
|
-
const routes = [
|
|
200
|
-
{ path: '/', name: 'Home', component: Home },
|
|
201
|
-
{ path: '/about', name: 'About', component: () => import('../views/About.vue') },
|
|
202
|
-
];
|
|
201
|
+
import { createRouter, createWebHistory } from 'vue-router'
|
|
202
|
+
import routes from '~pages' // 自动生成的路由
|
|
203
203
|
|
|
204
204
|
const router = createRouter({
|
|
205
205
|
history: createWebHistory(),
|
|
206
|
-
routes
|
|
207
|
-
})
|
|
206
|
+
routes
|
|
207
|
+
})
|
|
208
|
+
|
|
209
|
+
export default router
|
|
210
|
+
```
|
|
208
211
|
|
|
209
|
-
|
|
212
|
+
> 🔹 页面文件夹结构示例:
|
|
213
|
+
```text
|
|
214
|
+
src/views/home/
|
|
215
|
+
├─ index.vue -> /home
|
|
216
|
+
└─ [id]/[name].vue -> /home/:id/:name
|
|
210
217
|
```
|
|
211
218
|
|
|
212
|
-
> 🔹
|
|
219
|
+
> 🔹 获取路由参数:
|
|
220
|
+
```ts
|
|
221
|
+
import { useRoute } from 'vue-router'
|
|
222
|
+
const route = useRoute()
|
|
223
|
+
console.log(route.params.id)
|
|
224
|
+
console.log(route.params.name)
|
|
225
|
+
```
|
|
213
226
|
|
|
214
227
|
---
|
|
215
228
|
|
|
216
229
|
### 4️⃣ 页面内容与样式
|
|
217
230
|
|
|
218
|
-
文件示例:`src/views/
|
|
231
|
+
文件示例:`src/views/home/index.vue`
|
|
219
232
|
```vue
|
|
220
233
|
<template>
|
|
221
234
|
<div class="home-container">
|
|
@@ -18,10 +18,10 @@
|
|
|
18
18
|
"@vitejs/plugin-vue": "^6.0.1",
|
|
19
19
|
"@vue/tsconfig": "^0.8.1",
|
|
20
20
|
"typescript": "~5.9.3",
|
|
21
|
-
"vite": "npm:rolldown-vite@
|
|
21
|
+
"vite": "npm:rolldown-vite@latest",
|
|
22
22
|
"vue-tsc": "^3.1.4"
|
|
23
23
|
},
|
|
24
24
|
"overrides": {
|
|
25
|
-
"vite": "npm:rolldown-vite@
|
|
25
|
+
"vite": "npm:rolldown-vite@latest"
|
|
26
26
|
}
|
|
27
27
|
}
|
|
File without changes
|
|
File without changes
|