Angular Ng-bootstrap

@ng-bootstrap/ng-bootstrap官網

安裝語法

1
ng add @ng-bootstrap/ng-bootstrap

錯誤訊息 Sass @import rules are deprecated and will be removed in Dart Sass 3.0.0.

Sass @import rules are deprecated and will be removed in Dart Sass 3.0.0.

More info and automated migrator: https://sass-lang.com/d/import

The plugin “angular-sass” was triggered by this import

angular:styles/global:styles:2:8:
  2 │ @import 'src/styles.scss';
    ╵         ~~~~~~~~~~~~~~~~~
處理方式 angular.json/ "projects": { "vite_angular19_st_project": { "architect": { "build": { "options": { 加在這裡 } } } } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
"projects": {
"vite_angular19_st_project": {
"architect": {
"build": {
"options": {
+新增在這裡
"stylePreprocessorOptions": {
"sass": {
"silenceDeprecations": [
"mixed-decls",
"color-functions",
"global-builtin",
"import"
]
}
},

}
}
}
}

新增
"stylePreprocessorOptions": {
"sass": {
"silenceDeprecations": [
"mixed-decls",
"color-functions",
"global-builtin",
"import"
]
}
},

錯誤訊息 [ERROR] Can’t find stylesheet to import.

✘ [ERROR] Can’t find stylesheet to import.

1 │ @use ‘bootstrap/scss/bootstrap’;

處理方式 安裝 bootstrap,如果安裝完成package.json 會出現”dependencies” 內 “bootstrap”: “^5.3.5”,”@popperjs/core”: “^2.11.8”,

1
npm install --save bootstrap

styles.scss引入 bootstrap

1
@use 'bootstrap/scss/bootstrap';

測試Html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<ng-template #content let-modal>
<div class="modal-header">
<h4 class="modal-title" id="modal-basic-title">Profile update</h4>
<button type="button" class="btn-close" aria-label="Close" (click)="modal.dismiss('Cross click')"></button>
</div>
<div class="modal-body">
<form>
<div class="mb-3">
<label for="dateOfBirth">Date of birth</label>
<div class="input-group">
<input
id="dateOfBirth"
class="form-control"
placeholder="yyyy-mm-dd"
name="dp"
ngbDatepicker
#dp="ngbDatepicker"
/>
<button class="btn btn-outline-secondary bi bi-calendar3" (click)="dp.toggle()" type="button"></button>
</div>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-outline-secondary" (click)="modal.close('Save click')">Save</button>
</div>
</ng-template>

<button class="btn btn-lg btn-outline-primary" (click)="open(content)">Launch demo modal</button>

<hr />

<pre>{{ closeResult() }}</pre>

TS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import { Component, inject, signal, TemplateRef, WritableSignal } from '@angular/core';

import { ModalDismissReasons, NgbDatepickerModule, NgbModal } from '@ng-bootstrap/ng-bootstrap';

@Component({
selector: 'ngbd-modal-basic',
imports: [NgbDatepickerModule],
templateUrl: './modal-basic.html',
})
export class NgbdModalBasic {
private modalService = inject(NgbModal);
closeResult: WritableSignal<string> = signal('');

open(content: TemplateRef<any>) {
this.modalService.open(content, { ariaLabelledBy: 'modal-basic-title' }).result.then(
(result) => {
this.closeResult.set(`Closed with: ${result}`);
},
(reason) => {
this.closeResult.set(`Dismissed ${this.getDismissReason(reason)}`);
},
);
}

private getDismissReason(reason: any): string {
switch (reason) {
case ModalDismissReasons.ESC:
return 'by pressing ESC';
case ModalDismissReasons.BACKDROP_CLICK:
return 'by clicking on a backdrop';
default:
return `with: ${reason}`;
}
}
}

Model範例

Angular 打包

Angular 打包

打包指令

1
ng build

angular.json內的設定:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"newProjectRoot": "projects",
"projects": {
"vite_angular19_todo_project": {
"projectType": "application",
"schematics": {
"@schematics/angular:component": {
"style": "scss"
}
},
"root": "",
"sourceRoot": "src",
"prefix": "app",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:application",
"options": {
+ "allowedCommonJsDependencies": [
+ "dayjs"
+ ],
+ "outputPath": "dist",
"index": "src/index.html",
"browser": "src/main.ts",
"polyfills": [
"zone.js"
],
"tsConfig": "tsconfig.app.json",
"inlineStyleLanguage": "scss",
"assets": [
{
"glob": "**/*",
"input": "public"
}
],
"styles": [
"@angular/material/prebuilt-themes/azure-blue.css",
+ "bootstrap/dist/css/bootstrap.min.css",
"src/styles.scss"
],
"scripts": [
+ "jquery/dist/jquery.min.js",
+ "popper.js/dist/umd/popper.min.js",
+ "bootstrap/dist/js/bootstrap.min.js"
],
"server": "src/main.server.ts",
"prerender": true,
"ssr": {
"entry": "src/server.ts"
}
},
"configurations": {
"production": {
"budgets": [
{
"type": "initial",
"maximumWarning": "50MB",
"maximumError": "10MB"
},
{
"type": "anyComponentStyle",
"maximumWarning": "50MB",
"maximumError": "10MB"
}
],
"outputHashing": "all"
},
"development": {
"optimization": true,
"extractLicenses": false,
"sourceMap": true
}
},
"defaultConfiguration": "production"
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"configurations": {
"production": {
"buildTarget": "vite_angular19_todo_project:build:production"
},
"development": {
"buildTarget": "vite_angular19_todo_project:build:development"
}
},
"defaultConfiguration": "development"
},
"extract-i18n": {
"builder": "@angular-devkit/build-angular:extract-i18n"
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"polyfills": [
"zone.js",
"zone.js/testing"
],
"tsConfig": "tsconfig.spec.json",
"inlineStyleLanguage": "scss",
"assets": [
{
"glob": "**/*",
"input": "public"
}
],
"styles": [
"@angular/material/prebuilt-themes/azure-blue.css",
"src/styles.scss"
],
"scripts": []
}
}
}
}
},
"cli": {
"analytics": "e07e021f-8e3d-4f1f-9cd5-d9911e112b15"
}
}

