日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

Angular 2.x 从0到1 (五)史上最简单的Angular2教程

發(fā)布時(shí)間:2023/12/9 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Angular 2.x 从0到1 (五)史上最简单的Angular2教程 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

第一節(jié):Angular 2.0 從0到1 (一)
第二節(jié):Angular 2.0 從0到1 (二)
第三節(jié):Angular 2.0 從0到1 (三)
第四節(jié):Angular 2.0 從0到1 (四)
第五節(jié):Angular 2.0 從0到1 (五)

第五節(jié):多用戶版本的待辦事項(xiàng)應(yīng)用

第四節(jié)我們完成的Todo的基本功能看起來(lái)還不錯(cuò),但是有個(gè)大問(wèn)題,就是每個(gè)用戶看到的都是一樣的待辦事項(xiàng),我們希望的是每個(gè)用戶擁有自己的待辦事項(xiàng)列表。我們來(lái)分析一下怎么做,如果每個(gè)todo對(duì)象帶一個(gè)UserId屬性是不是可以解決呢?好像可以,邏輯大概是這樣:用戶登錄后轉(zhuǎn)到/todo,TodoComponent得到當(dāng)前用戶的UserId,然后調(diào)用TodoService中的方法,傳入當(dāng)前用戶的UserId,TodoService中按UserId去篩選當(dāng)前用戶的Todos。
但可惜我們目前的LoginComponent還是個(gè)實(shí)驗(yàn)品,很多功能的缺失,我們是先去做Login呢,還是利用現(xiàn)有的Todo對(duì)象先試驗(yàn)一下呢?我個(gè)人的習(xí)慣是先進(jìn)行試驗(yàn)。

數(shù)據(jù)驅(qū)動(dòng)開發(fā)

按之前我們分析的,給todo加一個(gè)userId屬性,我們手動(dòng)給我們目前的數(shù)據(jù)加上userId屬性吧。更改todo\todo-data.json為下面的樣子:

{"todos": [{"id": "bf75769b-4810-64e9-d154-418ff2dbf55e","desc": "getting up","completed": false,"userId": 1},{"id": "5894a12f-dae1-5ab0-5761-1371ba4f703e","desc": "have breakfast","completed": true,"userId": 2},{"id": "0d2596c4-216b-df3d-1608-633899c5a549","desc": "go to school","completed": true,"userId": 1},{"id": "0b1f6614-1def-3346-f070-d6d39c02d6b7","desc": "test","completed": false,"userId": 2},{"id": "c1e02a43-6364-5515-1652-a772f0fab7b3","desc": "This is a te","completed": false,"userId": 1}] }

如果你還沒(méi)有啟動(dòng)json-server的話讓我們啟動(dòng)它: json-server ./src/app/todo/todo-data.json,然后打開瀏覽器在地址欄輸入http://localhost:3000/todos/?userId=2你會(huì)看到只有userId=2的json被輸出了

[{"id": "5894a12f-dae1-5ab0-5761-1371ba4f703e","desc": "have breakfast","completed": true,"userId": 2},{"id": "0b1f6614-1def-3346-f070-d6d39c02d6b7","desc": "test","completed": false,"userId": 2} ]

有興趣的話可以再試試http://localhost:3000/todos/?userId=2&completed=false或其他組合查詢。現(xiàn)在todo有了userId字段,但我們還沒(méi)有User對(duì)象,User的json表現(xiàn)形式看起來(lái)應(yīng)該是這樣:

{"id": 1,"username": "wang","password": "1234"}

當(dāng)然這個(gè)表現(xiàn)形式有很多問(wèn)題,比如密碼是明文的,這些問(wèn)題我們先不管,但大概樣子是類似的。那么現(xiàn)在如果要建立User數(shù)據(jù)庫(kù)的話,我們應(yīng)該新建一個(gè)user-data.json

{"users": [{"id": 1,"username": "wang","password": "1234"},{"id": 2,"username": "peng","password": "5678"}] }

