如何使用ui-router


如何使用ui-router?_騰訊視頻



【JS-6】

如何使用ui-router?

小課堂【武漢分院第137期】

分享人:徐恒

目錄

1.背景介紹

2.知識(shí)剖析

3.常見問題

4.解決方案

5.編碼實(shí)戰(zhàn)

6.擴(kuò)展思考

7.參考文獻(xiàn)

8.更多討論

一.背景介紹

angular路由

路由(route),幾乎所有的MVC(VM)框架都應(yīng)該具有的特性,因?yàn)樗乔岸藰?gòu)建單頁面應(yīng)用(SPA)必不可少的組成部分。

那么,對(duì)于angular而言,它自然也有內(nèi)置的路由模塊:叫做ngRoute。

不過,大家很少用它,因?yàn)樗墓δ芴邢蓿荒軡M足開發(fā)需求!!

于是,一個(gè)基于ngRoute開發(fā)的第三方路由模塊,叫做ui.router,受到了大家的“追捧”。

ngRoute vs ui.router

首先,無論是使用哪種路由,作為框架額外的附加功能,它們都將以模塊依賴的形式被引入,簡而言之就是:在引入路由源文件之后,你的代碼應(yīng)該這樣寫(以u(píng)i.router為例):

angular.module("myApp", ["ui.router"]); // myApp為自定義模塊,依賴第三方路由模塊ui.router

這樣做的目的是:在程序啟動(dòng)(bootstrap)的時(shí)候,加載依賴模塊(如:ui.router),將所有掛載在該模塊的服務(wù)(provider),指令(directive),過濾器(filter)等都進(jìn)行注冊(cè),那么在后面的程序中便可以調(diào)用了。

說到這里,就得看看ngRoute模塊和ui.router模塊各自都提供了哪些服務(wù),哪些指令?

ngRoute

$routeProvider(服務(wù)提供者) ——— 對(duì)應(yīng)于下面的urlRouterProvider和stateProvider

$route(服務(wù)) ——— 對(duì)應(yīng)于下面的urlRouter和state

$routeParams(服務(wù)) ——— 對(duì)應(yīng)于下面的stateParams

ng-view(指令) ——— 對(duì)應(yīng)于下面的ui-view

ui.router

$urlRouterProvider(服務(wù)提供者) ——— 用來配置路由重定向

$urlRouter(服務(wù))

$stateProvider(服務(wù)提供者) ——— 用來配置路由

$state(服務(wù)) ——— 用來顯示當(dāng)前路由狀態(tài)信息,以及一些路由方法(如:跳轉(zhuǎn))

$stateParams(服務(wù)) ——— 用來存儲(chǔ)路由匹配時(shí)的參數(shù)

ui-view(指令) ——— 路由模板渲染,對(duì)應(yīng)的dom相關(guān)聯(lián)

ui-sref(指令)

(注:服務(wù)提供者:用來提供服務(wù)實(shí)例和配置服務(wù)。)

這樣一看,其實(shí)ui.router和ngRoute大體的設(shè)計(jì)思路,對(duì)應(yīng)的模塊劃分都是一致的(畢竟是同一個(gè)團(tuán)隊(duì)開發(fā)),不同的地方在于功能點(diǎn)的實(shí)現(xiàn)和增強(qiáng)。

那么問題來了:ngRoute弱在哪些方面,ui.router怎么彌補(bǔ)了這些方面?

這里,列舉兩個(gè)最重要的方面來說(其他細(xì)節(jié),后面再說):

多視圖

嵌套視圖

多視圖

多視圖:頁面可以顯示多個(gè)動(dòng)態(tài)變化的不同區(qū)塊。

這樣的業(yè)務(wù)場景是有的:

比如:頁面一個(gè)區(qū)塊用來顯示頁面狀態(tài),另一個(gè)區(qū)塊用來顯示頁面主內(nèi)容,當(dāng)路由切換時(shí),頁面狀態(tài)跟著變化,對(duì)應(yīng)的頁面主內(nèi)容也跟著變化。

首先,我們嘗試著用ngRoute來做:

html

區(qū)塊1

區(qū)塊2

js$routeProvider? ? .when('/', {? ? ? ? template: 'hello world'? ? });

