React为什么要使用高阶组件件应如何使用

React&高阶组件入门介绍
高阶组件的定义
HoC 不属于 React 的
API,它是一种实现模式,本质上是一个函数,接受一个或多个 React 组件作为参数,返回一个全新的 React
组件,而不是改造现有的组件,这样的组件被称为高阶组件。开发过程中,有的功能需要在多个组件类复用时,这时可以创建一个
const HoC = (WrappendComponent) =& {
const WrappingComponent = (props) =& (
return WrappingC
上述代码中,接受
WrappendComponent 作为参数,此参数就是将要被 HoC 包装的普通组件,在 render 中包裹一个 div,赋予它
className 属性,最终产生的 WrappingComponent 和 传入的 WrappendComponent
是两个完全不同的组件。
在 WrappingComponent
中,可以读取、添加、编辑、删除传给 WrappendComponent 的 props,也可以用其它元素包裹
WrappendComponent,用来实现封装样式、添加布局或其它操作。
const HoC = (WrappedComponent, LoginView) =& {
const WrappingComponent = () =& {
&&const {user} =
&&if (user) {
&&} else {
return WrappingC
上述代码中有两个组件,WrappedComponent 和 LoginView,如果传入的 props 中存在
user,则正常显示的 WrappedComponent 组件,否则显示 LoginView 组件,让用户去登录。HoC
传递的参数可以为多个,传递多个组件定制新组件的行为,例如用户登录状态下显示主页面,未登录显示登录界面;在渲染列表时,传入 List 和
Loading 组件,为新组件添加加载中的行为。
const HoC = (WrappendComponent) =& {
class WrappingComponent extends WrappendComponent {
&&render() (
& &const {user, ...otherProps} =
& &this.props =
super.render();
return WrappingC
WrappingComponent
是一个新组件,它继承自 WrappendComponent,共享父级的函数和属性。可以使用 super.render() 或者
super.componentWillUpdate()
调用父级的生命周期函数,但是这样会让两个组件耦合在一起,降低组件的复用性。
中对组件的封装是按照最小可用单元的思想来进行封装的,理想情况下,一个组件只做一件事情,符合 OOP
中的单一职责原则。如果需要对组件的功能增强,通过组合的方式或者添加代码的方式对组件进行增强,而不是修改原有的代码。
不要在 render
函数中使用高阶组件
render() {
// 每一次render函数调用都会创建一个新的EnhancedComponent实例
// EnhancedComponent1 !== EnhancedComponent2
const EnhancedComponent = enhance(MyComponent);
// 每一次都会使子对象树完全被卸载或移除
React 中的 diff
算法会比较新旧子对象树,确定是否更新现有的子对象树或丢掉现有的子树并重新挂载。
必须将静态方法做拷贝
// 定义静态方法
WrappedComponent.staticMethod = function() {}
// 使用高阶组件
const EnhancedComponent = enhance(WrappedComponent);
// 增强型组件没有静态方法
typeof EnhancedComponent.staticMethod === 'undefined' //
Refs属性不能传递
HoC中指定的
ref,并不会传递到子组件,需要通过回调函数使用 props 传递。
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。本文代码浅显易懂,思想深入实用。此属于react进阶用法,如果你还不了解react,建议从开始看起。
我们都知道高阶函数是什么, 高阶组件其实是差不多的用法,只不过传入的参数变成了react组件,并返回一个新的组件.
A higher-order component is a function that takes a component and returns a new component.
const EnhancedComponent = higherOrderComponent(WrappedComponent);
高阶组件是react应用中很重要的一部分,最大的特点就是重用组件逻辑。它并不是由React API定义出来的功能,而是由React的组合特性衍生出来的一种设计模式。如果你用过redux,那你就一定接触过高阶组件,因为react-redux中的connect就是一个高阶组件。
原文欢迎star另外本次demo代码都放在&clone下来跑一下加深理解
先来一个最简单的高阶组件
import React, { Component } from 'react';
import simpleHoc from './simple-hoc';
class Usual extends Component {
render() {
console.log(this.props, 'props');
import React, { Component } from 'react';
const simpleHoc = WrappedComponent =& {
console.log('simpleHoc');
return class extends Component {
render() {
组件Usual通过simpleHoc的包装,打了一个log... 那么形如simpleHoc就是一个高阶组件了,通过接收一个组件class Usual,并返回一个组件class。 其实我们可以看到,在这个函数里,我们可以做很多操作。 而且return的组件同样有自己的生命周期,function,另外,我们看到也可以把props传给WrappedComponent(被包装的组件)。 高阶组件的定义我都是用箭头函数去写的,如有不适请参照
装饰器模式
高阶组件可以看做是装饰器模式(Decorator Pattern)在React的实现。即允许向一个现有的对象添加新的功能,同时又不改变其结构,属于包装模式(Wrapper Pattern)的一种
ES7中添加了一个decorator的属性,使用@符表示,可以更精简的书写。那上面的例子就可以改成:
import React, { Component } from 'react';
import simpleHoc from './simple-hoc';
@simpleHoc
export default class Usual extends Component {
render() {
是同样的效果。当然兼容性是存在问题的,通常都是通过babel去编译的。 babel提供了plugin,高阶组件用的是类装饰器,所以用transform-decorators-legacy&
引入里我们写的最简单的形式,就是属性代理(Props Proxy)的形式。通过hoc包装wrappedComponent,也就是例子中的Usual,本来传给Usual的props,都在hoc中接受到了,也就是props proxy。 由此我们可以做一些操作
操作props最直观的就是接受到props,我们可以做任何读取,编辑,删除的很多自定义操作。包括hoc中定义的自定义事件,都可以通过props再传下去。
import React, { Component } from 'react';
const propsProxyHoc = WrappedComponent =& class extends Component {
handleClick() {
console.log('click');
render() {
然后我们的Usual组件render的时候,&console.log(this.props)&会得到handleClick.
refs获取组件实例当我们包装Usual的时候,想获取到它的实例怎么办,可以通过引用(ref),在Usual组件挂载的时候,会执行ref的回调函数,在hoc中取到组件的实例。通过打印,可以看到它的props, state,都是可以取到的。
import React, { Component } from 'react';
const refHoc = WrappedComponent =& class extends Component {
componentDidMount() {
console.log(this.instanceComponent, 'instanceComponent');
render() {
这里不是通过ref获取state, 而是通过 { props, 回调函数 } 传递给wrappedComponent组件,通过回调函数获取state。这里用的比较多的就是react处理表单的时候。通常react在处理表单的时候,一般使用的是受控组件(),即把input都做成受控的,改变value的时候,用onChange事件同步到state中。当然这种操作通过Container组件也可以做到,具体的区别放到后面去比较。看一下代码就知道怎么回事了:
这里我们把state,onChange等方法都放到HOC里,其实是遵从的react组件的一种规范,子组件简单,傻瓜,负责展示,逻辑与操作放到Container。比如说我们在HOC获取到用户名密码之后,再去做其他操作,就方便多了,而state,处理函数放到Form组件里,只会让Form更加笨重,承担了本不属于它的工作,这样我们可能其他地方也需要用到这个组件,但是处理方式稍微不同,就很麻烦了。
反向继承(Inheritance Inversion),简称II,本来我是叫继承反转的...因为有个模式叫控制反转嘛...跟属性代理的方式不同的是,II采用通过 去继承WrappedComponent,本来是一种嵌套的关系,结果II返回的组件却继承了WrappedComponent,这看起来是一种反转的关系。通过继承WrappedComponent,除了一些静态方法,包括生命周期,state,各种function,我们都可以得到。上栗子:
iiHoc return的组件通过继承,拥有了Usual的生命周期及属性,所以didMount会打印,state也通过constructor执行,得到state.usual。其实,你还可以通过II:
这里HOC里定义的组件继承了WrappedComponent的render(渲染),我们可以以此进行hijack(劫持),也就是控制它的render函数。栗子:
我这里通过二阶函数,把config参数预制进HOC, 算是一种柯理化的思想。栗子很简单,这个hoc就是添加样式的功能。但是它暴露出来的信息却不少。首先我们可以通过config参数进行逻辑判断,有条件的渲染,当然这个参数的作用很多,react-redux中的connect不就是传入了props-key 嘛。再就是我们还可以拿到WrappedComponent的元素树,可以进行修改操作。最后就是我们通过div包裹,设置了style。但其实具体如何操作还是根据业务逻辑去处理的...
我的应用场景
通常我会通过高阶组件去优化之前老项目写的不好的地方,比如两个页面UI几乎一样,功能几乎相同,仅仅几个操作不太一样,却写了两个耦合很多的页面级组件。当我去维护它的时候,由于它的耦合性过多,经常会添加一个功能(这两个组件都要添加),我要去改完第一个的时候,还要改第二个。而且有时候由于我的记性不好,会忘掉第二个... 就会出现bug再返工。更重要的是由于个人比较懒,不想去重构这部分的代码,因为东西太多了,花费太多时间。所以加新功能的时候,我会写一个高阶组件,往HOC里添加方法,把那两个组件包装一下,也就是属性代理。这样新代码就不会再出现耦合,旧的逻辑并不会改变,说不定哪天心情好就会抽离一部分功能到HOC里,直到理想的状态。
另一种情况就是之前写过一个组件A,做完上线,之后产品加了一个新需求,很奇怪要做的组件B跟A几乎一模一样,但稍微有区别。那我可能就通过II的方式去继承之前的组件A,比如它在didMount去fetch请求,需要的数据是一样的。不同的地方我就会放到HOC里,存储新的state这样,再通过劫持渲染,把不同的地方,添加的地方进行处理。但其实这算Hack的一种方式,能快速解决问题,也反映了组件设计规划之初有所不足(原因比较多)。
Container解决不了的时候甚至不太优雅的时候。其实大部分时候包一层Container组件也能做到差不多的效果,比如操作props,渲染劫持。但其实还是有很大区别的。比如我们现在有两个功能的container,添加样式和添加处理函数的,对Usual进行包装。栗子:
import React, { Component } from 'react';
import Usual from './usual';
class StyleContainer extends Component {
render() {
import React, { Component } from 'react';
import StyleContainer from './container-add-style';
class FuncContainer extends Component {
handleClick() {
console.log('click');
render() {
const props = {
...this.props,
handleClick: this.handleClick,
外层Container必须要引入内层Container,进行包装,还有props的传递,同样要注意包装的顺序。当然你可以把所有的处理都放到一个Container里。那用HOC怎么处理呢,相信大家有清晰的答案了。
const addFunc = WrappedComponent =& class extends Component {
handleClick() {
console.log('click');
render() {
const props = {
...this.props,
handleClick: this.handleClick,
const addStyle = WrappedComponent =& class extends Component {
render() {
const WrappenComponent = addStyle(addFunc(Usual));
class WrappedUsual extends Component {
render() {
console.log(this.props, 'props');
显然HOC是更优雅一些的,每个HOC都定义自己独有的处理逻辑,需要的时候只需要去包装你的组件。相较于Container的方式,HOC耦合性更低,灵活性更高,可以自由组合,更适合应付复杂的业务。当然当你的需求很简单的时候,还是用Container去自由组合,应用场景需要你清楚。
注意点(约束)
其实官网有很多,简单介绍一下。
最重要的原则就是,注意高阶组件不会修改子组件,也不拷贝子组件的行为。高阶组件只是通过组合的方式将子组件包装在容器组件中,是一个无副作用的纯函数
要给hoc添加class名,便于debugger。我上面的好多栗子组件都没写class 名,请不要学我,因为我实在想不出叫什么名了... 当我们在chrome里应用React-Developer-Tools的时候,组件结构可以一目了然,所以DisplayName最好还是加上。
静态方法要复制无论PP还是II的方式,WrappedComponent的静态方法都不会复制,如果要用需要我们单独复制。
refs不会传递。 意思就是HOC里指定的ref,并不会传递到子组件,如果你要使用最好写回调函数通过props传下去。
不要在render方法内部使用高阶组件。简单来说react的差分算法会去比较 NowElement === OldElement, 来决定要不要替换这个elementTree。也就是如果你每次返回的结果都不是一个引用,react以为发生了变化,去更替这个组件会导致之前组件的状态丢失。
使用compose组合HOC。函数式编程的套路... 例如应用redux中的middleware以增强功能。
const addFuncHOC = ...
const addStyleHOC = ...
关于注意点,官网有所介绍,不再赘述。
高阶组件最大的好处就是解耦和灵活性,在react的开发中还是很有用的。当然这不可能是高阶组件的全部用法。掌握了它的一些技巧,还有一些限制,你可以结合你的应用场景,发散思维,尝试一些不同的用法。
阅读(...) 评论()浅谈React高阶组件
转载 &更新时间:日 09:10:25 & 作者:呆头呆脑丶
这篇文章主要介绍了浅谈React高阶组件,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
前段时间在工作中写Hybrid页面时遇到了这样的一个场景,公司需要一系列的活动组件,在每个组件注册的时候都需要调用App端提供的一个接口。一开始也考虑了几种方式,包括mixin、组件继承以及react高阶组件。但经过了种种衡量,最后选择使用了高阶组件的做法。
那什么是高级组件?首先你得先了解请求ES6中的class只是语法糖,本质还是原型继承。能够更好的进行说明,我们将不会修改组件的代码。而是通过提供一些能够包裹组件的组件, 并通过一些额外的功能来增强组件。这样的组件我们称之为高阶组件(Higher-Order Component)。
1、Mixins的缺点
React官方已不推荐使用Mixins的技术来实现代码的重用,Mixins技术有一系列的缺点,首先Mixins会造成命名冲突,我们通过以下的方式来注入Mixins:
var myMixins = require('myMixins');
var Button = React.createClass({
mixins: [myMixins],
如果你需要注入多个mixins,其中一个是自己的,另外的可能是第三方的。那有可能在两个mixins里使用了相同名称的方法,这会使得其中的一个不起作用,而你能做的只有修改其中一个方法的名称。另一方面,一个mixins一开始可能是非常简单的,仅仅需要实现某一个功能,但当业务越加的复杂,需要往其中加入更多的方法的时候,就会变得非常复杂。要,可以查看官方博客。
2、组件继承
对于我自己来说这种方法以前使用的比较多,先创建一个BaseComponent,在其中实现一系列公共的方法,其后的每个组件都继承于这个组件,但缺点是不够灵活,在基础组件中只能实现一些比较固定的方法,而对于每个组件的定制化会有很大的限制。
3、React高阶组件
由于mixins的一系列缺点,React官方也意识到使用mixins所带来的痛点远远高于技术本身产生的优点,而高阶组件便可以代替mixins,而且当深入之后它还有着更加丰富的用法。
高阶组件(HOC)是React中对组件逻辑进行重用的高级技术。但高阶组件本身并不是React API。它只是一种模式,这种模式是由React自身的组合性质必然产生的。
说到高阶组件,就先得说到高阶函数了,高阶函数是至少满足下列条件的函数:
1、接受一个或多个函数作为输入
2、输出一个函数
在javascript这门函数为一等公民的语言中,高阶函数的使用还是非常之多的,像我们平时的回调函数等等,都用到了高阶函数的知识。我们先来看一个简单的高阶函数
var fun = function(x, y) {
return x +
fun是一个函数,下面我们将整个函数作为参数传递给另一个函数
var comp = function(x, y, f) {
return f(x,y);
comp(1,2,fun) // 3
高阶组件定义
类比高阶函数的定义,高阶组件就是接受一个组件作为参数,在函数中对组件做一系列的处理,随后返回一个新的组件作为返回值。
我们先定义一个高阶组件BaseActivity
const BaseActivity = (WrappedComponent) =& {
return class extends Component {
render() {
&div&我的包裹组件&/div&
&WrappedComponent /&
&/section&
组件接受一个被包裹的组件作为参数,返回了一个经过处理的匿名组件。
在其他组件中使用这个高阶组件
class Example extends React.PureComponent {
constructor(props) {
super(props);
this.state = {
width: '100%',
height: '100%'
componentWillMount() {
if ((navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i))) {
this.setState({
width: '375px',
height: '640px'
render() {
let { width, height } = this.
&div className="activity"&
&div className="activity-content" style={{ width, height }}&
&button className="btn"&参加活动&/button&
export default BaseActivity(Example);
具体用法就是在export 组件的时候,使用BaseActivity函数来包裹这个组件,看下输出的react dom内容
在Example组件外面包裹了一个匿名组件。
既然高阶组件是一个函数,我们就可以向里面传递我们需要的参数
const BaseActivity = (WrappedComponent, title) =& {
return class extends Component {
render() {
&div&{title}&/div&
&WrappedComponent /&
&/section&
在Example中这样export
export default BaseActivity(Example, '这是高阶组件的参数');
我们看下输出的react dom
可以看到参数已经传递进去了。
当然还可以这样用(柯里化)
const BaseActivity (title) =& (WrappedComponent) =& {
return class extends Component {
render() {
&div&{title}&/div&
&WrappedComponent /&
&/section&
在Example中这样export
export default BaseActivity('这是高阶组件的参数')(Example);
这种用法在ant-design的表单以及redux的connect中我们都可以看到
const WrappedDemo = Form.create()(Demo)
export default connect(mapStateToProps, mapDispatchToProps)(Counter)
高阶组件还可以扩展原组件的props属性,如下所示:
const BaseActivity (title) =& (WrappedComponent) =& {
return class extends Component {
render() {
const newProps = {
id: Math.random().toString(8)
&div&{title}&/div&
&WrappedComponent {...this.props} {...newProps}/&
&/section&
看下输出的react dom
高阶组件的缺点
高阶组件也有一系列的缺点,首先是被包裹组件的静态方法会消失,这其实也是很好理解的,我们将组件当做参数传入函数中,返回的已经不是原来的组件,而是一个新的组件,原来的静态方法自然就不存在了。如果需要保留,我们可以手动将原组件的方法拷贝给新的组件,或者使用hoist-non-react-statics之类的库来进行拷贝。
高阶函数对于初学者来说可能不太好理解,但当你深入其中,了解其中的原理之后,我们可以使用高阶函数来完成很多的工作。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具React 高阶组件入门介绍
高阶组件的定义
HoC 不属于 React 的 API,它是一种实现模式,本质上是一个函数,接受一个或多个 React 组件作为参数,返回一个全新的 React 组件,而不是改造现有的组件,这样的组件被称为高阶组件。开发过程中,有的功能需要在多个组件类复用时,这时可以创建一个 Hoc。
const HoC = (WrappendComponent) =& {
const WrappingComponent = (props) =& (
&div className=&container&&
&WrappendComponent {...props} /&
&/div&
return WrappingC
上述代码中,接受 WrappendComponent 作为参数,此参数就是将要被 HoC 包装的普通组件,在 render 中包裹一个 div,赋予它 className 属性,最终产生的 WrappingComponent 和 传入的 WrappendComponent 是两个完全不同的组件。
在 WrappingComponent 中,可以读取、添加、编辑、删除传给 WrappendComponent 的 props,也可以用其它元素包裹 WrappendComponent,用来实现封装样式、添加布局或其它操作。
const HoC = (WrappedComponent, LoginView) =& {
const WrappingComponent = () =& {
const {user} = this.
if (user) {
return &WrappedComponent {...this.props} /&
return &LoginView {...this.props} /&
return WrappingC
上述代码中有两个组件,WrappedComponent 和 LoginView,如果传入的 props 中存在 user,则正常显示的 WrappedComponent 组件,否则显示 LoginView 组件,让用户去登录。HoC 传递的参数可以为多个,传递多个组件定制新组件的行为,例如用户登录状态下显示主页面,未登录显示登录界面;在渲染列表时,传入 List 和 Loading 组件,为新组件添加加载中的行为。
const HoC = (WrappendComponent) =& {
class WrappingComponent extends WrappendComponent {
render() (
const {user, ...otherProps} = this.
this.props = otherP
return super.render();
return WrappingC
WrappingComponent 是一个新组件,它继承自 WrappendComponent,共享父级的函数和属性。可以使用 super.render() 或者 super.componentWillUpdate() 调用父级的生命周期函数,但是这样会让两个组件耦合在一起,降低组件的复用性。
React 中对组件的封装是按照最小可用单元的思想来进行封装的,理想情况下,一个组件只做一件事情,符合 OOP 中的单一职责原则。如果需要对组件的功能增强,通过组合的方式或者添加代码的方式对组件进行增强,而不是修改原有的代码。
不要在 render 函数中使用高阶组件
render() {
// 每一次render函数调用都会创建一个新的EnhancedComponent实例
// EnhancedComponent1 !== EnhancedComponent2
const EnhancedComponent = enhance(MyComponent);
// 每一次都会使子对象树完全被卸载或移除
return &EnhancedComponent /&;
React 中的 diff 算法会比较新旧子对象树,确定是否更新现有的子对象树或丢掉现有的子树并重新挂载。
必须将静态方法做拷贝
// 定义静态方法
WrappedComponent.staticMethod = function() {/*...*/}
// 使用高阶组件
const EnhancedComponent = enhance(WrappedComponent);
// 增强型组件没有静态方法
typeof EnhancedComponent.staticMethod === 'undefined' // true
Refs属性不能传递
HoC中指定的 ref,并不会传递到子组件,需要通过回调函数使用 props 传递。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持JavaScript中文网。
你可能感兴趣的文章:
Vue.js(读音 /vju:/, 类似于 view)是一个构建数据驱动的 web 界面的库。Vue.js 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件。
Vue.js 自身不是一个全能框架——它只聚焦于视图层。因此...
如果我有几个页面都需要有分页效果,不可能每个页面都去复制一下这段代码吧,意思是封装一下,变成通用的组件。
首先使用基础 Vue 构造器,创建一个“子类”,Vue.extend( options )
var barHtml = '&...
socket.io为什么会诞生呢?请看下面文字说明。
为什么需要socket.io?
node.js提供了高效的服务端运行环境,但是由于浏览器端对HTML5的支持不一,为了兼容所有浏览器,提供卓越的实时的用户体验,并且为程序员提供客户端与服...
如果你在两个月前问我对React的看法,我很可能这样说:
我的模板在哪里?javascript中的HTML在做些什么疯狂的事情?JSX开起来非常奇怪!快向它开火,消灭它吧!
那是因为我没有理解它.
我发誓,React 无疑是在正确的轨道...
可怜的我用着华为3C手机,用别人现成的组件都好卡,为了适应我这种屌丝,于是自己简化写了一版的照片预览效果,暂时无缩放功能,以后可能有空再加吧,你也可以自己加下,这是个github上的开源项目。它的github地址是:https://gith...
本篇介绍如何使用bootstrap fileinput.js(最好用的文件上传组件)来进行图片的展示,上传,包括springMVC后端文件保存。
二、插件引入
&link type=“text/css” rel=“s...
JavaScript事件的一个重要的方面是它们拥有一些相对一致的特点,可以给开发提供强大的功能;
最方便和强大的就是事件对象,它们可以帮你处理鼠标事件和键盘敲击方面的情况;
此外还可以修改一般事件的捕获/冒泡流的函数;
一 事件对象
项目中遇到倒计时需求,考虑到以后在其他模块也会用到,就自己封装了一个组件。便于以后复用。
组件需求如下:
接收父级组件传递截止日期
接收父级组件传递标题
组件countdown.html代码
&div clas...
随着近日Paypal和Netflix宣告 迁移到Node.js, 服务器端Javascript平台已经证明其自身在企业领域的价值. 这对于Node来说是一小步,对于Javascript而言却是一大跨越啊! 来自.NET, Java, PHP...
闲来没事,分享下项目中自己写的分页组件。来不及了,直接上车。
输入框可任意输入,并会自动提交到该页
fontawesome,bootstrap
&ul class=&page clearf...
微信公众号搜索: FedJavaScript ,选择关注,与十万前端开发者一起探讨前端学习
扫描下方二维码回复 1024 获取验证码
验证码有误,请重新输入
本站(www.javascriptcn.com)所提供的等资源来源互联网,仅供学习研究之用,版权归该资源的合法拥有者所有,如用于商业用途,请购买正版,原作者若认为本站侵犯了您的版权,请联系我们,我们会立即删除!
鄂ICP备号-1
没有账号?}

我要回帖

更多关于 react高阶组件封装 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信