React上手 —— 進階篇

代碼分割

使用Webpack或者Browserify這樣的打包工具,最終會生成一個bundle.js钻趋,會一次性把代碼都加載進來,但是隨著項目的不斷擴大, 一次性加載所有文件導(dǎo)致加載時間過長鞭铆。為了避免搞出大體積的代碼包,在前期就思考該問題并對代碼包進行分割是個不錯的選擇。代碼分割是由諸如 Webpack(代碼分割)和 Browserify(factor-bundle)這類打包器支持的一項技術(shù)车遂,能夠創(chuàng)建多個包并在運行時動態(tài)加載封断。

import

import("./math").then(math => {
  console.log(math.add(16, 26));
});

如果你自己配置 Webpack,你可能要閱讀下 Webpack 關(guān)于代碼分割的指南舶担。你的 Webpack 配置應(yīng)該類似于此坡疼。

當(dāng)使用 Babel 時,你要確保 Babel 能夠解析動態(tài) import 語法而不是將其進行轉(zhuǎn)換衣陶。對于這一要求你需要 babel-plugin-syntax-dynamic-import 插件柄瑰。

React.lazy 函數(shù)能讓你像渲染常規(guī)組件一樣處理動態(tài)引入(的組件)。

const OtherComponent = React.lazy(() => import('./OtherComponent'));

function MyComponent() {
  return (
    <div>
      <OtherComponent />
    </div>
  );
}

Suspense

const OtherComponent = React.lazy(() => import('./OtherComponent'));

function MyComponent() {
  return (
    <div>
      <Suspense fallback={<div>Loading...</div>}>
        <OtherComponent />
      </Suspense>
    </div>
  );
}

如果還沒有加載完可以這么操作剪况。

異常捕獲邊界(Error boundaries)

import MyErrorBoundary from './MyErrorBoundary';
const OtherComponent = React.lazy(() => import('./OtherComponent'));
const AnotherComponent = React.lazy(() => import('./AnotherComponent'));

const MyComponent = () => (
  <div>
    <MyErrorBoundary>
      <Suspense fallback={<div>Loading...</div>}>
        <section>
          <OtherComponent />
          <AnotherComponent />
        </section>
      </Suspense>
    </MyErrorBoundary>
  </div>
);

React.lazy 目前只支持默認導(dǎo)出(default exports)教沾。如果需要使用命名導(dǎo)出需要增加中間模塊:

// ManyComponents.js
export const MyComponent = /* ... */;
export const MyUnusedComponent = /* ... */;
// MyComponent.js
export { MyComponent as default } from "./ManyComponents.js";
// MyApp.js
import React, { lazy } from 'react';
const MyComponent = lazy(() => import("./MyComponent.js"));

Context

從基礎(chǔ)篇我們可以看見,數(shù)據(jù)都是自定向上译断,但是由于項目的不斷擴大详囤,組件的層級也不斷加深,有些數(shù)據(jù)是應(yīng)該被共享的而不應(yīng)該镐作,一層層傳遞(維護成本太高)藏姐,比如:主題顏色、用戶信息该贾、定位地區(qū)等羔杨。
如何使用:

// Context 可以讓我們無須明確地傳遍每一個組件,就能將值深入傳遞進組件樹杨蛋。
// 為當(dāng)前的 theme 創(chuàng)建一個 context(“l(fā)ight”為默認值)兜材。
const ThemeContext = React.createContext('light');

class App extends React.Component {
  render() {
    // 使用一個 Provider 來將當(dāng)前的 theme 傳遞給以下的組件樹。
    // 無論多深逞力,任何組件都能讀取這個值曙寡。
    // 在這個例子中,我們將 “dark” 作為當(dāng)前的值傳遞下去寇荧。
    return (
      <ThemeContext.Provider value="dark">
        <Toolbar />
      </ThemeContext.Provider>
    );
  }
}

// 中間的組件再也不必指明往下傳遞 theme 了举庶。
function Toolbar(props) {
  return (
    <div>
      <ThemedButton />
    </div>
  );
}

