使用 Angular 和 Tailwind CSS 构建 URL 缩短应用程序

在本博客中,我们将引导您完成使用 angular 作为前端并使用 tailwind css 进行样式创建 url 缩短器应用程序的过程。 url 缩短器是一个方便的工具,可以将长 url 转换为更短、更易于管理的链接。该项目将帮助您了解如何使用现代 web 开发技术构建功能齐全且美观的 web 应用程序。

先决条件

要学习本教程,您应该对 angular 有基本的了解,并对 tailwind css 有一定的了解。确保您的计算机上安装了 node.js 和 angular cli。

项目设置

1. 创建一个新的 angular 项目

首先,通过在终端中运行以下命令来创建一个新的 angular 项目:

1

2

n小白轻松搭建系统点我wcqh.cng new url-shortener-app

cd url-shortener-app

登录后复制

2. 安装 tailwind css

接下来,在您的 angular 项目中设置 tailwind css。通过 npm 安装 tailwind css 及其依赖项:

1

2

npm install -d tailwindcss postcss autoprefixer

npx tailwindcss init

登录后复制

通过更新 tailwind.config.js 文件来配置 tailwind css:

1

2

3

4

5

6

7

8

9

module.exports = {

content: [

“./src/**/*.{htm小白轻松搭建系统点我wcqh.cnl,ts}”,

],

theme: {

extend: {},

},

plugins: [],

}

登录后复制

将 tailwind 指令添加到您的 src/styles.scss 文件中:

1

2

3

@tailwind base;

@tailwind components;

@tailwind utilities;

登录后复制

构建 url 缩短器

3. 创建 url 模型

创建 url 模型来定义 url 数据的结构。添加新文件 src/app/models/url.model.ts:

1

2

3

4

5

6

7

8

9

10

11

export type urls = url[];

export interface url {

_id: strin小白轻松搭建系统点我wcqh.cng;

originalurl: string;

shorturl: string;

clicks: number;

expirationdate: string;

createdat: string;

__v: number;

}

登录后复制

4. 设置 url 服务

创建一个服务来处理与 url 缩短相关的 api 调用。添加新文件 src/app/services/url.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

import { httpclient } from @angular/common/http;

import {小白轻松搭建系统点我wcqh.cn injectable } from @angular/core;

import { observable } from rxjs;

import { url, urls } from ../models/url.model;

import { environment } from ../../environments/environment;

@injectable({

providedin: root,

})

export class urlservice {

private apiurl = environment.apiurl;

constructor(private http: httpclient)小白轻松搭建系统点我wcqh.cn {}

shortenurl(originalurl: string): observable<url> {

return this.http.post<url>(`${this.apiurl}/shorten`, { originalurl });

}

getallurls(): observable<urls> {

return this.http.get<urls>(`${this.apiurl}/urls`);

}

getdetails(id: string): observable<url> {

return this.http.get<url>(`${this.apiurl}/details/${小白轻松搭建系统点我wcqh.cnid}`);

}

deleteurl(id: string): observable<url> {

return this.http.delete<url>(`${this.apiurl}/delete/${id}`);

}

}

</url></url></url></url></urls></urls></url></url>

登录后复制

5. 创建缩短 url 组件

生成一个用于缩短 url 的新组件:

1

ng generate component shorten

登录后复制

更新组件的 html (src/app/shorten/shorten.component.html) 如下所示:

1

2

3

4

5

6

7

8

9

10

1小白轻松搭建系统点我wcqh.cn1

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

<div class=”max-w-md mx-auto p-4 shadow-lg rounded-lg mt-4″>

<h2 class=”t小白轻松搭建系统点我wcqh.cnext-2xl font-bold mb-2″>url shortener</h2>

<form>

<div class=”flex items-center mb-2″>

<input class=”flex-1 p-2 border border-gray-300 rounded mr-4″ formcontrolname=”originalurl” placeholder=”enter your url” required><button class=”px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600″ type=”submi小白轻松搭建系统点我wcqh.cnt”>