允許 CommonJs 依賴項
### 錯誤訊息 打包時 [WARNING] Module 'dayjs' used by 'src/app/home/home.component.ts' is not ESM
處理方式
angular.json 檔案內=>"projects"=> "vite_project" => "architect" => "build" => "options" allowedCommonJsDependencies(允許 CommonJs 依賴項):["dayjs"]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 {
"projects":{
"vite_project":{
"architect":{
"build":{
"options":{
+ "allowedCommonJsDependencies": [
+ "dayjs"
+ ],
}
}
}
}
}
}

錯誤訊息 打包時 bundle exceeded maximun. Budget 500kb was not met by ….
捆綁包超出最大值。預算 500 kb 未達
如圖

處理方式
angular.json 檔案內 budgets捆綁initial最初 與 anyComponentStyle任何組件樣式 =>maximumWarning 最大警告 =>maximumError最大誤差
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
{
"projects":{
"vite_project":{
"architect":{
"build":{
"configurations": {
"production": {
"budgets":[
{
"type": "initial",
+ "maximumWarning": "50MB",
+ "maximumError": "10MB"
},
{
"type": "anyComponentStyle",
+ "maximumWarning": "50MB",
+ "maximumError": "10MB"
}
]
}
}
}
}
}
}
}
打包路徑
1
"outputPath": "dist",
打包以後
注意要更改js 與css 的位址改為正確。

✘ [ERROR] The ‘index/product/:id’ route uses

✘ [ERROR] The ‘index/product/:id’ route uses prerendering and includes parameters, but ‘getPrerenderParams’ is missing. Please define ‘getPrerenderParams’ function for this route in your server routing configuration or specify a different ‘renderMode’.

處理方式
1
2
3
4
5
6
7
8
9
import { RenderMode, ServerRoute } from '@angular/ssr';

export const serverRoutes: ServerRoute[] = [
{
path: '**',
+ renderMode: RenderMode.Server
}
];

Angular Service 獨立管理

RxJS 的 BehaviorSubject