但這樣做的話感覺(jué)單獨(dú)為其建一個(gè)文件有點(diǎn)不值得,我們干脆把user和todo數(shù)據(jù)都放在一個(gè)文件吧,現(xiàn)在刪除./src/app/todo/todo-data.json刪除,在src\app下面新建一個(gè)data.json

//src\app\data.json {"todos": [{"id": "bf75769b-4810-64e9-d154-418ff2dbf55e","desc": "getting up","completed": false,"userId": 1},{"id": "5894a12f-dae1-5ab0-5761-1371ba4f703e","desc": "have breakfast","completed": true,"userId": 2},{"id": "0d2596c4-216b-df3d-1608-633899c5a549","desc": "go to school","completed": true,"userId": 1},{"id": "0b1f6614-1def-3346-f070-d6d39c02d6b7","desc": "test","completed": false,"userId": 2},{"id": "c1e02a43-6364-5515-1652-a772f0fab7b3","desc": "This is a te","completed": false,"userId": 1}],"users": [{"id": 1,"username": "wang","password": "1234"},{"id": 2,"username": "peng","password": "5678"}] }

當(dāng)然有了數(shù)據(jù),我們就得有對(duì)應(yīng)的對(duì)象,基于同樣的理由,我們把所有的entity對(duì)象都放在一個(gè)文件:刪除src\app\todo\todo.model.ts,在src\app下新建一個(gè)目錄domain,然后在domain下新建一個(gè)entities.ts,請(qǐng)別忘了更新所有的引用。

export class Todo {id: string;desc: string;completed: boolean;userId: number; } export class User {id: number;username: string;password: string; }

驗(yàn)證用戶賬戶的流程