shorten

</button>

</div>

@if (urlform.get(originalurl)?.invalid &amp;&amp; (urlform.get(originalurl)?.dirty ||

urlform.get(originalurl)?.touched)) {

<div class=”text-red-500″ role=”alert” aria-live=”assertive”>

@if (urlform.get(originalurl)?.errors?.[required]) {

url is required.

}

@if (urlform.get(origin小白轻松搭建系统点我wcqh.cnalurl)?.errors?.[pattern]) {

invalid url format. please enter a valid url starting with http:// or https://.

}

</div>

}

</form>

@if (errormsg) {

<div class=”p-4 bg-red-100 rounded mt-4″>

<p class=”text-red-500″>{{ errormsg }}</p>

</div>

}

@if (shorturl) {

<div class=”p-4 bg-green-100 rounded”>

<p>shortened url: 小白轻松搭建系统点我wcqh.cn<a class=”text-blue-500 hover:text-blue-600″ shorturl target=”_blank”>{{ shorturl }}</a>

<button class=”ml-2 px-2 py-1 bg-gray-200 text-gray-800 border border-slate-950 rounded hover:bg-gray-300″ shorturl>copy</button>

@if (copymessage) {

<span class=”text-green ml-2″>{{ copymessage }}</span>

}

</p>

</div小白轻松搭建系统点我wcqh.cn>

}

</div>

<div class=”max-w-md mx-auto mt-4 p-2″>

<h2 class=”text-2xl font-bold mb-4″>all urls</h2>

@if (isloading) {

<div class=”max-w-md mx-auto p-4 shadow-lg rounded-lg”>

<div class=”text-center p-4″>

loading…

</div>

</div>

}

@else if (error) {

<div class=”max-w-md mx-auto p-4 shadow-lg rounded-lg”>

<div cl小白轻松搭建系统点我wcqh.cnass=”text-center p-4″>

<p class=”text-red-500″>{{ error }}</p>

</div>

</div>

}

@else {

@if (urls.length &gt; 0 &amp;&amp; !isloading &amp;&amp; !error) {

<ul>

@for (url of urls; track $index) {

<li class=”p-2 border border-gray-300 rounded mb-2″>

<div class=”flex justify-between items-center”>

<div>

url:

<a clas小白轻松搭建系统点我wcqh.cns=”text-blue-500 hover:text-blue-600″ url.shorturl target=”_blank”>{{

url.shorturl }}</a>

</div>

<div class=”flex justify-between items-center”>

<button class=”px-2 py-1 bg-blue-200 text-blue-800 rounded hover:bg-blue-300″>details</button>

<button class=”ml-2 px-2 py-1 bg-gray-200 text-gray-800 rounded h小白轻松搭建系统点我wcqh.cnover:bg-gray-300″ url.shorturl>{{

copyindex === $index ? copied : copy

}}</button>

<button class=”ml-2 px-2 py-1 bg-red-200 text-red-800 rounded hover:bg-red-300″>delete</button>

</div>

</div>

</li>

}

</ul>

}

@else {

<div class=”max-w-md mx-auto p-4 shadow-lg rounded-lg”>

<div class=”text-center p-4″>

no urls fo小白轻松搭建系统点我wcqh.cnund.

</div>

</div>

}

}

</div>

@if (showdeletemodal) {

<div class=”fixed inset-0 flex items-center justify-center bg-black bg-opacity-50″>

<div class=”bg-white p-4 rounded shadow-lg”>

<h3 class=”text-xl font-bold mb-2″>confirm deletion</h3>

<p class=”mb-4″>are you sure you want to delete this url?</p>

<button c小白轻松搭建系统点我wcqh.cnlass=”px-4 py-2 bg-red-500 text-white rounded hover:bg-red-600″>yes,

delete</button>

<button class=”px-4 py-2 bg-gray-300 text-gray-800 rounded hover:bg-gray-400 ml-2″ false>cancel</button>

</div>

</div>

}

