Vue.js教程: 構(gòu)建一個預(yù)渲染SEO友好的應(yīng)用示例 [譯]

作者:Maxime Laboissonniere
原文地址: Vue.js Tutorial: An Example to Build and Prerender an SEO-Friendly Site
譯者:jeneser

快速了解抠刺?直接前往教程步驟或Github倉庫&在線演示

“我受不了了!我們的內(nèi)部報告面板太爛了”

產(chǎn)品經(jīng)理很生氣灶壶。他從這個即將崩潰的應(yīng)用程序中拉取數(shù)據(jù)的操作是災(zāi)難性的。

“Max勋陪,我們需要更好的報告逆粹。你能修嗎?”

“老實說裤唠,我更愿意建立一個全新的應(yīng)用”砂客,我笑著回答說泥张。

“好,請便鞠值。全權(quán)委托媚创,老鐵”

我笑著,搓了搓手齿诉。最后筝野,在一個需要使用JS框架的場景中晌姚,大家一致選擇了Vue.js粤剧。


最近歇竟,我完成該應(yīng)用的代碼,我對它簡直愛不釋手抵恋。
我花了一些時間為社區(qū)寫了一個vue.js教程焕议,這些教程的靈感全部來自于我最近對vue的實踐。在這里弧关,我主要討論以下兩點:

  1. 如何使用Vue.js構(gòu)建精簡的Web應(yīng)用程序
  2. 如何使用prerender-spa-plugin來處理Vue.js應(yīng)用的預(yù)渲染與SEO

更具體地說盅安,我將帶您創(chuàng)建一個小商店,它將具備SEO友好的產(chǎn)品頁面世囊。我會提供在線演示以及相關(guān)代碼别瞭。
在我們開發(fā)的最新版Headless CMS中我接觸過一些vue,這一次我們會更加的深入株憾,我很興奮蝙寨!

更新:我們正在將Snipcart的前端從Backbone遷移到Vue.js,了解更多

我們先來為那些不熟悉漸進(jìn)式框架(Vue.js)的同學(xué)做一下簡單的介紹嗤瞎。

Vue.js到底是什么墙歪?

Vue.js

Vue.js是一套幫助你構(gòu)建用戶界面的輕量級,漸進(jìn)式的JavaScript框架

不要被“JS框架”這一定義所愚弄贝奇。Vue與目前流行的React.js & Angular.js是截然不同的虹菲。對于初學(xué)者來說,它不是Google&Facebook等商業(yè)技術(shù)巨頭的開源副產(chǎn)品掉瞳。

Evan You(尤雨溪)在2014年首次發(fā)布了它毕源,旨在創(chuàng)建一個“增量開發(fā)”的現(xiàn)代JS庫。Vue最強(qiáng)大的功能之一是:創(chuàng)建可復(fù)用的組件陕习,你可以在其他項目中重用這些組件而不用再次編寫霎褐。所有開發(fā)人員都可以在項目中嘗試Vue,而不用擔(dān)心這會對現(xiàn)有的代碼庫產(chǎn)生危害或是增加額外的負(fù)擔(dān)衡查。

拋開模式和術(shù)語瘩欺,我覺得Vue有以下提論:

1. 一開始你不知道整個應(yīng)用的架構(gòu)狀態(tài)
2. 應(yīng)用數(shù)據(jù)一定會在運行時發(fā)生改變

正是圍繞這些提論,vue塑造了自身:它是漸進(jìn)式拌牲,基于組件和響應(yīng)式的俱饿。組件的粒度劃分可以讓你輕松地分離應(yīng)用邏輯,同時又保持它們的可重用性塌忽。更重要的是拍埠,它將您的數(shù)據(jù)原生綁定到視圖,以便在需要時“神奇”地更新(通過watcher)土居。雖然許多響應(yīng)式前端框架擁有同樣的功能枣购,但是我發(fā)現(xiàn)Vue更優(yōu)雅的實現(xiàn)了它嬉探,并且,對于我的大多數(shù)用例棉圈,它往往表現(xiàn)的更好涩堤。

Vue還具有更加平滑的學(xué)習(xí)曲線,對于React來說分瘾,我們需要掌握J(rèn)SX模板等的相關(guān)知識胎围。甚至可以說Vue是React減去了比較復(fù)雜的部分。

Vue官方文檔提供了與其他JS框架(React, Angular, Ember, Knockout, Polymer, Riot)更加深入的對比德召。查看官方文檔

最后但同樣重要的是:得益于高性能&強(qiáng)大的開發(fā)工具白魂,Vue為我們提供了最佳的編碼體驗。它能如此流行也就不足為奇了!

