最簡(jiǎn)單的服務(wù)端渲染框架-Next.js

最簡(jiǎn)單的服務(wù)端渲染框架-Next.js

快速入門

Next.js是一個(gè)用于React應(yīng)用的極簡(jiǎn)的服務(wù)端渲染框架旁趟∽咐矗框架中集成了Webpack皮假,Babel等一系列React相關(guān)的工具并進(jìn)行了默認(rèn)的配置转锈。因此省去了復(fù)雜的配置過程,實(shí)現(xiàn)了一鍵搭建開發(fā)環(huán)境和打包構(gòu)建尤误。同時(shí)提供了自定義配置接口侠畔,可以在默認(rèn)配置的基礎(chǔ)上對(duì)工具進(jìn)行自定義配置,滿足個(gè)性化需求损晤。

安裝

使用npm安裝: npm install next --save

為了方便的使用next提供的命令软棺,把命令寫在package.json文件的scripts中:

{
  "scripts": {
    "dev": "next",  // 運(yùn)行開發(fā)服務(wù)器,并監(jiān)控源代碼尤勋,具備hod reload功能
    "build": "next build", // 以生產(chǎn)模式打包代碼
    "start": "next start"  // 啟動(dòng)Next服務(wù)器喘落,可以自定義服務(wù)器和端口
    "init": "next init" // 初始化項(xiàng)目,創(chuàng)建基礎(chǔ)的文件夾和index頁面文件
  }
}

之后斥黑,在項(xiàng)目的根目錄下創(chuàng)建pages文件夾和static文件夾揖盘,分別用來放對(duì)應(yīng)的頁面資源和靜態(tài)資源。

Note:也可以使用npm run init命令自動(dòng)生成锌奴。

運(yùn)行

如果使用npm run init命令的話兽狭,現(xiàn)在pages文件夾下已經(jīng)有了index.js文件,如果是手動(dòng)創(chuàng)建pages文件夾的話鹿蜀,現(xiàn)在在該文件下創(chuàng)建一個(gè)index.js文件箕慧,內(nèi)容為:

export default () => <p>Hello, world</p>

接著執(zhí)行npm run dev命令并在瀏覽器中打開http://localhost:3000

現(xiàn)在茴恰,就得到了一個(gè)采用服務(wù)端渲染的極簡(jiǎn)React應(yīng)用颠焦,這個(gè)應(yīng)用還實(shí)現(xiàn)了自動(dòng)代碼分割,保證每個(gè)頁面只會(huì)加載自身的依賴往枣,不會(huì)有依賴冗余伐庭。

Next的核心就是pages和static文件夾。其中pages文件夾用于存放每個(gè)頁面的頂層組件分冈,static用于存放項(xiàng)目中的靜態(tài)資源圾另。

Next會(huì)將pages中的文件結(jié)構(gòu)自動(dòng)映射為對(duì)應(yīng)的路由結(jié)構(gòu),例如現(xiàn)在該文件夾下有兩個(gè)文件:pages/index.js和pages/about.js雕沉。則對(duì)應(yīng)的路由分別為//about集乔。并且支持多級(jí)目錄,例如page/foo/bar.js對(duì)應(yīng)的路由為/foo/bar坡椒。

static文件夾用來存放靜態(tài)文件扰路,例如現(xiàn)在有一個(gè)圖片文件static/image.png,使用的時(shí)候引用/static/image.png就可以了:

export default () => (
  <img src="/static/mage.png" />
)

打包完成后倔叼,Next會(huì)在項(xiàng)目根目錄生成一個(gè).next文件夾汗唱,其中的兩個(gè)文件夾distbundlesdist文件夾中存放著編譯后的源代碼丈攒,用于服務(wù)端渲染渡嚣。bunldes文件夾中存放著pages中每個(gè)頁面打包后的整體代碼的JSON格式。在應(yīng)用的初始頁面,會(huì)使用dist文件夾中的代碼進(jìn)行服務(wù)端渲染识椰,而其他使用路由到達(dá)的頁面绝葡,則將bundles文件夾中的對(duì)應(yīng)JSON格式的代碼返回客戶端執(zhí)行渲染。