<div class=”fixed inset-0 flex items-center justify-center bg-black bg-opaci小白轻松搭建系统点我wcqh.cnty-50″>

<div class=”bg-white p-4 rounded shadow-lg”>

<h3 class=”text-xl font-bold mb-2″>url details</h3>

@if (isloading) {

<p class=”mb-4″>loading…</p>

}

@else {

<p class=”mb-4″>short url: <a class=”text-blue-500 hover:text-blue-600″ selectedurl.shorturl target=”_blank”>{{ selectedurl.shorturl }}</a></p>小白轻松搭建系统点我wcqh.cn

<p class=”mb-4″>original url: <a class=”text-blue-500 hover:text-blue-600″ target=”_blank”>{{ selectedurl.originalurl }}</a></p>

<p class=”mb-4″>clicks: <span class=”text-green-500″>{{ selectedurl.clicks }}</span></p>

<p class=”mb-4″>created at: {{ selectedurl.createdat | date: medium }}</p>

<p class=”小白轻松搭建系统点我wcqh.cnmb-4″>expires at: {{ selectedurl.expirationdate | date: medium }}</p>

<button class=”px-4 py-2 bg-gray-300 text-gray-800 rounded hover:bg-gray-400″ false>close</button>

}

</div>

</div>

}

登录后复制

6. 向组件添加逻辑

更新组件的 typescript 文件(src/app/shorten/shorten.component.ts)以处理表单提交

和 api 交互:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20小白轻松搭建系统点我wcqh.cn

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

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

1小白轻松搭建系统点我wcqh.cn47

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

import { component, inject, oninit } from @angular/core;

import { urlservice } from ../services/url.service;

import {

formcontrol,

formgroup,

validators,

} from @angular/forms;

import { url } from ../models/url.model小白轻松搭建系统点我wcqh.cn;

import { environment } from ../../environments/environment;

import { datepipe } from @angular/common;

import { subject, takeuntil } from rxjs;

@component({

selector: app-shorten,

standalone: true,

templateurl: ./shorten.component.html,

styleurl: ./shorten.component小白轻松搭建系统点我wcqh.cn.scss,

})