class ThemedButton extends React.Component {
  // 指定 contextType 讀取當(dāng)前的 theme context。
  // React 會往上找到最近的 theme Provider揩抡,然后使用它的值户侥。
  // 在這個例子中,當(dāng)前的 theme 值為 “dark”峦嗤。
  static contextType = ThemeContext;
  render() {
    return <Button theme={this.context} />;
  }
}

還有一種情況是蕊唐,componentA 渲染 componentB ,componentB 渲染 componentC烁设, componentC 渲染 componentD替梨,而控制組件數(shù)據(jù)的是A,最終渲染的是D,這樣的情況不需要Context而用組合組件是更優(yōu)雅的方式:

function Page(props) {
  const user = props.user;
  const userLink = (
    <Link href={user.permalink}>
      <Avatar user={user} size={props.avatarSize} />
    </Link>
  );
  return <PageLayout userLink={userLink} />;
}

// 現(xiàn)在副瀑,我們有這樣的組件:
<Page user={user} avatarSize={avatarSize} />
// ... 渲染出 ...
<PageLayout userLink={...} />
// ... 渲染出 ...
<NavigationBar userLink={...} />
// ... 渲染出 ...
{props.userLink}

即在A里就定義好組件D弓熏,將組件D一層一層傳遞下去。
但是如果是很多組件俗扇,不同層級需要相同數(shù)據(jù)還是使用Context比較好硝烂。

錯誤邊界

注意
錯誤邊界無法捕獲以下場景中產(chǎn)生的錯誤:

  • 事件處理(了解更多
  • 異步代碼(例如 setTimeoutrequestAnimationFrame 回調(diào)函數(shù))
  • 服務(wù)端渲染
  • 它自身拋出來的錯誤(并非它的子組件)

請使用 static getDerivedStateFromError() 渲染備用 UI 箕别,使用 componentDidCatch() 打印錯誤信息铜幽。

class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false };
  }

  static getDerivedStateFromError(error) {
    // Update state so the next render will show the fallback UI.
    return { hasError: true };
  }

  componentDidCatch(error, info) {
    // You can also log the error to an error reporting service
    logErrorToMyService(error, info);
  }

  render() {
    if (this.state.hasError) {
      // You can render any custom fallback UI
      return <h1>Something went wrong.</h1>;
    }

    return this.props.children; 
  }
}

然后你可以將它作為一個常規(guī)組件去使用:

<ErrorBoundary>
  <MyWidget />
</ErrorBoundary>

Refs 轉(zhuǎn)發(fā)

當(dāng)我們需要控制一個封裝的組件的焦點時,比如input或者button串稀,我們需要那到這個組件的實例就是ref除抛。來進行操作,react提供了一個方法來來轉(zhuǎn)發(fā)ref母截。

const FancyButton = React.forwardRef((props, ref) => (
  <button ref={ref} className="FancyButton">
    {props.children}
  </button>
));

// 你可以直接獲取 DOM button 的 ref:
const ref = React.createRef();
<FancyButton ref={ref}>Click me!</FancyButton>;
  • 我們通過調(diào)用 React.createRef 創(chuàng)建了一個 React ref 并將其賦值給 ref 變量到忽。
  • 我們通過指定 ref 為 JSX 屬性,將其向下傳遞給 <FancyButton ref={ref}>清寇。
  • React 傳遞 ref 給 fowardRef 內(nèi)函數(shù) (props, ref) => ...喘漏,作為其第二個參數(shù)。
  • 我們向下轉(zhuǎn)發(fā)該 ref 參數(shù)到 <button ref={ref}>华烟,將其指定為 JSX 屬性翩迈。
  • 當(dāng) ref 掛載完成,ref.current 將指向 <button> DOM 節(jié)點盔夜。
function logProps(WrappedComponent) {
  class LogProps extends React.Component {
    componentDidUpdate(prevProps) {
      console.log('old props:', prevProps);
      console.log('new props:', this.props);
    }

    render() {
      return <WrappedComponent {...this.props} />;
    }
  }

  return LogProps;
}