Next的出現(xiàn)大大簡(jiǎn)化了React應(yīng)用開發(fā)的配置和構(gòu)建工作腹鹉,使開發(fā)者能夠?qū)W⒂诮M件的開發(fā)藏畅,而不需要在Webpack,Babel等工具上花費(fèi)過多的精力功咒∮溲郑基于簡(jiǎn)單的文件系統(tǒng),就可以創(chuàng)建包含路由功能和服務(wù)端渲染的React應(yīng)用力奋。需要注意的是:創(chuàng)建的應(yīng)用中只有初始頁面采用服務(wù)端渲染榜旦,其他通過路由操作到達(dá)的頁面均為客戶福渲染。

組件

Next對(duì)React組件的getInitialProps生命周期方法做了改造景殷,傳入一個(gè)上下文對(duì)象溅呢,該對(duì)象在服務(wù)端渲染和客戶端渲染時(shí),具有不同的屬性:

  • req: HTTP請(qǐng)求對(duì)象(服務(wù)端渲染獨(dú)有)
  • res: HTTP響應(yīng)對(duì)象(服務(wù)端渲染獨(dú)有)
  • pathname: URL中的路徑部分
  • query:URL中的查詢字符串部分解析出的對(duì)象
  • err:錯(cuò)誤對(duì)象猿挚,如果在渲染時(shí)發(fā)生了錯(cuò)誤
  • xhr:XMLHttpRequest對(duì)象(客戶端渲染獨(dú)有)

因此咐旧,可以在組件的getInitialProps方法中處理上下文對(duì)象,控制傳入組件的props數(shù)據(jù)绩蜻。例如:

import React from 'react'
export default class extends React.Component {
  static async getInitialProps ({ req }) {
    return req
      ? { userAgent: req.headers['user-agent'] }
      : { userAgent: navigator.userAgent }
  }
  render () {
    return <div>
      Hello World {this.props.userAgent}
    </div>
  }
}

上面的例子根據(jù)是否有req對(duì)象來判斷是服務(wù)端渲染還是客戶端渲染铣墨,然后采用對(duì)應(yīng)的方式取得用戶代碼數(shù)據(jù)并傳入組件的props中。

獲取數(shù)據(jù)

組件的getInitialProps還可以用來獲取數(shù)據(jù):

import React, { Component } from 'react';
import 'isomorphic-fetch';

export default class extends Component {
  static async getInitialProps() {
    const res = await fetch('https://api.github.com/repos/zeit/next.js');
    const json = await res.json();
    return { 
      stars: json.stargazers_count 
    };
    
  }
  
  render() {
    return <div>{this.props.stars}</div>
  }
}

需要注意的一點(diǎn)是办绝,getInitialProps方法執(zhí)行完畢之后伊约,才會(huì)執(zhí)行組件的render方法。這也就導(dǎo)致了如果網(wǎng)絡(luò)狀況不佳的情況下孕蝉,會(huì)出現(xiàn)長(zhǎng)時(shí)間的等待碱妆。并且只有每個(gè)頁面的頂層組件的getInitialProps會(huì)被執(zhí)行,所以想在子組件中獲取數(shù)據(jù)的話只能在其他生命周期函數(shù)例如componentDidMount配合組件的state實(shí)現(xiàn):

export default class extends Component {
  constructor(props) {
    super(props);
    this.state = {
      stars: 0
    }
  }

  async componentDidMount() {
    const res = await fetch('https://api.github.com/repos/zeit/next.js');
    const json = await res.json();
    this.setState({
      stars: json.stargazers_count
    });
  }
  
  render() {
    return <div>{this.state.stars}</div>
  }
}

CSS

NEXT組件中聲明CSS昔驱,目前主要有兩種方式:

  • 1?內(nèi)嵌CSS
  • 2?CSS-in-JS

內(nèi)嵌(Built-in)CSS