我們?cè)趆tml中利用ng-view指令定義了兩個(gè)區(qū)塊,于是兩個(gè)div中顯示了相同的內(nèi)容,這很合乎情理,但卻不是我們想要的,但是又不能為力,因?yàn)椋趎gRoute中:

視圖沒有名字進(jìn)行唯一標(biāo)志,所以它們被同等的處理。

路由配置只有一個(gè)模板,無法配置多個(gè)。

ok,針對(duì)上述兩個(gè)問題,我們嘗試用ui.router來做:

html

js$stateProvider? ? .state('home', {? ? ? ? url: '/',? ? ? ? views: {? ? ? ? ? ? '': {? ? ? ? ? ? ? ? template: 'hello world'? ? ? ? ? ? },? ? ? ? ? ? 'status': {? ? ? ? ? ? ? ? template: 'home page'? ? ? ? ? ? }? ? ? ? }? ? });

這次,結(jié)果是我們想要的,兩個(gè)區(qū)塊,分別顯示了不同的內(nèi)容,原因在于,在ui.router中:

可以給視圖命名,如:ui-view=”status”。

可以在路由配置中根據(jù)視圖名字(如:status),配置不同的模板(其實(shí)還有controller等)。

注:視圖名是一個(gè)字符串,不可以包含@(原因后面會(huì)說)。

嵌套視圖

嵌套視圖:頁面某個(gè)動(dòng)態(tài)變化區(qū)塊中,嵌套著另一個(gè)可以動(dòng)態(tài)變化的區(qū)塊。

這樣的業(yè)務(wù)場景也是有的:

比如:頁面一個(gè)主區(qū)塊顯示主內(nèi)容,主內(nèi)容中的部分內(nèi)容要求根據(jù)路由變化而變化,這時(shí)就需要另一個(gè)動(dòng)態(tài)變化的區(qū)塊嵌套在主區(qū)塊中。

其實(shí),嵌套視圖,在html中的最終表現(xiàn)就像這樣:

I am parent

I am child