注意:refs 將不會透傳下去负饲。這是因為 ref 不是 prop 屬性。就像 key 一樣喂链,其被 React 進行了特殊處理返十。如果你對 HOC 添加 ref,該 ref 將引用最外層的容器組件椭微,而不是被包裹的組件洞坑。

Fragments

React 中的一個常見模式是一個組件返回多個元素。Fragments 允許你將子列表分組蝇率,而無需向 DOM 添加額外節(jié)點检诗。

render() {
  return (
    <React.Fragment>
      <ChildA />
      <ChildB />
      <ChildC />
    </React.Fragment>
  );
}

最終不會渲染Fragment,只有children瓢剿。

高階組件

高階組件(HOC)是 React 中用于復(fù)用組件邏輯的一種高級技巧逢慌。HOC 自身不是 React API 的一部分,它是一種基于 React 的組合特性而形成的設(shè)計模式间狂。

HOC 是純函數(shù)攻泼,沒有副作用。

比如A組件需要發(fā)布訂閱,組件B需要發(fā)布訂閱忙菠,甚至更多的組件需要一個相似的功能何鸡,如果每次我們都是在每個組件里寫的話維護成本太高,效率太低牛欢,我們希望我們只寫base組件骡男,而用高級組件給包裹一下就能都擁有這個邏輯:

我們可以編寫一個創(chuàng)建組件的函數(shù)(高級函數(shù)),比如 CommentList 和 BlogPost傍睹,訂閱 DataSource隔盛。該函數(shù)將接受一個子組件作為它的其中一個參數(shù),該子組件將訂閱數(shù)據(jù)作為 prop拾稳。讓我們調(diào)用函數(shù) withSubscription:

const CommentListWithSubscription = withSubscription(
  CommentList,
  (DataSource) => DataSource.getComments()
);

const BlogPostWithSubscription = withSubscription(
  BlogPost,
  (DataSource, props) => DataSource.getBlogPost(props.id)
);

當(dāng)渲染 CommentListWithSubscription 和 BlogPostWithSubscription 時吮炕, CommentList 和 BlogPost 將傳遞一個 data prop,其中包含從 DataSource 檢索到的最新數(shù)據(jù):

// 此函數(shù)接收一個組件...
function withSubscription(WrappedComponent, selectData) {
  // ...并返回另一個組件...
  return class extends React.Component {
    constructor(props) {
      super(props);
      this.handleChange = this.handleChange.bind(this);
      this.state = {
        data: selectData(DataSource, props)
      };
    }

    componentDidMount() {
      // ...負責(zé)訂閱相關(guān)的操作...
      DataSource.addChangeListener(this.handleChange);
    }

    componentWillUnmount() {
      DataSource.removeChangeListener(this.handleChange);
    }

    handleChange() {
      this.setState({
        data: selectData(DataSource, this.props)
      });
    }

    render() {
      // ... 并使用新數(shù)據(jù)渲染被包裝的組件!
      // 請注意访得,我們可能還會傳遞其他屬性
      return <WrappedComponent data={this.state.data} {...this.props} />;
    }
  };
}

Portals

Portal 提供了一種將子節(jié)點渲染到存在于父組件以外的 DOM 節(jié)點的優(yōu)秀的方案龙亲。
第一個參數(shù)(child)是任何可渲染的 React 子元素,例如一個元素悍抑,字符串或 fragment鳄炉。第二個參數(shù)(container)是一個 DOM 元素。
這包含事件冒泡搜骡。一個從 portal 內(nèi)部觸發(fā)的事件會一直冒泡至包含 React 樹的祖先拂盯,即便這些元素并不是 DOM 樹 中的祖先。假設(shè)存在如下 HTML 結(jié)構(gòu):

<html>
  <body>
    <div id="app-root"></div>
    <div id="modal-root"></div>
  </body>
</html>

在 #app-root 里的 Parent 組件能夠捕獲到未被捕獲的從兄弟節(jié)點 #modal-root 冒泡上來的事件浆兰。