Next采用的內(nèi)嵌CSS方案是styled-jsx庫,也是Next所推薦的CSS聲明方式上忍。優(yōu)點(diǎn)是具有組件級(jí)的獨(dú)立作用域骤肛,避免了樣式污染問題。并且支持完整的CSS功能窍蓝,如:hover等腋颠。

import React from 'react'

export default () => (
  <div>
    Hello world
    <p>scoped!</p>
    <style jsx>{`
      p {
        color: blue;
      }
      div {
        background: red;
      }
      div:hover {
        background: blue;
      }
      @media (max-width: 600px) {
        div {
          background: blue;
        }
      }
    `}</style>
  </div>
)

CSS-in-JS

Next支持多種CSS-in-JS方案,例如基本的在組件style屬性中寫樣式:

import React from 'react'

export default () => (
  <div style={{color: red}}>
    Hello world
  </div>
)

還有其他的CSS-in-JS庫吓笙,可以根據(jù)自己的需要和喜好靈活選擇淑玫。

路由系統(tǒng)

Link組件

Next中提供了一個(gè)組件,用來實(shí)現(xiàn)路由功能。例如絮蒿,我們的應(yīng)用有兩個(gè)頁面:pages/index.jspages/about.js尊搬,想要實(shí)現(xiàn)頁面跳轉(zhuǎn),只需要:
<Link>組件的工作流程和瀏覽器很相似:

  • 1?獲取新的組件
  • 2?如果新組件定義了getInitialProps土涝,則獲取數(shù)據(jù)佛寿,如果發(fā)生錯(cuò)誤,則渲染_error.js
  • 3?步驟1但壮,2完成之后冀泻,執(zhí)行pushState并渲染新組件

每個(gè)頂層組件中還會(huì)傳入一個(gè)url對(duì)象,提供了幾個(gè)路由相關(guān)的方法:

  • pathname:String-當(dāng)前URL不包括查詢字符串的path部分
  • query:Object-當(dāng)前URL中查詢字符串解析成的對(duì)象
  • back-后退
  • push(url, as=url)-使用傳入的url(字符串)執(zhí)行pushState操作
  • replace(url, as=url)-使用傳入的url(字符串)執(zhí)行replaceState操作 注意:push和replace方法中的第二個(gè)參數(shù)as為可選項(xiàng)蜡饵,只有在服務(wù)端配置了自定義路由才有作用弹渔。

Router對(duì)象

除了使用<Link>組件之外,Next還提供了一個(gè)Router對(duì)象滿足命令式寫法的需要:

import Router from 'next/router'

export default () => (
  <div>Click <span onClick={() => Router.push('/about')}>here</span> to read more</div>
)

與url對(duì)象相比溯祸,Router對(duì)象多了一個(gè)route屬性肢专,值為當(dāng)前的路由。 需要注意的是您没,Router對(duì)象中的屬性和方法僅可以在客戶端部分使用鸟召,服務(wù)端渲染的頁面無法使用,否則會(huì)報(bào)錯(cuò)氨鹏。

路由事件

Router對(duì)象還提供了三個(gè)路由事件方法:

  • routeChangeStart(url) - 路由變化開始時(shí)觸發(fā)
  • routeChangeComplete(url) - 路由變化完成時(shí)觸發(fā)
  • routeChangeError(err, url) - 路由變化發(fā)生錯(cuò)誤時(shí)觸發(fā) 如果使用Router.push(url, as)或相似的方法并傳入了as參數(shù)欧募,則路由事件方法中的url參數(shù)值為as的值,否則仆抵,url參數(shù)的值是路由舔磚目標(biāo)的URL

注意:與Router對(duì)象中其他的屬性和方法不同的是跟继,這三個(gè)路由事件方法可以在服務(wù)端渲染的頁面使用。

監(jiān)聽路由變化:

Router.onRouteChangeStart = (url) => {
  console.log('App is changing to: ', url)
}

取消監(jiān)聽:

Router.onRouteChangeStart = null;

如果路由加載取消了(連續(xù)快速點(diǎn)擊兩個(gè)鏈接)镣丑,就會(huì)觸發(fā)routeChangeError的回調(diào)舔糖,傳入的err參數(shù)中將包含一個(gè)cancelled屬性,值為true莺匠。