利用 RxJS 的 BehaviorSubject,將原本儲存在各 Component 中的狀態,集中儲存在 Service 中,以方便各階層的元件透過 DI 存取,而不需要透過元件間的互動來傳遞狀態數值。

Api Service 獨立管理

Configures Angular’s HttpClient service to be available for injection.
配置 Angular 的 HttpClient 服務以供注入。
provideHttpClient
src/app/app.config.ts

錯誤訊息:ERROR NullInjectorError: R3InjectorError(Environment Injector)[_ProductsService -> _ApiService -> _HttpClient -> _HttpClient]:
處理方式如下
引入 provideHttpClient
1
2
3
4
5
6
7
8
9
10
11
12
13
import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core';
import { provideRouter } from '@angular/router';
+ import {provideHttpClient} from '@angular/common/http';
import { routes } from './app.routes';

export const appConfig: ApplicationConfig = {
providers: [provideZoneChangeDetection({ eventCoalescing: true }), provideRouter(routes)]
providers: [
provideZoneChangeDetection({ eventCoalescing: true }),
+ provideHttpClient(),
provideRouter(routes)
]
};
新增 api資料夾 http-provider.service.ts 與 web-api.service.ts 官網Injectable 注入
Injectable: 裝飾器將某個類別標記為可用,可以作為依賴項提供和注入。
Observable:
透過網路傳輸來取得,則是屬於「非同步任務」,理由是需要連線到伺服器,使用者的應用程式必須等待伺服器回傳資料。
參考資料
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
//web-api.service.ts
import { Injectable, inject } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Observable, throwError } from 'rxjs';
import { catchError } from 'rxjs/operators';

@Injectable({ providedIn: 'root' })
export class WebApiService {
private readonly http = inject(HttpClient);

private readonly httpOptions = {
headers: new HttpHeaders({ 'Content-Type': 'application/json' })
};

get(url: string): Observable<any> {
return this.http.get(url, this.httpOptions)
.pipe(catchError(this.handleError));
}

post(url: string, model: any): Observable<any> {
return this.http.post(url, model, this.httpOptions)
.pipe(catchError(this.handleError));
}

put(url: string, model: any): Observable<any> {
return this.http.put(url, model, this.httpOptions)
.pipe(catchError(this.handleError));
}

delete(url: string): Observable<any> {
return this.http.delete(url, this.httpOptions)
.pipe(catchError(this.handleError));
}

private handleError(error: any) {
console.error('API 錯誤:', error);
return throwError(() => new Error(error.message || '錯誤已消失'));
}
}

http-provider.service.ts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
import { Injectable, inject } from '@angular/core';
import { Observable } from 'rxjs';
import { WebApiService } from './web-api.service';
import { environment } from '../../environment/environment';
import dayjs from 'dayjs'

@Injectable({ providedIn: 'root' })

export class HttpProviderService {
private readonly apiUrl = environment.apiUrl;
private readonly webApiService = inject(WebApiService);

getAllLists(): Observable<any> {
return this.webApiService.get(`${this.apiUrl}/api/toDoLists`);
}
// 編輯
deleteTodoById(_id: string): Observable<any> {
return this.webApiService.delete(`${this.apiUrl}/api/toDo/${encodeURIComponent(_id)}`);
}

getTodoById(id: string): Observable<any> {
return this.webApiService.get(`${this.apiUrl}/api/toDo/${encodeURIComponent(id)}`);
}
// 新增
addList(newTask: string): Observable<any> {
let query:any = {
title: newTask,
buildDate: Date.now(),
updataDate: Date.now(),
}
return this.webApiService.post(`${this.apiUrl}/api/toDo`,query);
}

// 編輯
updateTodo(item: any): Observable<any> {
let query:any = {
title: item.title,
buildDate: dayjs(item.buildDate).valueOf(),//改為時間搓
updataDate: Date.now(),
}
return this.webApiService.put(`${this.apiUrl}/api/toDo/${encodeURIComponent(item._id)}`, query);
}
}

頁面的引入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
+ import { HttpProviderService } from '../api/http-provider.service';
import { addListsType } from '../Types/toDo';
import dayjs from 'dayjs'
@Component({
selector: 'app-home',
imports: [CommonModule,RouterModule,FormsModule,ToDoListsComponent ],
templateUrl: './home.component.html',
styleUrl: './home.component.scss'
})