// 在 DOM 中有兩個容器是兄弟級 (siblings)
const appRoot = document.getElementById('app-root');
const modalRoot = document.getElementById('modal-root');

class Modal extends React.Component {
  constructor(props) {
    super(props);
    this.el = document.createElement('div');
  }

  componentDidMount() {
    // 在 Modal 的所有子元素被掛載后磕仅,
    // 這個 portal 元素會被嵌入到 DOM 樹中,
    // 這意味著子元素將被掛載到一個分離的 DOM 節(jié)點中簸呈。
    // 如果要求子組件在掛載時可以立刻接入 DOM 樹榕订,
    // 例如衡量一個 DOM 節(jié)點,
    // 或者在后代節(jié)點中使用 ‘a(chǎn)utoFocus’蜕便,
    // 則需添加 state 到 Modal 中劫恒,
    // 僅當(dāng) Modal 被插入 DOM 樹中才能渲染子元素。
    modalRoot.appendChild(this.el);
  }

  componentWillUnmount() {
    modalRoot.removeChild(this.el);
  }

  render() {
    return ReactDOM.createPortal(
      this.props.children,
      this.el,
    );
  }
}

class Parent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {clicks: 0};
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {
    // 當(dāng)子元素里的按鈕被點擊時轿腺,
    // 這個將會被觸發(fā)更新父元素的 state两嘴,
    // 即使這個按鈕在 DOM 中不是直接關(guān)聯(lián)的后代
    this.setState(state => ({
      clicks: state.clicks + 1
    }));
  }

  render() {
    return (
      <div onClick={this.handleClick}>
        <p>Number of clicks: {this.state.clicks}</p>
        <p>
          Open up the browser DevTools
          to observe that the button
          is not a child of the div
          with the onClick handler.
        </p>
        <Modal>
          <Child />
        </Modal>
      </div>
    );
  }
}

function Child() {
  // 這個按鈕的點擊事件會冒泡到父元素
  // 因為這里沒有定義 'onClick' 屬性
  return (
    <div className="modal">
      <button>Click</button>
    </div>
  );
}

ReactDOM.render(<Parent />, appRoot);

Refs and the DOM

Refs 提供了一種方式,允許我們訪問 DOM 節(jié)點或在 render 方法中創(chuàng)建的 React 元素族壳。
何時使用 Refs:

  • 下面是幾個適合使用 refs 的情況:
  • 管理焦點憔辫,文本選擇或媒體播放。
  • 觸發(fā)強制動畫仿荆。
  • 集成第三方 DOM 庫贰您。

創(chuàng)建refs:

16.3以后:

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.myRef = React.createRef();
  }
  render() {
    return <div ref={this.myRef} />;
  }
}

16.3以前:回調(diào)創(chuàng)建

class CustomTextInput extends React.Component {
  constructor(props) {
    super(props);

    this.textInput = null;

    this.setTextInputRef = element => {
      this.textInput = element;
    };

    this.focusTextInput = () => {
      // 使用原生 DOM API 使 text 輸入框獲得焦點
      if (this.textInput) this.textInput.focus();
    };
  }

  componentDidMount() {
    // 組件掛載后坏平,讓文本框自動獲得焦點
    this.focusTextInput();
  }

  render() {
    // 使用 `ref` 的回調(diào)函數(shù)將 text 輸入框 DOM 節(jié)點的引用存儲到 React
    // 實例上(比如 this.textInput)
    return (
      <div>
        <input
          type="text"
          ref={this.setTextInputRef}
        />
        <input
          type="button"
          value="Focus the text input"
          onClick={this.focusTextInput}
        />
      </div>
    );
  }
}

在 componentDidMount 或 componentDidUpdate 觸發(fā)前,React 會保證 refs 一定是最新的锦亦。
你可以在組件間傳遞回調(diào)形式的 refs舶替,就像你可以傳遞通過 React.createRef() 創(chuàng)建的對象 refs 一樣。

function CustomTextInput(props) {
  return (
    <div>
      <input ref={props.inputRef} />
    </div>
  );
}

class Parent extends React.Component {
  render() {
    return (
      <CustomTextInput
        inputRef={el => this.inputElement = el}
      />
    );
  }
}