Router.onRouteChangeError = (err, url) => {
  if (err.cancelled) {
    console.log(`Route to ${url} was cancelled!`)
  }
}

預(yù)獲取頁面

Next提供了一個(gè)基于ServiceWorker實(shí)現(xiàn)的金吗,具有預(yù)獲取頁面功能的模塊:next/prefetch。 使用預(yù)獲取功能趣竣,可以使APP預(yù)加載那些可能到達(dá)的頁面摇庙,提升網(wǎng)站的使用體驗(yàn)和性能。當(dāng)然遥缕,前提是你的瀏覽器必須支持ServiceWorker卫袒。并且預(yù)獲取功能只支持應(yīng)用內(nèi)的頁面,不支持外部鏈接单匣。

<Link>組件

next/prefetch模塊也提供了一個(gè)具有預(yù)獲取功能的<Link>組件夕凝,代替路由系統(tǒng)中的<Link>組件宝穗,使用方法一致:

import Link from 'next/prefetch'

export default () => (
  <nav>
    <ul>
      <li><Link href='/'><a>Home</a></Link></li>
      <li><Link href='/about'><a>About</a></Link></li>
      <li><Link href='/contact'><a>Contact</a></Link></li>
    </ul>
  </nav>
)

此外預(yù)獲取功能可以精確控制到每個(gè)<Link>標(biāo)簽,使用prefetch屬性來控制開關(guān):

<Link href='/contact' prefetch={false}><a>Home</a></Link>

prefetch方法

和路由器一樣码秉,預(yù)獲取模塊也提供了一個(gè)prefetch方法逮矛,用來方便命令式的寫法:

import { prefetch } from 'next/prefetch'
export default ({ url }) => (
  <div>
    <a onClick={ () => setTimeout(() => url.pushTo('/dynamic'), 100) }>
      100ms后執(zhí)行路由跳轉(zhuǎn)
    </a>
    {
      預(yù)獲取頁面
      prefetch('/dynamic')
    }
  </div>
)

自定義配置

如果默認(rèn)的配置無法滿足需要的話,Next還提供了諸多的自定義配置接口泡徙,可以根據(jù)自己的需求靈活配置橱鹏。

自定義服務(wù)器和路由

默認(rèn)的服務(wù)器和路由系統(tǒng)可能無法滿足需要,比如堪藐,我需要把/a的路由解析到pages/b.js莉兰,把/b的路由解析到pages/a.js,此時(shí)礁竞,就需要通過自定義糖荒,手動(dòng)控制頁面渲染來實(shí)現(xiàn),在項(xiàng)目根目錄下創(chuàng)建server.js文件:

// server.js

const { createServer } = require('http')
const { parse } = require('url')
const next = require('next')

const dev = process.env.NODE_ENV !== 'production'
const app = next({ dev })
const handle = app.getRequestHandler()

app.prepare().then(() => {
  createServer((req, res) => {
    const parsedUrl = parse(req.url, true)
    const { pathname, query } = parsedUrl

    if (pathname === '/a') {
      app.render(req, res, '/b', query)
    } else if (pathname === '/b') {
      app.render(req, res, '/a', query)
    } else {
      handle(req, res, parsedUrl)
    }
  })
  .listen(3000, (err) => {
    if (err) throw err
    console.log('> Ready on http://localhost:3000')
  })
})

你可以選擇自己喜歡的服務(wù)端框架模捂,express或者koa等捶朵,進(jìn)行自定義。

自定義head

Next提供了<HEAD>組件狂男,可以自定義頁面<head>標(biāo)簽中的內(nèi)容综看。每個(gè)組件都可以在內(nèi)部自定義<head>的內(nèi)容:

import Head from 'next/head'
export default () => (
  <div>
    <Head>
      <title>My page title</title>
      <meta name="viewport" content="initial-scale=1.0, width=device-width" />
    </Head>
    <p>Hello world!</p>
  </div>
)