+ export class HomeComponent implements OnInit {
+ private readonly httpProvider = inject(HttpProviderService);
}
todoLists = <addListsType[] >([]);
//獲取數據
async getAllList() {
this.httpProvider.getAllLists().pipe(
tap(lists => {
let arrLists:any[] = [];
lists.map(function(item: any) {
let query: any = {
_id: item._id,
title: item.title,
Editing: false, // 編輯
Status: false, //選取狀態
CanEdit: true, //可以編輯
buildDate: dayjs(item.buildDate).format('YYYY-MM-DD HH:mm'),
updataDate: dayjs(item.updataDate).format('YYYY-MM-DD HH:mm'),
};
arrLists.push(query);
// 排序
arrLists.sort((a, b) => {
return dayjs(b.buildDate).valueOf() - dayjs(a.buildDate).valueOf()
})

});
this.todoLists = arrLists;
}),
catchError((error: any) => {
console.error("獲取錯誤:", error);
return of([]);
})
).subscribe();

}

使用 BehaviorSubject 的狀態儲存器

Subject
Subject 可以接受 Observer 的訂閱。 也可以用來訂閱其他的 Observable,所以他本身既是 Observable 又是 Observer。

BehaviorSubject 繼承自 Subject具有同樣的功能,然而兩者最主要的差異,在於:

  1. BehaviorSubject 可以接受給定初值,而 Subject 不可以。
  2. Subject 只會在被訂閱之後,而所訂閱的 Observable 有發出新值時,才會做通知。而 BehaviorSubject 會在每一 Observer 訂閱時,對其發出目前已收到的最新值。
也因此 BehaviorSubject 這種類似『狀態暫存』的模式,很適合用來做狀態管理之用。
參考資料

Css nth-child 選擇器

nth-child(even) 雙數

css

1
2
3
4
5
6
7
ul li{
padding:5px;
}
ul li:nth-child(even){
background-color:green;
color:white;
}

Scss

1
2
3
4
5
6
7
8
9
ul {
li{
padding:5px;
&:nth-child(even){
background-color:#ffd207;
color:white;
}
}
}

nth-child(odd) 單數

css

1
2
3
4
5
6
7
ul li{
padding:5px;
}
ul li:nth-child(odd){
background-color:green;
color:white;
}

Scss

1
2
3
4
5
6
7
8
9
ul {
li{
padding:5px;
&:nth-child(odd){
background-color:#ffd207;
color:white;
}
}
}

nth-child(3n) 倍數n

3n 指的是 3 乘 n,而 n 是個由0開始的固定數列 ( 就是 0123456789…n),我們就可以得到下列結果清單

1
2
3
4
5
6
7
8
9
 ul {
li{
padding:5px;
&:nth-child(3n){
background-color:#ffd207;
color:#333;
}
}
}

nth-child(an+b) 倍數an+b

3n+1

  • 3 x 0 + 1 = 1
  • 3 x 1 + 1 = 4
  • 3 x 2 + 1 = 7
  • 3 x 3 + 1 = 10
  • 3 x 4 + 1 = 13
1
2
3
4
5
6
7
8
9
 ul {
li{
padding:5px;
&:nth-child(3n+1){
background-color:#ffd207;
color:#333;
}
}
}

nth-child(an-b) 倍數an-b

3n-1

  • 3 x 0 - 1 = -1
  • 3 x 1 - 1 = 2
  • 3 x 2 - 1 = 5
  • 3 x 3 - 1 = 8
  • 3 x 4 - 1 = 11
1
2
3
4
5
6
7
8
9
 ul {
li{
padding:5px;
&:nth-child(3n-1){
background-color:#ffd207;
color:#333;
}
}
}

Angular 防止冒泡

事件冒泡

  • stopPropagation($event)
  • stopPropagation(event: Event) { event.stopPropagation(); console.log('Div clicked!'); }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import { Component } from '@angular/core';

@Component({
selector: 'app-click-event',
template: `<div (click)="stopPropagation($event)">Click on me!</div>`
})
export class ClickEventComponent {

stopPropagation(event: Event) {
event.stopPropagation();
console.log('Div clicked!');
}
}