訪問Refs

  • 原生元素:接受底層DOM作為current屬性
  • class組件:接受組件實例作為current屬性
  • 函數(shù)組件:不能在函數(shù)組件上創(chuàng)建refs

Render Props

術(shù)語 “render prop” 是指一種在 React 組件之間使用一個值為函數(shù)的 prop 共享代碼的簡單技術(shù)
解決什么問題需要這個Render Props呢杠园?
比如顾瞪,我有一個鼠標(biāo)組件,他會記錄每次用戶的鼠標(biāo)位置:

// <Mouse> 組件封裝了我們需要的行為...
class Mouse extends React.Component {
  constructor(props) {
    super(props);
    this.handleMouseMove = this.handleMouseMove.bind(this);
    this.state = { x: 0, y: 0 };
  }

  handleMouseMove(event) {
    this.setState({
      x: event.clientX,
      y: event.clientY
    });
  }

  render() {
    return (
      <div style={{ height: '100%' }} onMouseMove={this.handleMouseMove}>

        {/* ...但我們?nèi)绾武秩?<p> 以外的東西? */}
        <p>The current mouse position is ({this.state.x}, {this.state.y})</p>
      </div>
    );
  }
}

class MouseTracker extends React.Component {
  render() {
    return (
      <div>
        <h1>移動鼠標(biāo)!</h1>
        <Mouse />
      </div>
    );
  }
}

現(xiàn)在我們需要實現(xiàn)抛蚁,鼠標(biāo)移動的時候有一只貓跟著鼠標(biāo)陈醒,又或者其他組件會跟隨鼠標(biāo),那么他們都需要鼠標(biāo)的x篮绿,y孵延。 如果僅僅只是一只貓跟著鼠標(biāo)吕漂,那么還好亲配,我們把鼠標(biāo)和貓的代碼寫在一起就行了:

class Cat extends React.Component {
  render() {
    const mouse = this.props.mouse;
    return (
      <img src="/cat.jpg" style={{ position: 'absolute', left: mouse.x, top: mouse.y }} />
    );
  }
}

class MouseWithCat extends React.Component {
  constructor(props) {
    super(props);
    this.handleMouseMove = this.handleMouseMove.bind(this);
    this.state = { x: 0, y: 0 };
  }

  handleMouseMove(event) {
    this.setState({
      x: event.clientX,
      y: event.clientY
    });
  }

  render() {
    return (
      <div style={{ height: '100%' }} onMouseMove={this.handleMouseMove}>

        {/*
          我們可以在這里換掉 <p> 的 <Cat>   ......
          但是接著我們需要創(chuàng)建一個單獨的 <MouseWithSomethingElse>
          每次我們需要使用它時,<MouseWithCat> 是不是真的可以重復(fù)使用.
        */}
        <Cat mouse={this.state} />
      </div>
    );
  }
}

class MouseTracker extends React.Component {
  render() {
    return (
      <div>
        <h1>移動鼠標(biāo)!</h1>
        <MouseWithCat />
      </div>
    );
  }
}

但是問題就在于有很多組件都需要x惶凝,y這倆值吼虎,如果我們都這么寫毫無復(fù)用性可言,這個時候就出現(xiàn)了這個技術(shù)苍鲜,render props:

class Cat extends React.Component {
  render() {
    const mouse = this.props.mouse;
    return (
      <img src="/cat.jpg" style={{ position: 'absolute', left: mouse.x, top: mouse.y }} />
    );
  }
}

class Mouse extends React.Component {
  constructor(props) {
    super(props);
    this.handleMouseMove = this.handleMouseMove.bind(this);
    this.state = { x: 0, y: 0 };
  }

  handleMouseMove(event) {
    this.setState({
      x: event.clientX,
      y: event.clientY
    });
  }

  render() {
    return (
      <div style={{ height: '100%' }} onMouseMove={this.handleMouseMove}>

        {/*
          Instead of providing a static representation of what <Mouse> renders,
          use the `render` prop to dynamically determine what to render.
        */}
        {this.props.render(this.state)}
      </div>
    );
  }
}