vuejs流行度

從開源項目LaravelPageKit上岗,到企業(yè)福荸,如GitlabCodeship(更不用說阿里巴巴和百度這些巨頭了),許多組織正在使用Vue肴掷。

OK敬锐,現(xiàn)在是時候來看看我們將如何使用它了。

Vue.js例子:一個快速的捆等,搜索引擎友好的電子商務(wù)應(yīng)用

在本節(jié)中滞造,我會告訴你如何使用Vue 2.0 & Snipcart建立一個小型的電子商務(wù)應(yīng)用程序。我們還將看到如何確保產(chǎn)品頁面被搜索引擎正確“抓取”栋烤。

準(zhǔn)備

如果你想深入了解 Vue 2.0 相關(guān)知識明郭,可以查看Laracasts上的這個系列买窟。

1. 環(huán)境配置

首先,我們將使用vue-cli來構(gòu)建基本的Vue應(yīng)用程序薯定。在你喜歡的終端里始绍,輸入:

npm install -g vue-cli
vue init webpack-simple vue-snipcart

這將創(chuàng)建一個新的vue-snipcart文件夾,其中包含使用vue-loader的基本配置话侄,它將能使我們編寫單文件組件(template/js/css在同一個.vue文件中)亏推。

我們希望這個示例盡可能真實,因此年堆,我們將在本應(yīng)用中增加兩個廣泛應(yīng)用于大型項目的模塊:vuexvue-router吞杭。

  • vuex是類Flux架構(gòu)的狀態(tài)管理器 - 輕量級,非常強(qiáng)大变丧。它受到了Redux的影響芽狗,你可以在這里了解更多
  • vue-router允許您定義路由以動態(tài)處理應(yīng)用程序的組件痒蓬。

要安裝這些童擎,請先進(jìn)入vue-snipcart項目文件夾滴劲,然后運行以下命令:

npm install --save vue-router
npm install --save vuex

接下來要安裝的是prerender-spa-plugin,這將使我們能夠預(yù)渲染“蜘蛛”將要爬行的路徑:

npm install --save prerender-spa-plugin

快要完成了顾复,最后四個包:

  • pug - 模板引擎班挖,相對于HTML我更喜歡它。
  • vuex-router-sync-to - 輕松保持vue-router和vuex存儲同步捕透。
  • copy-webpack-plugin-to - 輕松包含我們在dist文件夾中的靜態(tài)文件聪姿。
  • babel-polyfill - 在PhantomJS中運行Vue(通過我們的預(yù)渲染插件使用)碴萧。

運行這些:

npm install --save pug
npm install --save vuex-router-sync
npm install --save copy-webpack-plugin
npm install --save babel-polyfill

2. 架構(gòu)

安裝完成后請檢查是否安裝正確乙嘀。之后,便可以處理我們的商店數(shù)據(jù)了破喻。

先從vuexstore開始虎谢,我們將使用它來存儲/訪問我們的產(chǎn)品信息。

在本演示中曹质,我們將使用靜態(tài)數(shù)據(jù)婴噩,如果我們要取而代之,它仍然可以工作羽德。

注:關(guān)于Snipcart几莽,我們使用基本的JS代碼段注入購物車,并使用簡單的HTML屬性定義產(chǎn)品宅静。

2.1 構(gòu)建store

src中創(chuàng)建一個store文件夾章蚣,包含以下3個文件:

  • state.js - 定義我們的靜態(tài)產(chǎn)品數(shù)據(jù)
  • getters.js - 定義get函數(shù),通過ID檢索產(chǎn)品
  • index.js - 組合前兩個文件
//state.js
export const state = {
    products: [
        {
            id: 1,
            name: 'The Square Pair',
            price: 100.00,
            description: 'Bold & solid.',
            image: 'https://snipcart.com/media/10171/glasses1.jpeg'
        },
        {
            id: 2,
            name: 'The Hip Pair',
            price: 110.00,
            description: 'Stylish & fancy.',
            image: 'https://snipcart.com/media/10172/glasses2.jpeg'
        },
        {
            id: 3,
            name: 'The Science Pair',
            price: 30,
            description: 'Discreet & lightweight.',
            image: 'https://snipcart.com/media/10173/glasses3.jpeg'
        }
    ]
}

//getters.js
    export const getters = {
        getProductById: (state, getters) => (id) => {
            return state.products.find(product => product.id == id)
        }
    }

//index.js
import Vue from 'vue'
import Vuex from 'vuex'
import { state } from './state.js'
import { getters } from './getters.js'