轉(zhuǎn)成javascript,我們會(huì)在程序里這樣寫:$routeProvider? ? .when('/', {? ? ? ? template: 'I am parent

I am child

'? ? });

倘若,你真的用ngRoute這樣寫,你會(huì)發(fā)現(xiàn)瀏覽器崩潰了,因?yàn)樵趎g-view指令link的過程中,代碼會(huì)無限遞歸下去。

那么造成這種現(xiàn)象的最根本原因:路由沒有明確的父子層級(jí)關(guān)系!

看看ui.router是如何解決這一問題的?

$stateProvider? ? .state('parent', {? ? ? ? abstract: true,? ? ? ? url: '/',? ? ? ? template: 'I am parent

'? ? })? ? .state('parent.child', {? ? ? ? url: '',? ? ? ? template: 'I am child'? ? });

巧妙地,通過parent與parent.child來確定路由的父子關(guān)系,從而解決無限遞歸問題。

另外子路由的模板最終也將被插入到父路由模板的div[ui-view]中去,從而達(dá)到視圖嵌套的效果。

記住下面是ui.router用到的所有指令

ui.router

$urlRouterProvider(服務(wù)提供者) ——— 用來配置路由重定向

$urlRouter(服務(wù))

$stateProvider(服務(wù)提供者) ——— 用來配置路由

$state(服務(wù)) ——— 用來顯示當(dāng)前路由狀態(tài)信息,以及一些路由方法(如:跳轉(zhuǎn))

$stateParams(服務(wù)) ——— 用來存儲(chǔ)路由匹配時(shí)的參數(shù)

ui-view(指令) ——— 路由模板渲染,對(duì)應(yīng)的dom相關(guān)聯(lián)

ui-sref(指令)

初級(jí)應(yīng)用(會(huì)用就行)

介紹用這個(gè)例子($urlRouter和$stateParams沒用到,其他都用到:$urlRouterProvider,$stateProvider,$state,ui-view,ui-sref)

var photoGallery = angular.module('photoGallery',["ui.router"]);

photoGallery.config(function($stateProvider, $urlRouterProvider){

$urlRouterProvider.otherwise('/home');

$stateProvider

.state('home',{

url: '/home',

templateUrl: 'partials/home.html'

})

.state('photos',{

url: '/photos',

templateUrl: 'partials/photos.html'

})

.state('about',{

url: '/about',

templateUrl: 'partials/about.html'

})

})

首先給大家介紹angular-ui-router的基本用法。

如何引用依賴angular-ui-router就是

再從簡單的開始(其實(shí)這幾個(gè)服務(wù)也都是有依賴的,例如$urlRouterProvider依賴$urlMatcherFactoryProvider? $locationProvider。$urlRouterProvider依賴$urlRouterProvider $urlMatcherFactoryProvider。但初級(jí)應(yīng)用這不展開,只講要用到某幾個(gè)方法(不是全部))

$urlRouteProvider(總共3個(gè)when,otherwise和rule)這里懂when和otherwise就行。

$urlRouteProvider.when(whenPath, toPath)

為給定的URL匹配注冊(cè)一個(gè)處理程序。

$urlRouterProvider.otherwise(path)

定義一個(gè)當(dāng)請(qǐng)求的路徑是無效路徑時(shí)跳轉(zhuǎn)的路徑。

例子:就用到一種情況(當(dāng)請(qǐng)求的路徑是無效路徑時(shí)跳轉(zhuǎn)的路徑)

$urlRouterProvider

.otherwise('/login');

// .when("","/login");

$stateProvider(總共2個(gè)方法:decorator和state。但這里只講state(state這個(gè)里面的配置也不講全的,只講幾個(gè)暫時(shí)用到的))

處理路由狀態(tài)的服務(wù),路由的狀態(tài)反映了該項(xiàng)在應(yīng)用程序中的位置,描述了在當(dāng)前狀態(tài)下UI是應(yīng)該怎么樣的,并且該做什么。

方法:

state(name,stateConfig);

注冊(cè)一個(gè)狀態(tài),并給定其配置。

//state可以有子父級(jí)

$stateProvider.state("home",{});

$stateProvider.state("home.child",{})

//state可以是鏈?zhǔn)降?/p>

$stateProvider.state("home",{}).state("about",{}).state("photos",{});

參數(shù):

name:狀態(tài)的名稱。

stateConfig:狀態(tài)配置對(duì)象。配置具有以下各項(xiàng)屬性(全部屬性,看一下好了):

template: string/function,html模板字符串,或者一個(gè)返回html模板字符串的函數(shù)。

templateUrl:string/function,模板路徑的字符串,或者返回模板路徑字符串的函數(shù)。

templateProvider:function,返回html模板字符串或模板路徑的服務(wù)。

controller:string/function,新注冊(cè)一個(gè)控制器函數(shù)或者一個(gè)已注冊(cè)的控制器的名稱字符串。

controllerProvider:function,返回控制器或者控制器名稱的服務(wù)

controllerAs:string,控制器別名。

parent:string/object,手動(dòng)指定該狀態(tài)的父級(jí)。

resolve:object,將會(huì)被注入controller去執(zhí)行的函數(shù),string,function>形式。

url:string,當(dāng)前狀態(tài)的對(duì)應(yīng)url。

views:object,視圖展示的配置。string,object>形式。

abstract:boolean,一個(gè)永遠(yuǎn)不會(huì)被激活的抽象的狀態(tài),但可以給其子級(jí)提供特性的繼承。默認(rèn)是true。

onEnter:function,當(dāng)進(jìn)入一個(gè)狀態(tài)后的回調(diào)函數(shù)。

onExit:function,當(dāng)退出一個(gè)狀態(tài)后的回調(diào)函數(shù)。

reloadOnSearch:boolean,如果為false,那么當(dāng)一個(gè)search/query參數(shù)改變時(shí)不會(huì)觸發(fā)相同的狀態(tài),用于當(dāng)你修改$location.search()的時(shí)候不想重新加載頁面。默認(rèn)為true。

data:object,任意對(duì)象數(shù)據(jù),用于自定義配置。繼承父級(jí)狀態(tài)的data屬性。換句話說,通過原型繼承可以達(dá)到添加一個(gè)data數(shù)據(jù)從而整個(gè)樹結(jié)構(gòu)都能獲取到。

params:url里的參數(shù)值,通過它可以實(shí)現(xiàn)頁面間的參數(shù)傳遞。

這里用到了

url:string,當(dāng)前狀態(tài)的對(duì)應(yīng)url。

params:url里的參數(shù)值,通過它可以實(shí)現(xiàn)頁面間的參數(shù)傳遞。

template: string/function,html模板字符串,或者一個(gè)返回html模板字符串的函數(shù)。

templateUrl:string/function,模板路徑的字符串,或者返回模板路徑字符串的函數(shù)。

resolve:object,將會(huì)被注入controller去執(zhí)行的函數(shù),string,function形式。

例子:

$stateProvider

.state("login",{

url: "/login",

templateUrl: "tpls/login.html",

resolve:{

load:['$ocLazyLoad',function($ocLazyLoad){

return $ocLazyLoad.load([

'css/login.css',

'js/login.js'

]);

}]

}

})

進(jìn)一步

.state("main.article-list",{

url: "/article-list/:page/:size/:startAt/:endAt/:type/:status",

params:{'page':"1",'size':"10"},

templateUrl: "tpls/article-list.html",

resolve:{

load:['$ocLazyLoad',function($ocLazyLoad){

return $ocLazyLoad.load([

'css/article-list.css',

'js/article-list.js'

]);

}]

}

})

再說下

$state(總共6個(gè)方法和1個(gè)事件:go,href,include,is,reload,transitionTo和事件:$stateChangeError,$stateChangeStart,$stateChangeSuccess和$stateNotFound。這里只要會(huì)go就行)

$state服務(wù)負(fù)責(zé)代表狀態(tài)及提供狀態(tài)之間的轉(zhuǎn)換。它還提供你當(dāng)前的狀態(tài)及上一個(gè)狀態(tài)。

方法:

go(to,params,options);

參數(shù):

to:string,即將跳轉(zhuǎn)的狀態(tài)。

params:object,跳轉(zhuǎn)所帶的參數(shù)。

options:object,可選配置對(duì)象。有 location(是否更新地址欄的url,或以什么字符串替換url),inherit(是否繼承當(dāng)前url的參數(shù)),relative(當(dāng)變化相對(duì)路徑:如"^,定義的狀態(tài)是相對(duì)的),notify(是否廣播$stateChangeStart和$stateChangeSuccess事件),reload(是否重新載入)。

實(shí)例:

$state.go("login");

跳轉(zhuǎn)到在前面中定義的狀態(tài)那里

$stateProvider

.state("login",{})

然后就是^和.的用法區(qū)別,一個(gè)是向上一級(jí),一個(gè)向下一級(jí)

$state.go('photos.detail')

$state.go('^')到上一級(jí),比如從photo.detail到photo

$state.go('^.list')到相鄰state,比如從photo.detail到photo.list

$state.go('^.detail.comment')到孫子級(jí)state,比如從photo.detail到photo.detial.comment

ui-sref(2種,一種不帶參數(shù),一種帶)

一種將鏈接(a標(biāo)簽)綁定到一個(gè)狀態(tài)的指令。點(diǎn)擊該鏈接將觸發(fā)一個(gè)可以帶有可選參數(shù)的狀態(tài)轉(zhuǎn)換。

ui-sref="stateName"ui-sref="stateName({param:value,param:value})"代碼:首頁你的主頁

ui-view

一種是沒有名字的

一種是有名字的

來一個(gè)demo1

項(xiàng)目文件結(jié)構(gòu)

node_modules/ //這里放各種依賴

partials/? ? //這里放跳的頁面

.....about.html

.....home.html

.....photos.html

app.js? ? ? //寫router

index.html

index.html文件? 就是一個(gè)導(dǎo)航欄(注意這里有ui-sref的跳轉(zhuǎn))+一個(gè)ui-view(當(dāng)然是跳轉(zhuǎn)后的各個(gè)頁面的東西)+依賴

Home

Photos

About

app.js? 寫的ui.router

var photoGallery = angular.module('photoGallery',["ui.router"]);

photoGallery.config(function($stateProvider, $urlRouterProvider){

$urlRouterProvider.otherwise('/home');

$stateProvider

.state('home',{

url: '/home',

templateUrl: 'partials/home.html'

})

.state('photos',{

url: '/photos',

templateUrl: 'partials/photos.html'

})

.state('about',{

url: '/about',

templateUrl: 'partials/about.html'

})

})

更進(jìn)一步就是task6-10(低版本)

router.js

var myApp = angular.module("myApp",['ui.router','oc.lazyLoad','ngMessages','tm.pagination']);

myApp.config(function ($stateProvider,$urlRouterProvider) {

$urlRouterProvider

.otherwise('/login');

// .when("","/login");

$stateProvider

.state("main.article-list",{

url: "/article-list/:page/:size/:startAt/:endAt/:type/:status",

params:{'page':"1",'size':"10"},

templateUrl: "tpls/article-list.html",

resolve:{

load:['$ocLazyLoad',function($ocLazyLoad){

return $ocLazyLoad.load([

'css/article-list.css',

'js/article-list.js'

]);

}]

}

})

});

上面用到了url的參數(shù),params的參數(shù),以及resolve。當(dāng)然后面會(huì)用到$stateParams。

url中的/:page/:size/在params中初始化,然后傳參數(shù)過去。resolve中的是懶加載。

上面URL傳過來的參數(shù)在article-list.js中用到(分頁插件用的),通過$stateParams獲取。

article-list.js

var listApp = angular.module("myApp",[]);

listApp.controller("listCtrl",['$scope','$http','$state','$stateParams',function ($scope,$http,$state,$stateParams) {

// 分頁部分

$scope.paginationConf = {

showFlag:0,

// 當(dāng)前頁

currentPage: 1,

// 每頁默認(rèn)

itemsPerPage: 10,

// 點(diǎn)擊每個(gè)分頁按鈕都會(huì)觸發(fā)這個(gè)函數(shù),然后刷新加載

onChange:function () {

console.log('$scope.paginationConf.currentPage=' );

console.log($scope.paginationConf.currentPage );

console.log('$scope.paginationConf.itemsPerPage=');

console.log($scope.paginationConf.itemsPerPage);

$state.go('main.article-list', {

page: $scope.paginationConf.currentPage ,

size: $scope.paginationConf.itemsPerPage

}, {reload: true});

}};

console.log('$stateParams=' );

console.log($stateParams );

$scope.paginationConf.currentPage = $stateParams.page ;

$scope.paginationConf.itemsPerPage = $stateParams.size ;

二.知識(shí)剖析

三.常見問題

四.解決方案

五.代碼實(shí)戰(zhàn)

六.拓展思考

七.參考文獻(xiàn)

ui.router源碼解析

AngularJS ui-router (嵌套路由)

angular的uiRouter服務(wù)學(xué)習(xí)

$stateParams服務(wù)

八.更多討論

鳴謝

感謝大家觀看

BY : 徐恒




1.ngRoute能做到多視圖嵌套么

2.ng-view能命名么

3.ui-router這么多參數(shù)常用的是那些?

4.還有哪些情況下是適合ngRoute使用的



------------------------------------------------------------------------------------------------------------------------

技能樹.IT修真院

“我們相信人人都可以成為一個(gè)工程師,現(xiàn)在開始,找個(gè)師兄,帶你入門,掌控自己學(xué)習(xí)的節(jié)奏,學(xué)習(xí)的路上不再迷茫”。

這里是技能樹.IT修真院,成千上萬的師兄在這里找到了自己的學(xué)習(xí)路線,學(xué)習(xí)透明化,成長可見化,師兄1對(duì)1免費(fèi)指導(dǎo)。快來與我一起學(xué)習(xí)吧 !

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,156評(píng)論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,401評(píng)論 3 415
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,069評(píng)論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,873評(píng)論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,635評(píng)論 6 408
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,128評(píng)論 1 323
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,203評(píng)論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,365評(píng)論 0 288
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,881評(píng)論 1 334
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,733評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,935評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,475評(píng)論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,172評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,582評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,821評(píng)論 1 282
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,595評(píng)論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,908評(píng)論 2 372

推薦閱讀更多精彩內(nèi)容