class MouseTracker extends React.Component {
  render() {
    return (
      <div>
        <h1>移動鼠標(biāo)!</h1>
        <Mouse render={mouse => (
          <Cat mouse={mouse} />
        )}/>
      </div>
    );
  }
}

這樣就實現(xiàn)了x思灰,y的共享。
除此之外混滔,我們并不一定要用render來命名洒疚,我們也可以用其他屬性名,甚至是children:

render() {
    return (
      <div style={{ height: '100%' }} onMouseMove={this.handleMouseMove}>

        {/*
          Instead of providing a static representation of what <Mouse> renders,
          use the `render` prop to dynamically determine what to render.
        */}
        {this.props.children(this.state)}
      </div>
    );
  }
<div>
        <h1>移動鼠標(biāo)!</h1>
        <Mouse>
          {mouse => (
          <Cat mouse={mouse} />
        )}
        </Mouse>
</div>

Typescript

在 Create React App 中使用 TypeScript

npx create-react-app my-app --typescript

如需將 TypeScript 添加到現(xiàn)有的 Create React App 項目中坯屿,請參考此文檔.

添加 TypeScript 到現(xiàn)有項目中

  • 安裝typescript
npm install --save-dev typescript

恭喜油湖!你已將最新版本的 TypeScript 安裝到項目中。安裝 TypeScript 后我們就可以使用 tsc 命令领跛。在配置編譯器之前乏德,讓我們將 tsc 添加到 package.json 中的 “scripts” 部分:

"scripts": {
    "build": "tsc",
    // ...
  },
  • 配置 TypeScript 編譯器
npx tsc --init

tsconfig.json 文件中,有許多配置項用于配置編譯器吠昭。查看所有配置項的的詳細說明喊括,請參考此文檔

  • 首先矢棚,讓我們重新整理下項目目錄郑什,把所有的源代碼放入 src 目錄中。
  • 其次蒲肋,我們將通過配置項告訴編譯器源碼和輸出的位置蘑拯。
// tsconfig.json

{
  "compilerOptions": {
    // ...
    "rootDir": "src",
    "outDir": "build"
    // ...
  },
}

類型定義

為了能夠顯示來自其他包的錯誤和提示劫拢,編譯器依賴于聲明文件。聲明文件提供有關(guān)庫的所有類型信息强胰。這樣舱沧,我們的項目就可以用上像 npm 這樣的平臺提供的三方 JavaScript 庫。

Bundled
DefinitelyTyped :DefinitelyTyped 是一個龐大的聲明倉庫偶洋,為沒有聲明文件的 JavaScript 庫提供類型定義熟吏。這些類型定義通過眾包的方式完成,并由微信和開源貢獻者一起管理玄窝。例如牵寺,React 庫并沒有自己的聲明文件。但我們可以從 DefinitelyTyped 獲取它的聲明文件恩脂。只要執(zhí)行以下命令帽氓。

# yarn
yarn add --dev @types/react

# npm
npm i --save-dev @types/react

你現(xiàn)在已做好編碼準(zhǔn)備了!我們建議你查看以下資源來了解有關(guān) TypeScript 的更多知識:

嚴(yán)格模式

import React from 'react';

function ExampleApplication() {
  return (
    <div>
      <Header />
      <React.StrictMode>
        <div>
          <ComponentOne />
          <ComponentTwo />
        </div>
      </React.StrictMode>
      <Footer />
    </div>
  );
}

在上述的示例中俩块,不會對 Header 和 Footer 組件運行嚴(yán)格模式檢查黎休。但是,ComponentOne 和 ComponentTwo 以及它們的所有后代元素都將進行檢查玉凯。
StrictMode 目前有助于:

使用 PropTypes 進行類型檢查

PropTypes 提供一系列驗證器势腮,可用于確保組件接收到的數(shù)據(jù)類型是有效的。在本例中, 我們使用了 PropTypes.string漫仆。當(dāng)傳入的 prop 值類型不正確時捎拯,JavaScript 控制臺將會顯示警告。出于性能方面的考慮盲厌,propTypes 僅在開發(fā)模式下進行檢查署照。