Vue.use(Vuex)

export default new Vuex.Store({
  state,
  getters
})

2.2 構(gòu)建路由器

我們將保持商店盡可能簡單:展示產(chǎn)品列表的首頁以及每個產(chǎn)品的詳細(xì)信息頁面姨夹。我們需要在路由器中注冊兩條路由來處理這些路由:

import VueRouter from 'vue-router'
import Vue from 'vue'
import ProductDetails from './../components/productdetails.vue'
import Home from './../components/home.vue'

Vue.use(VueRouter)

export default new VueRouter({
  mode: 'history',
  routes: [
    { path: '/products/:id', component: ProductDetails },
    { path: '/', component: Home },
  ]
})

我們還沒有創(chuàng)建這些組件纤垂,不用擔(dān)心,馬上就來磷账,;)

請注意峭沦,我們在VueRouter聲明中使用了mode:'history'。這一點很重要逃糟,否則我們的prerender插件將不會工作吼鱼。其區(qū)別在于路由器將使用history API而不是hashbang來導(dǎo)航。

2.3 把所有東西組合在一起

現(xiàn)在绰咽,我們有了數(shù)據(jù)(store)和路由器菇肃,我們需要把他們注冊到應(yīng)用中。更新你的src/main.js文件:

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import { sync } from 'vuex-router-sync'
import store from './store'

sync(store, router)

new Vue({
  store,
  router,
  render: h => h(App)
}).$mount('#app')

很簡單吧剃诅!正如前面提到的巷送,vuex-router-sync中的sync方法從我們的store中注入狀態(tài)到當(dāng)前的路由中。我們稍后再用矛辕。

3. 書寫Vue組件

有數(shù)據(jù)感覺真棒笑跛,但將它顯示出來將會更好付魔。我們即將用到的三個組件:

  • Home - 展示產(chǎn)品列表
  • Product - 單個產(chǎn)品信息,將被用在Home組件中
  • ProductDetails - 產(chǎn)品詳情頁

他們將被包含在src/components文件夾中飞蹂。

//Home.vue

<template lang="pug">
    div(class="products")
        div(v-for="product in products", class="product")
            product(:product="product")
</template>

<script>
import Product from './../components/Product.vue'

export default {
  name: 'home',
  components: { Product },
  computed: {
    products(){
      return this.$store.state.products
    }
  }
}
</script>

以上几苍,我們使用store中的狀態(tài)來獲取我們的產(chǎn)品,并對它們進(jìn)行迭代陈哑,來渲染每一個產(chǎn)品妻坝。

//Product.vue
<template lang="pug">
  div(class="product")
   router-link(v-bind:to="url").product
      img(v-bind:src="product.image" v-bind:alt="product.name" class="thumbnail" height="200")
      p {{ product.name }}
    
    button(class="snipcart-add-item"
      v-bind:data-item-name="product.name"
      v-bind:data-item-id="product.id"
      v-bind:data-item-image="product.image"
      data-item-url="/"
      v-bind:data-item-price="product.price")
        | Buy it for {{ product.price }}$
 
</template>

<script>
export default {
  name: 'Product',
  props: ['product'],
  computed: {
    url(){
      return `/products/${this.product.id}`
    }
  }
}
</script>

通過路由器,我們鏈接到其他頁面(ProductDetails)惊窖,來看看我們的最后一個組件:

//ProductDetails.vue
<template lang="pug">
  div(class="product-details")
    
    img(v-bind:src="product.image" v-bind:alt="product.name" class="thumbnail" height="200")
     
    div(class="product-description" v-bind:href="url")
      p {{ product.name }}
      p {{ product. description}}

      button(class="snipcart-add-item"
        v-bind:data-item-name="product.name"
        v-bind:data-item-id="product.id"
        v-bind:data-item-image="product.image"
        data-item-url="/"
        v-bind:data-item-price="product.price")
          | Buy it for {{ product.price }}$

</template>

<script>
export default {
  name: 'ProductDetails',
  computed: {
    id(){
      return this.$store.state.route.params.id
    },
    product(){
      return this.$store.getters.getProductById(this.id)
    }
  }
}
</script>

這一節(jié)的邏輯要稍微復(fù)雜些:我們從路由中獲取當(dāng)前的ID刽宪,然后通過之前創(chuàng)建的getter獲取相關(guān)的產(chǎn)品信息。

4. 創(chuàng)建App

我們開始使用剛才創(chuàng)建的組件界酒。

打開App.vue文件圣拄,其內(nèi)容是腳手架(vue init webpack-simple)生成的默認(rèn)內(nèi)容。我們來修改它:

<template lang="pug">
  div(id="app")
    TopContext
    router-view

</template>

<script>
import TopContext from './components/TopContext.vue'

export default {
  name: 'app',
  components: { TopContext }
}
</script>

TopContext組件不是很重要毁欣,它僅僅是一個header庇谆。關(guān)鍵部分是router-view:它將通過VueRouter動態(tài)加載組件,而之前與之關(guān)聯(lián)的組件將被替換凭疮。

最后我們來更新一下index.html饭耳。對于我們的用例來說,我們在src中創(chuàng)建新的目錄static执解,移動index.html文件至static并將其更新為如下內(nèi)容:

<!DOCTYPE html><html lang="en">
  <head>
    <meta charset="utf-8">
    <title>vue-snipcart</title>
  </head>

  <body>
  
    <div id="app">    
    </div>
  
    <script src="/build.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script>
    <script src="https://cdn.snipcart.com/scripts/2.0/snipcart.js" data-api-key="YjdiNWIyOTUtZTIyMy00MWMwLTkwNDUtMzI1M2M2NTgxYjE0" id="snipcart"></script>
    <link  rel="stylesheet" type="text/css" />
  </body>
</html>

你可以看到寞肖,我們在index.html中添加了Snipcart的必要腳本。如果將他們精細(xì)的劃分到各個組件之中代碼看起來會更加干凈材鹦,但逝淹,由于我們所有的View都需要它們,我們便這樣做了桶唐。

5. 使用Prerender插件處理Vue.js SEO

vuejs seo prerendering

我們應(yīng)用中的所有內(nèi)容都是使用JS動態(tài)渲染的栅葡,這很不利于搜索引擎優(yōu)化(SEO):網(wǎng)頁中的異步內(nèi)容不能被“蜘蛛”(search engine bots)有效的識別并抓取,這樣的話尤泽,我們的電子商務(wù)網(wǎng)站錯過了所有有用的“網(wǎng)絡(luò)爬蟲”欣簇,這不是一個明智的選擇!

讓我們使用prerendering技術(shù)來為我們的Vue.js應(yīng)用程序帶來更多的SEO機(jī)會坯约。

相對于Vue的SSR(服務(wù)器端渲染)熊咽,prerendering則更容易使用。坦率地說闹丐,前者有些矯枉過正了横殴,除非你有大量的路由要處理。另外,這兩種技術(shù)在實現(xiàn)SEO層面所達(dá)到的效果是相似的衫仑。

預(yù)渲染將使我們能夠保持我們的前端作為一種快速梨与,輕量級的靜態(tài)網(wǎng)站,以便于“蜘蛛”進(jìn)行爬取文狱。

讓我們來看看如何使用它:轉(zhuǎn)到WebPack配置文件粥鞋,在plugin配置項中添加以下配置:

plugins: [
  new CopyWebpackPlugin([{
    from: 'src/static'
  }]),
  new PrerenderSpaPlugin(
    path.join(__dirname, 'dist'),
    [ '/', '/products/1', '/products/2', '/products/3']
  )
]

好吧,它是如何工作的呢瞄崇?

CopyWebpackPlugin將會復(fù)制static文件夾中的文件到dist文件夾中(只包含引用Vue App的應(yīng)用程序的視圖)呻粹。然后,PrerenderSpaPlugin使用PhantomJS加載網(wǎng)頁的內(nèi)容苏研,并將結(jié)果作為我們的靜態(tài)資源等浊。

瞧!我們現(xiàn)在已經(jīng)為我們的Vue應(yīng)用程序提供了預(yù)渲染的楣富,SEO友好的產(chǎn)品頁面凿掂。

我們使用如下命令來進(jìn)行測試:

npm run build

這將生成一個dist文件夾,其中包含生產(chǎn)環(huán)境所需的一切纹蝴。

其他重要的SEO因素

  1. 考慮為您的頁面添加適當(dāng)?shù)?code>meta標(biāo)記和站點地圖(sitemap)。您可以在“postProcessHtml”函數(shù)(prerender-spa-plugin插件的配置項)中了解有關(guān)meta標(biāo)記的更多信息踪少。
  2. 恰當(dāng)?shù)膬?nèi)容在現(xiàn)代SEO中起了重要作用塘安。建議您確保應(yīng)用程序中的內(nèi)容易于創(chuàng)建,編輯和優(yōu)化援奢。為了授權(quán)內(nèi)容編輯者兼犯,請考慮將headless CMS放入組合中并用來構(gòu)建真正的JAMstack
  3. 現(xiàn)在集漾,HTTPS連接正式成為Google的排名因素切黔。我們在Netlify上托管這個演示,Netlify為我們提供了免費的SSL證書具篇。
  4. Mobile-first indexingmobile-friendliness也是排名的重要因素纬霞。確保您的移動體驗與桌面版一樣快速完整!