參考資料

Angular NgClass & NgStyle

動態綁定Class

在 HTML 元素上新增和刪除 CSS 類別。

1
2
ngClass
string | string[] | Set<string> | { [klass: string]: any; } | null | undefined

CSS 類別根據表達式評估的類型進行如下更新:
expression evaluation =>表達式求值

  • 字串 - 新增字串中列出的 CSS 類別(以空格分隔),
  • 陣列 - 新增聲明為陣列元素的 CSS 類,
  • 物件 - 鍵是 CSS 類,當值中給出的表達式計算結果為真值時,它們會被添加,否則會被刪除
必須引入 NgClass
Ts [ngClass]必須引入NgClass
1
2
<some-element [ngClass]="stringExp|arrayExp|objExp|Set">...</some-element>
<some-element [ngClass]="{'class1 class2 class3' : true}">...</some-element>
對於更簡單的用例,您可以直接使用類別綁定。它不需要導入指令。
1
2
3
4
<some-element [class]="'first second'">...</some-element>
<some-element [class.expanded]="isExpanded">...</some-element>
<some-element [class]="['first', 'second']">...</some-element>
<some-element [class]="{'first': true, 'second': true, 'third': false}">...</some-element>

參考官網NgClass

NgStyle

用於更新包含 HTML 元素的樣式的屬性指令。
設定一個或多個樣式屬性,指定為冒號分隔的鍵值對。關鍵是樣式名稱,帶有可選的 . 後綴(例如 ‘top.px’、’font-style.em’)。該值是一個要評估的表達式。將以給定單位表示的結果非空值指派給給定的樣式屬性。如果評估結果為空,則刪除相應的樣式。
必須引入 NgStyle

Ts [ngStyle]必須引入NgStyle
將包含元素的寬度設定為表達式傳回的像素值。
1
2
3
//[ngStyle]="{'Style':動態欄位}"
[ngStyle]="{'background-color': sendBgStyle}"
<some-element [ngStyle]="{'max-width.px': widthExp}">...</some-element>
將包含元素的寬度設定為表達式傳回的像素值。...
1
<some-element [style]="{'font-style': styleExp}">...</some-element>
NgStyle

Angular Serve

RxJS 與 Angular 訊號的互通

重要提示:RxJS Interop 套件可供開發人員預覽。它已經準備好供您嘗試,但是在穩定之前可能會發生變化。

使用 toSignal 從 RxJs Observable 建立訊號

使用 toSignal 函數建立一個追蹤 Observable 值的訊號。它的行為類似於模板中的非同步管道,但更靈活,可以在應用程式的任何位置使用。
rxjs-interop

使用 toObservable 從訊號建立 RxJS Observable Create an RxJS Observable from a signal with toObservable

Quasar Vite Vue3 專案安裝

npm 進行 quasar 建置

使用 npm 進行 quasar 建置。
目前使用 Node v20.17.0

1
npm init quasar

npx
create-quasar

? What would you like to build? › - Use arrow-keys. Return to submit.
? 您想要建造什麼? ›——使用箭頭鍵。返回提交。
❯ App with Quasar CLI, let’s go! <= 選擇這個
❯ 帶有Quasar CLI的應用程序,我們開始吧!
spa/pwa/ssr/bex/electron/capacitor/cordova
AppExtension (AE) for Quasar CLI
Quasar UI kit (Quasar UI 套件)

✔ What would you like to build? › App with Quasar CLI, let’s go!
? Project folder: › quasar-project
? Pick script type: › - Use arrow-keys. Return to submit.
Javascript
❯ Typescript <= 選擇這個
? Pick Quasar App CLI variant: › - Use arrow-keys. Return to submit.
❯ Quasar App CLI with Vite - recommended ( Quasar App CLI 與 Vite - 推薦)<= 選擇這個
Quasar App CLI with Webpack
? Project product name: (must start with letter if building mobile apps) › Quasar App
?專案產品名稱:(如果建立行動應用程序,必須以字母開頭)› Quasar App
? Project description: › A Quasar Project
? Pick a Vue component style: › - Use arrow-keys. Return to submit.
❯ Composition API with < script setup > <= 選擇這個
recommended
Composition API
Options API
? Pick your CSS preprocessor: › - Use arrow-keys. Return to submit.
❯ Sass with SCSS syntax <= 選擇這個
Sass with indented syntax
None (the others will still be available)
Instructions:
↑/↓: Highlight option
←/→/[space]: Toggle selection
a: Toggle all
enter/return: Complete answer
◉ Linting (vite-plugin-checker + ESLint + vue-tsc)
recommended
◉ State Management (Pinia)
◉ axios
◉ vue-i18n