export class shortencomponent implements oninit {

shorturl: string = ;

redirecturl = environment.apiurl + /;

copymessage: string = ;

copylistmessage: string = ;

urls: url[] = [];

showdeletemodal = false;

urltodelete = ;

copyindex: number = -1;

selectedurl: url = {} as url;

isl小白轻松搭建系统点我wcqh.cnoading = false;

isloading = false;

error: string = ;

errormsg: string = ;

urlform: formgroup = new formgroup({});

private unsubscribe$: subject<void> = new subject<void>();

urlservice = inject(urlservice);

ngoninit() {

this.urlform = new formgroup({

originalurl: new formcontrol(, [

validators.required,

validat小白轻松搭建系统点我wcqh.cnors.pattern(^(http|https)://.*$),

]),

});

this.getallurls();

}

shortenurl() {

if (this.urlform.valid) {

this.urlservice.shortenurl(this.urlform.value.originalurl).pipe(takeuntil(this.unsubscribe$)).subscribe({

next: (response) =&gt; {

// console.log(shortened url: , response);

this.shorturl = response.shortur小白轻松搭建系统点我wcqh.cnl;

this.getallurls();

},

error: (error) =&gt; {

console.error(error shortening url: , error);

this.errormsg = error?.error?.message || an error occurred!;

},

});

}

}

getallurls() {

this.isloading = true;

this.urlservice.getallurls().pipe(takeuntil(this.unsubscribe$)).subscribe({

next: (response) =&gt; {

// consol小白轻松搭建系统点我wcqh.cne.log(all urls: , response);

this.urls = response;

this.isloading = false;

},

error: (error) =&gt; {

console.error(error getting all urls: , error);

this.isloading = false;

this.error = error?.error?.message || an error occurred!;

},

});

}

showdetails(id: string) {

this.getdetails(i小白轻松搭建系统点我wcqh.cnd);

}

getdetails(id: string) {

this.isloading = true;

this.urlservice.getdetails(id).subscribe({

next: (response) =&gt; {

// console.log(url details: , response);

this.selectedurl = response;

this.isloading = false;

},

error: (error) =&gt; {

console.error(error getting url details: , error);

this.error = error?小白轻松搭建系统点我wcqh.cn.error?.message || an error occurred!;

},

});

}

copyurl(url: string) {

navigator.clipboard

.writetext(url)

.then(() =&gt; {

// optional: display a message or perform an action after successful copy

console.log(url copied to clipboard!);

this.copymessage = copied!;

settimeout(() =&gt; {

this.copymessage = ;

}, 20小白轻松搭建系统点我wcqh.cn00);

})

.catch((err) =&gt; {

console.error(failed to copy url: , err);

this.copymessage = failed to copy url;

});

}

copylisturl(url: string, index: number) {

navigator.clipboard

.writetext(url)

.then(() =&gt; {

// optional: display a message or perform an action after successful copy

console.log(url copied to c小白轻松搭建系统点我wcqh.cnlipboard!);

this.copylistmessage = copied!;

this.copyindex = index;

settimeout(() =&gt; {

this.copylistmessage = ;

this.copyindex = -1;

}, 2000);

})

.catch((err) =&gt; {

console.error(failed to copy url: , err);

this.copylistmessage = failed to copy url;

});

}

preparedelete(url: string) {

this.urltodelete = url;

t小白轻松搭建系统点我wcqh.cnhis.showdeletemodal = true;

}

confirmdelete() {

// close the modal

this.showdeletemodal = false;

// delete the url

this.deleteurl(this.urltodelete);

}

deleteurl(id: string) {

this.urlservice.deleteurl(id).subscribe({

next: (response) =&gt; {

// console.log(deleted url: , response);

this.getallurls();

},

error: (e小白轻松搭建系统点我wcqh.cnrror) =&gt; {

console.error(error deleting url: , error);

this.error = error?.error?.message || an error occurred!;

},

});

}

ngondestroy() {

this.unsubscribe$.next();

this.unsubscribe$.complete();

}

}

</void></void>

登录后复制

7.更新应用程序组件的html文件(src/app/app.component.html)

1

<router-outlet></router-outlet>

登录后复制

8.更新应用程序配小白轻松搭建系统点我wcqh.cn置文件(src/app/app.config.ts)

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 { routes } from ./app.routes;

import { providehttpclient } from @angular/common/http;

export const appconfig: applicationconfig = 小白轻松搭建系统点我wcqh.cn{

providers: [

providezonechangedetection({ eventcoalescing: true }),

providerouter(routes),

providehttpclient(),

],

};

登录后复制

9.更新应用程序路由文件(src/app/app.routes.ts)

1

2

3

4

5

6

7

8

9

import { Routes } from @angular/router;

export const routes: Routes = [

{

path: ,

loadComponent: () =&gt;

import(./shorten/shorten.component).t小白轻松搭建系统点我wcqh.cnhen((m) =&gt; m.ShortenComponent),

},

];

登录后复制

结论

您已经使用 angular 和 tailwind css 成功构建了 url 缩短器应用程序。该项目演示了如何集成现代前端技术来创建功能强大且时尚的 web 应用程序。借助 angular 的强大功能和 tailwind css 实用程序优先的方法,您可以轻松构建响应灵敏且高效的 web 应用程序。

请随意通过添加用户身份验证等功能来扩展此应用程序。祝您编码愉快!

立即学习前端免费学习笔记(深入)”;

探索代码

访问 github 存储库以详细探索代码。

以上就是使用 Angular 和 Tailwind CSS 小白轻松搭建系统点我wcqh.cn构建 URL 缩短应用程序的详细内容,更多请关注青狐资源网其它相关文章!

© 版权声明
THE END
喜欢就支持一下吧
点赞149 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容