GitHub庫和在線演示

vuejs-tutorial-live-demo.png

來吧驱显,這里是在線演示及代碼倉庫的地址诗芜!

GitHub倉庫

在線演示

總結(jié)

我之前使用過Vue,本教程的制作過程還是相當(dāng)順利的埃疫。我花了一個小時在Demo上伏恐,在使用CopyWebpackPlugin時遇到了困難,好在我在他們的文檔中找到了答案栓霜。

我希望這篇文章能鼓勵開發(fā)人員在一些項目中開始使用Vue翠桦。就像我說的,您可以通過開發(fā)一個現(xiàn)有項目的一小部分來逐步地開始胳蛮,我認(rèn)為這絕對值得一試销凑。我們的開發(fā)主管正在使用Vue編寫最新的商業(yè)儀表盤功能愁铺,他非常喜歡Vue。另外闻鉴,如果配置正確茵乱,Vue完全可以驅(qū)動具有良好SEO結(jié)果的應(yīng)用程序。

如果你受到了啟發(fā)孟岛,可以看看Awesome-vue瓶竭,它包含了Vue示例和相關(guān)項目。

如果你真的喜愛Vue渠羞,cop some swagsupport the creator


如果你覺得這篇文章有價值斤贰,請花一點時間分享到Twitter上。有什么遺漏或錯誤的次询?有關(guān)于Vue的荧恍?或其他框架處理SEO的一些想法?現(xiàn)在評論區(qū)是你的了屯吊!

End

作者:Maxime Laboissonniere
原文地址: Vue.js Tutorial: An Example to Build and Prerender an SEO-Friendly Site

譯者:jeneser
譯者GitHub:https://github.com/jeneser

版權(quán)聲明:自由轉(zhuǎn)載-非商用-非衍生-保持署名(創(chuàng)意共享3.0許可證

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末送巡,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子盒卸,更是在濱河造成了極大的恐慌骗爆,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,214評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蔽介,死亡現(xiàn)場離奇詭異摘投,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)虹蓄,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評論 2 382
  • 文/潘曉璐 我一進(jìn)店門犀呼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人薇组,你說我怎么就攤上這事外臂。” “怎么了体箕?”我有些...
    開封第一講書人閱讀 152,543評論 0 341
  • 文/不壞的土叔 我叫張陵专钉,是天一觀的道長。 經(jīng)常有香客問我累铅,道長跃须,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,221評論 1 279
  • 正文 為了忘掉前任娃兽,我火速辦了婚禮菇民,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己第练,他們只是感情好阔馋,可當(dāng)我...
    茶點故事閱讀 64,224評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著娇掏,像睡著了一般呕寝。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上婴梧,一...
    開封第一講書人閱讀 49,007評論 1 284
  • 那天下梢,我揣著相機(jī)與錄音,去河邊找鬼塞蹭。 笑死孽江,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的番电。 我是一名探鬼主播岗屏,決...
    沈念sama閱讀 38,313評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼漱办!你這毒婦竟也來了这刷?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,956評論 0 259
  • 序言:老撾萬榮一對情侶失蹤洼冻,失蹤者是張志新(化名)和其女友劉穎崭歧,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體撞牢,經(jīng)...
    沈念sama閱讀 43,441評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,925評論 2 323
  • 正文 我和宋清朗相戀三年叔营,在試婚紗的時候發(fā)現(xiàn)自己被綠了屋彪。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,018評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡绒尊,死狀恐怖畜挥,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情婴谱,我是刑警寧澤蟹但,帶...
    沈念sama閱讀 33,685評論 4 322
  • 正文 年R本政府宣布,位于F島的核電站谭羔,受9級特大地震影響华糖,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜瘟裸,卻給世界環(huán)境...
    茶點故事閱讀 39,234評論 3 307
  • 文/蒙蒙 一客叉、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦兼搏、人聲如沸卵慰。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽裳朋。三九已至,卻和暖如春吓著,著一層夾襖步出監(jiān)牢的瞬間鲤嫡,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評論 1 261
  • 我被黑心中介騙來泰國打工夜矗, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留泛范,地道東北人。 一個月前我還...
    沈念sama閱讀 45,467評論 2 352
  • 正文 我出身青樓紊撕,卻偏偏與公主長得像罢荡,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子对扶,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,762評論 2 345

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