我們來(lái)梳理一下用戶驗(yàn)證的流程

  • 存儲(chǔ)要訪問(wèn)的URL

  • 根據(jù)本地的已登錄標(biāo)識(shí)判斷是否此用戶已經(jīng)登錄,如果已登錄就直接放行

  • 如果未登錄導(dǎo)航到登錄頁(yè)面 用戶填寫用戶名和密碼進(jìn)行登錄

  • 系統(tǒng)根據(jù)用戶名查找用戶表中是否存在此用戶,如果不存在此用戶,返回錯(cuò)誤

  • 如果存在對(duì)比填寫的密碼和存儲(chǔ)的密碼是否一致,如果不一致,返回錯(cuò)誤

  • 如果一致,存儲(chǔ)此用戶的已登錄標(biāo)識(shí)到本地

  • 導(dǎo)航到原本要訪問(wèn)的URL即第一步中存儲(chǔ)的URL,刪掉本地存儲(chǔ)的URL

  • 看上去我們需要實(shí)現(xiàn)

    • UserService:用于通過(guò)用戶名查找用戶并返回用戶

    • AuthService:用于認(rèn)證用戶,其中需要利用UserService的方法

    • AuthGuard:路由攔截器,用于攔截到路由后通過(guò)AuthService來(lái)知道此用戶是否有權(quán)限訪問(wèn)該路由,根據(jù)結(jié)果導(dǎo)航到不同路徑。
      看到這里,你可能有些疑問(wèn),為什么我們不把UserService和AuthService合并呢?這是因?yàn)閁serService是用于對(duì)用戶的操作的,不光認(rèn)證流程需要用到它,我們未來(lái)要實(shí)現(xiàn)的一系列功能都要用到它,比如注冊(cè)用戶,后臺(tái)用戶管理,以及主頁(yè)要顯示用戶名稱等。

    核心模塊

    根據(jù)這個(gè)邏輯流程,我們來(lái)組織一下代碼。開始之前我們想把認(rèn)證相關(guān)的代碼組織在一個(gè)新的模塊下,我們暫時(shí)叫它c(diǎn)ore吧。在src\app下新建一個(gè)core目錄,然后在core下面新建一個(gè)core.module.ts

    import { ModuleWithProviders, NgModule, Optional, SkipSelf } from '@angular/core'; import { CommonModule } from '@angular/common'; @NgModule({imports: [CommonModule] }) export class CoreModule {constructor (@Optional() @SkipSelf() parentModule: CoreModule) {if (parentModule) {throw new Error('CoreModule is already loaded. Import it in the AppModule only');}}

    注意到這個(gè)模塊和其他模塊不太一樣,原因是我們希望只在應(yīng)用啟動(dòng)時(shí)導(dǎo)入它一次,而不會(huì)在其它地方導(dǎo)入它。在模塊的構(gòu)造函數(shù)中我們會(huì)要求Angular把CoreModule注入自身,這看起來(lái)像一個(gè)危險(xiǎn)的循環(huán)注入。不過(guò),@SkipSelf裝飾器意味著在當(dāng)前注入器的所有祖先注入器中尋找CoreModule。如果該構(gòu)造函數(shù)在我們所期望的AppModule中運(yùn)行,就沒(méi)有任何祖先注入器能夠提供CoreModule的實(shí)例,于是注入器會(huì)放棄查找。默認(rèn)情況下,當(dāng)注入器找不到想找的提供商時(shí),會(huì)拋出一個(gè)錯(cuò)誤。 但@Optional裝飾器表示找不到該服務(wù)也無(wú)所謂。 于是注入器會(huì)返回null,parentModule參數(shù)也就被賦成了空值,而構(gòu)造函數(shù)沒(méi)有任何異常。
    那么我們?cè)谑裁磿r(shí)候會(huì)需要這樣一個(gè)模塊?比如在這個(gè)模塊中我們可能會(huì)要提供用戶服務(wù)(UserService),這樣的服務(wù)系統(tǒng)各個(gè)地方都需要,但我們不希望它被創(chuàng)建多次,希望它是一個(gè)單例。再比如某些只應(yīng)用于AppComponent模板的一次性組件,沒(méi)有必要共享它們,然而如果把它們留在根目錄,還是顯得太亂了。我們可以通過(guò)這種形式隱藏它們的實(shí)現(xiàn)細(xì)節(jié)。然后通過(guò)根模塊AppModule導(dǎo)入CoreModule來(lái)獲取其能力。

    路由守衛(wèi)

    首先我們來(lái)看看Angular內(nèi)建的路由守衛(wèi)機(jī)制,在實(shí)際工作中我們常常會(huì)碰到下列需求:

    • 該用戶可能無(wú)權(quán)導(dǎo)航到目標(biāo)組件。 導(dǎo)航前需要用戶先登錄(認(rèn)證)。

    • 在顯示目標(biāo)組件前,我們可能得先獲取某些數(shù)據(jù)。

    • 在離開組件前,我們可能要先保存修改。

    • 我們可能要詢問(wèn)用戶:你是否要放棄本次更改,而不用保存它們?

    我們可以往路由配置中添加守衛(wèi),來(lái)處理這些場(chǎng)景。守衛(wèi)返回true,導(dǎo)航過(guò)程會(huì)繼續(xù);返回false,導(dǎo)航過(guò)程會(huì)終止,且用戶會(huì)留在原地(守衛(wèi)還可以告訴路由器導(dǎo)航到別處,這樣也取消當(dāng)前的導(dǎo)航)。

    路由器支持多種守衛(wèi):

    • 用CanActivate來(lái)處理導(dǎo)航到某路由的情況。

    • 用CanActivateChild處理導(dǎo)航到子路由的情況。

    • 用CanDeactivate來(lái)處理從當(dāng)前路由離開的情況。

    • 用Resolve在路由激活之前獲取路由數(shù)據(jù)。

    • 用CanLoad來(lái)處理異步導(dǎo)航到某特性模塊的情況。

    在分層路由的每個(gè)級(jí)別上,我們都可以設(shè)置多個(gè)守衛(wèi)。路由器會(huì)先按照從最深的子路由由下往上檢查的順序來(lái)檢查CanDeactivate守護(hù)條件。然后它會(huì)按照從上到下的順序檢查CanActivate守衛(wèi)。如果任何守衛(wèi)返回false,其它尚未完成的守衛(wèi)會(huì)被取消,這樣整個(gè)導(dǎo)航就被取消了。

    本例中我們希望用戶未登錄前不能訪問(wèn)todo,那么需要使用CanActivate

    import { AuthGuardService } from '../core/auth-guard.service'; const routes: Routes = [{path: 'todo/:filter',canActivate: [AuthGuardService],component: TodoComponent} ];

    當(dāng)然光這么寫是沒(méi)有用的,下面我們來(lái)建立一個(gè)AuthGuardService,命令行中鍵入ng g s core/auth-guard(angular-cli對(duì)于Camel寫法的文件名是采用-來(lái)分隔每個(gè)大寫的詞)。

    import { Injectable, Inject } from '@angular/core'; import {CanActivate,Router,ActivatedRouteSnapshot,RouterStateSnapshot } from '@angular/router';@Injectable() export class AuthGuardService implements CanActivate {constructor(private router: Router) { }canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {//取得用戶訪問(wèn)的URLlet url: string = state.url;return this.checkLogin(url);}checkLogin(url: string): boolean {//如果用戶已經(jīng)登錄就放行if (localStorage.getItem('userId') !== null) { return true; }//否則,存儲(chǔ)要訪問(wèn)的URl到本地localStorage.setItem('redirectUrl', url);//然后導(dǎo)航到登陸頁(yè)面this.router.navigate(['/login']);//返回false,取消導(dǎo)航return false;} }

    觀察上面代碼,我們發(fā)現(xiàn)本地存儲(chǔ)的userId的存在與否決定了用戶是否已登錄的狀態(tài),這當(dāng)然是一個(gè)漏洞百出的實(shí)現(xiàn),但我們暫且不去管它。現(xiàn)在我們要在登錄時(shí)把這個(gè)狀態(tài)值寫進(jìn)去。我們新建一個(gè)登錄鑒權(quán)的AuthService:ng g s core/auth

    import { Injectable, Inject } from '@angular/core'; import { Http, Headers, Response } from '@angular/http';import 'rxjs/add/operator/toPromise'; import { Auth } from '../domain/entities';@Injectable() export class AuthService {constructor(private http: Http, @Inject('user') private userService) { }loginWithCredentials(username: string, password: string): Promise<Auth> {return this.userService.findUser(username).then(user => {let auth = new Auth();localStorage.removeItem('userId');let redirectUrl = (localStorage.getItem('redirectUrl') === null)?'/': localStorage.getItem('redirectUrl');auth.redirectUrl = redirectUrl;if (null === user){auth.hasError = true;auth.errMsg = 'user not found';} else if (password === user.password) {auth.user = Object.assign({}, user);auth.hasError = false;localStorage.setItem('userId',user.id);} else {auth.hasError = true;auth.errMsg = 'password not match';}return auth;}).catch(this.handleError);}private handleError(error: any): Promise<any> {console.error('An error occurred', error); // for demo purposes onlyreturn Promise.reject(error.message || error);} }

    注意到我們返回了一個(gè)Auth對(duì)象,這是因?yàn)槲覀円缼准?#xff1a;

    • 用戶最初要導(dǎo)航的頁(yè)面URL

    • 用戶對(duì)象

    • 如果發(fā)生錯(cuò)誤的話,是什么錯(cuò)誤,我們需要反饋給用戶

    這個(gè)Auth對(duì)象同樣在src\app\domain\entities.ts中聲明

    export class Auth {user: User;hasError: boolean;errMsg: string;redirectUrl: string; }

    當(dāng)然我們還得實(shí)現(xiàn)UserService:ng g s user

    import { Injectable } from '@angular/core';import { Http, Headers, Response } from '@angular/http';import 'rxjs/add/operator/toPromise'; import { User } from '../domain/entities';@Injectable() export class UserService {private api_url = 'http://localhost:3000/users';constructor(private http: Http) { }findUser(username: string): Promise<User> {const url = `${this.api_url}/?username=${username}`;return this.http.get(url).toPromise().then(res => {let users = res.json() as User[];return (users.length>0)?users[0]:null;}).catch(this.handleError);}private handleError(error: any): Promise<any> {console.error('An error occurred', error); // for demo purposes onlyreturn Promise.reject(error.message || error);} }

    這段代碼比較簡(jiǎn)單,就不細(xì)講了。下面我們改造一下src\app\login\login.component.html,在原來(lái)用戶名的驗(yàn)證信息下加入,用于顯示用戶不存在或者密碼不對(duì)的情況

    <div *ngIf="usernameRef.errors?.required">this is required</div><div *ngIf="usernameRef.errors?.minlength">should be at least 3 charactors</div><!--add the code below--><div *ngIf="auth?.hasError">{{auth.errMsg}}</div>

    當(dāng)然我們還得改造src\app\login\login.component.ts

    import { Component, OnInit, Inject } from '@angular/core'; import { Router, ActivatedRoute, Params } from '@angular/router';import { Auth } from '../domain/entities';@Component({selector: 'app-login',templateUrl: './login.component.html',styleUrls: ['./login.component.css'] }) export class LoginComponent implements OnInit {username = '';password = '';auth: Auth;constructor(@Inject('auth') private service, private router: Router) { }ngOnInit() {}onSubmit(formValue){this.service.loginWithCredentials(formValue.login.username, formValue.login.password).then(auth => {let redirectUrl = (auth.redirectUrl === null)? '/': auth.redirectUrl;if(!auth.hasError){this.router.navigate([redirectUrl]);localStorage.removeItem('redirectUrl');} else {this.auth = Object.assign({}, auth);}});} }

    然后我們別忘了在core模塊中聲明我們的服務(wù)src\app\core\core.module.ts

    import { ModuleWithProviders, NgModule, Optional, SkipSelf } from '@angular/core'; import { CommonModule } from '@angular/common'; import { AuthService } from './auth.service'; import { UserService } from './user.service'; import { AuthGuardService } from './auth-guard.service'; @NgModule({imports: [CommonModule],providers: [{ provide: 'auth', useClass: AuthService },{ provide: 'user', useClass: UserService },AuthGuardService] }) export class CoreModule {constructor (@Optional() @SkipSelf() parentModule: CoreModule) {if (parentModule) {throw new Error('CoreModule is already loaded. Import it in the AppModule only');}} }

    最后我們得改寫一下TodoService,因?yàn)槲覀冊(cè)L問(wèn)的URL變了,要傳遞的數(shù)據(jù)也有些變化

    //todo.service.ts代碼片段// POST /todosaddTodo(desc:string): Promise<Todo> {//“+”是一個(gè)簡(jiǎn)易方法可以把string轉(zhuǎn)成numberconst userId:number = +localStorage.getItem('userId');let todo = {id: UUID.UUID(),desc: desc,completed: false,userId};return this.http.post(this.api_url, JSON.stringify(todo), {headers: this.headers}).toPromise().then(res => res.json() as Todo).catch(this.handleError);}// GET /todosgetTodos(): Promise<Todo[]>{const userId = +localStorage.getItem('userId');const url = `${this.api_url}/?userId=${userId}`;return this.http.get(url).toPromise().then(res => res.json() as Todo[]).catch(this.handleError);}// GET /todos?completed=true/falsefilterTodos(filter: string): Promise<Todo[]> {const userId:number = +localStorage.getItem('userId');const url = `${this.api_url}/?userId=${userId}`;switch(filter){case 'ACTIVE': return this.http.get(`${url}&completed=false`).toPromise().then(res => res.json() as Todo[]).catch(this.handleError);case 'COMPLETED': return this.http.get(`${url}&completed=true`).toPromise().then(res => res.json() as Todo[]).catch(this.handleError);default:return this.getTodos();}}

    現(xiàn)在應(yīng)該已經(jīng)ok了,我們來(lái)看看效果:
    用戶密碼不匹配時(shí),顯示password not match

    用戶不存在時(shí),顯示user not found

    直接在瀏覽器地址欄輸入http://localhost:4200/todo,你會(huì)發(fā)現(xiàn)被重新導(dǎo)航到了login。輸入正確的用戶名密碼后,我們被導(dǎo)航到了todo,現(xiàn)在每個(gè)用戶都可以創(chuàng)建屬于自己的待辦事項(xiàng)了。

    路由模塊化

    Angular團(tuán)隊(duì)推薦把路由模塊化,這樣便于使業(yè)務(wù)邏輯和路由松耦合。雖然目前在我們的應(yīng)用中感覺(jué)用處不大,但按官方推薦的方式還是和大家一起改造一下吧。刪掉原有的app.routes.ts和todo.routes.ts。添加app-routing.module.ts:

    import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; import { LoginComponent } from './login/login.component';const routes: Routes = [{path: '',redirectTo: 'login',pathMatch: 'full'},{path: 'login',component: LoginComponent},{path: 'todo',redirectTo: 'todo/ALL'} ];@NgModule({imports: [RouterModule.forRoot(routes)],exports: [RouterModule] }) export class AppRoutingModule {}

    以及src\app\todo\todo-routing.module.ts

    import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; import { TodoComponent } from './todo.component';import { AuthGuardService } from '../core/auth-guard.service';const routes: Routes = [{path: 'todo/:filter',canActivate: [AuthGuardService],component: TodoComponent} ];@NgModule({imports: [ RouterModule.forChild(routes) ],exports: [ RouterModule ] }) export class TodoRoutingModule { }

    并分別在AppModule和TodoModule中引入路由模塊。

    用VSCode進(jìn)行調(diào)試

    有讀者問(wèn)如何用vscode進(jìn)行debug,這章我們來(lái)介紹一下。首先需要安裝一個(gè)vscode插件,點(diǎn)擊左側(cè)最下面的圖標(biāo)或者“在查看菜單中選擇命令面板,輸入install,選擇擴(kuò)展:安裝擴(kuò)展”,然后輸入“debugger for chrome”回車,點(diǎn)擊安裝即可。

    然后點(diǎn)擊最左邊的倒數(shù)第二個(gè)按鈕

    如果是第一次使用的話,齒輪圖標(biāo)上會(huì)有個(gè)紅點(diǎn),點(diǎn)擊選擇debugger for chrome,vscode會(huì)幫你創(chuàng)建一個(gè)配置文件,這個(gè)文件位于\.vscode\launch.json是debugger的配置文件,請(qǐng)改寫成下面的樣子。注意如果是MacOSX或者Linux,請(qǐng)把userDataDir替換成對(duì)應(yīng)的臨時(shí)目錄,另外把"webpack:///C:*":"C:/*"替換成"webpack:///*": "/*",這句是因?yàn)閍ngular-cli是采用webpack打包的,如果沒(méi)有使用angular-cli不需要添加這句。

    {"version": "0.2.0","configurations": [{"name": "Launch Chrome against localhost, with sourcemaps","type": "chrome","request": "launch","url": "http://localhost:4200","sourceMaps": true,"runtimeArgs": ["--disable-session-crashed-bubble","--disable-infobars"],"diagnosticLogging": true,"webRoot": "${workspaceRoot}/src",//windows setup"userDataDir": "C:\\temp\\chromeDummyDir","sourceMapPathOverrides": {"webpack:///C:*":"C:/*"//use "webpack:///*": "/*" on Linux/OSX}},{"name": "Attach to Chrome, with sourcemaps","type": "chrome","request": "attach","port": 9222,"sourceMaps": true,"diagnosticLogging": true,"webRoot": "${workspaceRoot}/src","sourceMapPathOverrides": {"webpack:///C:*":"C:/*"}}] }

    現(xiàn)在你可以試著在源碼中設(shè)置一個(gè)斷點(diǎn),點(diǎn)擊debug視圖中的debug按鈕,可以嘗試右鍵點(diǎn)擊變量把它放到監(jiān)視中看看變量值或者逐步調(diào)試應(yīng)用。

    本章完整代碼見: https://github.com/wpcfan/awe...

    第一節(jié):Angular 2.0 從0到1 (一)
    第二節(jié):Angular 2.0 從0到1 (二)
    第三節(jié):Angular 2.0 從0到1 (三)
    第四節(jié):Angular 2.0 從0到1 (四)
    第五節(jié):Angular 2.0 從0到1 (五)

    總結(jié)

    以上是生活随笔為你收集整理的Angular 2.x 从0到1 (五)史上最简单的Angular2教程的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。