a =>全選
? Add Prettier for code formatting? › (Y/n) ?新增 Prettier 來進行程式碼格式化? › (是/否)<= 選擇是

Quasar • Generating files…

  • README.md
  • .editorconfig
  • .gitignore
  • .npmrc
  • .vscode/extensions.json
  • .vscode/settings.json
  • package.json
  • tsconfig.json
  • index.html
  • postcss.config.js
  • public/favicon.ico
  • public/icons/favicon-128x128.png
  • public/icons/favicon-16x16.png
  • public/icons/favicon-32x32.png
  • public/icons/favicon-96x96.png
  • quasar.config.ts
  • src/App.vue
  • src/assets/quasar-logo-vertical.svg
  • src/boot/.gitkeep
  • src/components/EssentialLink.vue
  • src/components/ExampleComponent.vue
  • src/components/models.ts
  • src/env.d.ts
  • src/layouts/MainLayout.vue
  • src/pages/ErrorNotFound.vue
  • src/pages/IndexPage.vue
  • src/router/index.ts
  • src/router/routes.ts
  • src/css/app.scss
  • src/css/quasar.variables.scss
  • src/boot/axios.ts
  • src/boot/i18n.ts
  • src/i18n/en-US/index.ts
  • src/i18n/index.ts
  • eslint.config.js
  • .prettierrc.json
  • src/stores/example-store.ts
  • src/stores/index.ts

Quasar • SUCCESS • The project has been scaffolded

? Install project dependencies? (recommended) › - Use arrow-keys. Return to submit.
❯ Yes, use npm <= 選擇
No, I will handle that myself

✔ Install project dependencies? (recommended) › Yes, use npm

quasar-project@0.0.1 postinstall
quasar prepare

App • Using quasar.config.ts in “ts” format
App • Generated tsconfig.json and types files in .quasar directory
App • The app is now prepared for linting, type-checking, IDE integration, etc.

added 547 packages, and audited 548 packages in 6m

144 packages are looking for funding
run npm fund for details

found 0 vulnerabilities

Quasar • Initialized Git repository 🚀
Quasar • 初始化 Git 儲存庫
To get started:開始吧:
啟動

1
2
cd quasar-project
npm run dev

Documentation can be found at: https://quasar.dev
文件可在以下網址找到:https://quasar.dev
Quasar is relying on donations to evolve. We’d be very grateful if you can
read our manifest on “Why donations are important”: https://quasar.dev/why-donate
Donation campaign: https://donate.quasar.dev
Any amount is very welcome.
If invoices are required, please first contact Razvan Stoenescu.

Please give us a star on Github if you appreciate our work:
https://github.com/quasarframework/quasar
Quasar 依靠捐贈來發展。如果你能
閱讀我們的「為什麼捐款很重要」宣言:https://quasar.dev/why-donate
捐款活動:https://donate.quasar.dev
無論數量多少,都非常歡迎。
如果需要發票,請先聯絡 Razvan Stoenescu。

如果您欣賞我們的工作,請在 Github 上給我們一顆星:
https://github.com/quasarframework/quasar
Enjoy! - Quasar Team

App • Using quasar.config.ts in “ts” format

» Reported at………… 2025/3/21 下午10:40:30
» App dir……………. /Users/larahuang/Desktop/作品集/天昕科技/quasar-project
» App URL……………. http://localhost:9000/
http://192.168.25.60:9000/
» Dev mode…………… spa
» Pkg quasar…………. v2.18.1
» Pkg @quasar/app-vite… v2.1.4
» Browser target……… es2022|firefox115|chrome115|safari14

App • Opening default browser at http://localhost:9000/