每個(gè)頁面組件只需要定義本頁面需要的<head>內(nèi)容,并且對(duì)于相同的標(biāo)簽岖食,例如<title>红碑。會(huì)按照組件渲染的順序,后定義的覆蓋先定義的內(nèi)容泡垃。

自定義Document

在前面的例子中析珊,服務(wù)端渲染時(shí),所有的頁面我們只需要寫內(nèi)容組件蔑穴,這是因?yàn)槭褂昧四J(rèn)的<Document>模板忠寻。當(dāng)然,可以自定義自己的服務(wù)端渲染模板存和。首先奕剃,創(chuàng)建pages/_document.js文件,寫上內(nèi)容:

// pages/_document.js
import Document, { Head, Main, NextScript } from 'next/document'

export default class MyDocument extends Document {
  static async getInitialProps (ctx) {
    const props = await Document.getInitialProps(ctx)
    return { ...props, customValue: 'hi there!' }
  }

  render () {
    return (
     <html>
       <Head>
         <style>{`body { margin: 0 } /* custom! */`}</style>
       </Head>
       <body className="custom_class">
         {this.props.customValue}
         <Main />
         <NextScript />
       </body>
     </html>
    )
  }
}

其中的ctx對(duì)象與其他組件中的getInitialProps方法中收到的參數(shù)一樣捐腿,只不過多了一個(gè)額外的方法:renderPage()纵朋。

自定義錯(cuò)誤處理

Next中,有一個(gè)默認(rèn)組件error.js叙量,負(fù)責(zé)處理404或者500這種錯(cuò)誤。當(dāng)然九串,你也可以自定義一個(gè)_error.js組件覆蓋默認(rèn)的錯(cuò)誤處理組件:

// _error.js

import React from 'react'
export default class Error extends React.Component {
  static getInitialProps ({ res, xhr }) {
    const statusCode = res ? res.statusCode : (xhr ? xhr.status : null)
    return { statusCode }
  }

  render () {
    return (
      <p>{
        this.props.statusCode
        ? `An error ${this.props.statusCode} occurred on server`
        : 'An error occurred on client'
      }</p>
    )
  }
}

自定義配置

相對(duì)Next進(jìn)行自定義配置的話绞佩,可以在項(xiàng)目根目錄下創(chuàng)建一個(gè)next.config.js

// next.config.js

module.exports = {
  /* 自定義配置 */
}

自定義Webpack配置

在創(chuàng)建好的next.config.js文件中寺鸥,可以擴(kuò)展Webpack配置:

module.exports = {
  webpack: (config, { dev }) => {
   
    // 修改config對(duì)象
   
    return config
  }
}

該函數(shù)接收默認(rèn)的Webpack config對(duì)象作為參數(shù),返回修改后的config對(duì)象品山。需要注意的是胆建,next.config.js文件會(huì)被直接執(zhí)行,因?yàn)橹荒苁褂帽緳C(jī)安裝的Node.js所支持的JS語法肘交。

警告:不建議在自定義Webpack配置中添加loader以支持新的文件類型笆载!因?yàn)橹挥锌蛻舳虽秩镜拇a會(huì)經(jīng)過打包,而服務(wù)端執(zhí)行的是源代碼涯呻,并沒有經(jīng)過Webpack處理凉驻,因此新的loader對(duì)服務(wù)端渲染不起作用。所以最好是使用Babel插件來處理新的文件類型复罐,因?yàn)闊o論是客戶端還是服務(wù)端渲染的代碼涝登,都會(huì)經(jīng)過Babel處理。

自定義Babel配置

自定義Babel配置效诅,只需要在項(xiàng)目根目錄下創(chuàng)建.babelrc文件胀滚,因?yàn)樽远x配置會(huì)覆蓋默認(rèn)配置,而不是擴(kuò)展默認(rèn)配置乱投。因此需要把next preset寫到.babelrc中咽笼。例如:

{
  "presets": [
    "next/babel",  // Next默認(rèn)配置
    "stage-0"
  ],
}

部署

生產(chǎn)模式下,需要先使用生產(chǎn)模式構(gòu)建代碼戚炫,再啟動(dòng)服務(wù)器剑刑。因此,需要兩條命令:

next build
next start

Next官方推薦使用now作為部署工具嘹悼,只要在package.json文件中寫入:

{
  "name": "my-app",
  "dependencies": {
    "next": "latest"
  },
  "scripts": {
    "dev": "next",
    "build": "next build",
    "start": "next start"
  }
}

接著運(yùn)行now命令叛甫,就可以實(shí)現(xiàn)一鍵部署。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末杨伙,一起剝皮案震驚了整個(gè)濱河市其监,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌限匣,老刑警劉巖抖苦,帶你破解...
    沈念sama閱讀 206,126評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異米死,居然都是意外死亡锌历,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門峦筒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來究西,“玉大人,你說我怎么就攤上這事物喷÷辈模” “怎么了遮斥?”我有些...
    開封第一講書人閱讀 152,445評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)扇丛。 經(jīng)常有香客問我术吗,道長(zhǎng),這世上最難降的妖魔是什么帆精? 我笑而不...
    開封第一講書人閱讀 55,185評(píng)論 1 278
  • 正文 為了忘掉前任较屿,我火速辦了婚禮,結(jié)果婚禮上卓练,老公的妹妹穿的比我還像新娘隘蝎。我一直安慰自己,他們只是感情好昆庇,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,178評(píng)論 5 371
  • 文/花漫 我一把揭開白布末贾。 她就那樣靜靜地躺著,像睡著了一般整吆。 火紅的嫁衣襯著肌膚如雪拱撵。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 48,970評(píng)論 1 284
  • 那天表蝙,我揣著相機(jī)與錄音拴测,去河邊找鬼。 笑死府蛇,一個(gè)胖子當(dāng)著我的面吹牛集索,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播汇跨,決...
    沈念sama閱讀 38,276評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼务荆,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了穷遂?” 一聲冷哼從身側(cè)響起函匕,我...
    開封第一講書人閱讀 36,927評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎蚪黑,沒想到半個(gè)月后盅惜,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,400評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡忌穿,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,883評(píng)論 2 323
  • 正文 我和宋清朗相戀三年抒寂,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片掠剑。...
    茶點(diǎn)故事閱讀 37,997評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡屈芜,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出朴译,到底是詐尸還是另有隱情井佑,我是刑警寧澤糕珊,帶...
    沈念sama閱讀 33,646評(píng)論 4 322
  • 正文 年R本政府宣布,位于F島的核電站毅糟,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏澜公。R本人自食惡果不足惜姆另,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,213評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望坟乾。 院中可真熱鬧迹辐,春花似錦、人聲如沸甚侣。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽殷费。三九已至印荔,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間详羡,已是汗流浹背仍律。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評(píng)論 1 260
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留实柠,地道東北人水泉。 一個(gè)月前我還...
    沈念sama閱讀 45,423評(píng)論 2 352
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像窒盐,于是被迫代替她去往敵國(guó)和親草则。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,722評(píng)論 2 345

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

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,499評(píng)論 25 707
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理蟹漓,服務(wù)發(fā)現(xiàn)炕横,斷路器,智...
    卡卡羅2017閱讀 134,599評(píng)論 18 139
  • ??今天為大家解讀的來自美國(guó)作家利維的代表作品《快節(jié)奏,慢生活》塔鳍,很多人看到本書的標(biāo)題伯铣,還以為是一本讓大家慢下來,...
    南山y(tǒng)ounger閱讀 579評(píng)論 0 1
  • 2017年6月12日 仔細(xì)看轮纫,每個(gè)人的生活都是一地雞毛腔寡! 她結(jié)婚三年沒有寶寶,一個(gè)月去四次醫(yī)院檢查掌唾;她懷了男孩是雙...
    晴真真閱讀 161評(píng)論 0 0
  • 創(chuàng)建第一個(gè)odoo 應(yīng)用 Odoo遵循傳統(tǒng)的MVC模式放前。我們可以通過創(chuàng)建簡(jiǎn)單的To-Do 應(yīng)用來具體介紹分析 mo...
    F4A3閱讀 1,439評(píng)論 0 5