參考文獻

https://react.docschina.org/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市吗浩,隨后出現(xiàn)的幾起案子建芙,更是在濱河造成了極大的恐慌,老刑警劉巖拓萌,帶你破解...
    沈念sama閱讀 218,546評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件岁钓,死亡現(xiàn)場離奇詭異,居然都是意外死亡微王,警方通過查閱死者的電腦和手機屡限,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來炕倘,“玉大人钧大,你說我怎么就攤上這事≌中” “怎么了啊央?”我有些...
    開封第一講書人閱讀 164,911評論 0 354
  • 文/不壞的土叔 我叫張陵眶诈,是天一觀的道長。 經(jīng)常有香客問我瓜饥,道長逝撬,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,737評論 1 294
  • 正文 為了忘掉前任乓土,我火速辦了婚禮宪潮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘趣苏。我一直安慰自己狡相,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,753評論 6 392
  • 文/花漫 我一把揭開白布食磕。 她就那樣靜靜地躺著尽棕,像睡著了一般。 火紅的嫁衣襯著肌膚如雪彬伦。 梳的紋絲不亂的頭發(fā)上滔悉,一...
    開封第一講書人閱讀 51,598評論 1 305
  • 那天,我揣著相機與錄音媚朦,去河邊找鬼氧敢。 笑死日戈,一個胖子當(dāng)著我的面吹牛询张,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播浙炼,決...
    沈念sama閱讀 40,338評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼份氧,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了弯屈?” 一聲冷哼從身側(cè)響起蜗帜,我...
    開封第一講書人閱讀 39,249評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎资厉,沒想到半個月后厅缺,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,696評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡宴偿,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,888評論 3 336
  • 正文 我和宋清朗相戀三年湘捎,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片窄刘。...
    茶點故事閱讀 40,013評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡窥妇,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出娩践,到底是詐尸還是另有隱情活翩,我是刑警寧澤烹骨,帶...
    沈念sama閱讀 35,731評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站材泄,受9級特大地震影響沮焕,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜拉宗,卻給世界環(huán)境...
    茶點故事閱讀 41,348評論 3 330
  • 文/蒙蒙 一遇汞、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧簿废,春花似錦空入、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,929評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至单料,卻和暖如春埋凯,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背扫尖。 一陣腳步聲響...
    開封第一講書人閱讀 33,048評論 1 270
  • 我被黑心中介騙來泰國打工白对, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人换怖。 一個月前我還...
    沈念sama閱讀 48,203評論 3 370
  • 正文 我出身青樓甩恼,卻偏偏與公主長得像,于是被迫代替她去往敵國和親沉颂。 傳聞我的和親對象是個殘疾皇子条摸,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,960評論 2 355

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

  • 深入JSX date:20170412筆記原文其實JSX是React.createElement(componen...
    gaoer1938閱讀 8,069評論 2 35
  • 歡迎訪問我的最佳實踐網(wǎng)站 一個動態(tài)導(dǎo)入加載組件的高階組件. 示例 用戶反饋: "我現(xiàn)在非常癡迷于: create-...
    lxg1986閱讀 26,479評論 0 24
  • 作為一個合格的開發(fā)者,不要只滿足于編寫了可以運行的代碼铸屉。而要了解代碼背后的工作原理钉蒲;不要只滿足于自己的程序...
    六個周閱讀 8,448評論 1 33
  • 離開那片霞紅之地,你將繼續(xù)去編織你青春里的某一段時光彻坛。在等待你的綠皮小火車到來之時顷啼,我們休憩的地方,聽“青春又醉倒...
    小芥閱讀 683評論 8 7
  • 你渴了昌屉, 我是離你最近的一杯茶钙蒙。 你干渴的唇是我的克星, 我終于被你一飲而盡怠益。 你卻沒有解渴仪搔, 我只剩一只空空的杯...
    相對兩無厭不止敬亭山閱讀 413評論 0 4