react import怎么使用

react import怎么使用,第1张

说说React
一个组件,有自己的结构,有自己的逻辑,有自己的样式,会依赖一些资源,会依赖某些其他组件。比如日常写一个组件,比较常规的方式:
- 通过前端模板引擎定义结构

- JS文件中写自己的逻辑

- CSS中写组件的样式

- 通过RequireJS、SeaJS这样的库来解决模块之间的相互依赖,

那么在React中是什么样子呢?
结构和逻辑
在React的世界里,结构和逻辑交由JSX文件组织,React将模板内嵌到逻辑内部,实现了一个JS代码和HTML混合的JSX。
结构
在JSX文件中,可以直接通过 ReactcreateClass 来定义组件:
var CustomComponent = ReactcreatClass({
render: function(){
return (<div className="custom-component"></div>);
}
});
通过这种方式可以很方便的定义一个组件,组件的结构定义在render函数中,但这并不是简单的模板引擎,我们可以通过js方便、直观的 *** 控组件结构,比如我想给组件增加几个节点:
var CustomComponent = ReactcreatClass({
render: function(){
var $nodes = ['h','e','l','l','o']map(function(str){
return (<span>{str}</span>);
});
return (<div className="custom-component">{$nodes}</div>);
}
});
通过这种方式,React使得组件拥有灵活的结构。那么React又是如何处理逻辑的呢?
逻辑
写过前端组件的人都知道,组件通常首先需要相应自身DOM事件,做一些处理。必要时候还需要暴露一些外部接口,那么React组件要怎么做到这两点呢?
事件响应
比如我有个按钮组件,点击之后需要做一些处理逻辑,那么React组件大致上长这样:
var ButtonComponent = ReactcreateClass({
render: function(){
return (<button>屠龙宝刀,点击就送</button>);
}
});
点击按钮应当触发相应地逻辑,一种比较直观的方式就是给button绑定一个 onclick 事件,里面就是需要执行的逻辑了:
function getDragonKillingSword() {
//送宝刀
}
var ButtonComponent = ReactcreateClass({
render: function(){
return (<button onclick="getDragonKillingSword()">屠龙宝刀,点击就送</button>);
}
});
但事实上 getDragonKillingSword() 的逻辑属于组件内部行为,显然应当包装在组件内部,于是在React中就可以这么写:
var ButtonComponent = ReactcreateClass({
getDragonKillingSword: function(){
//送宝刀
},
render: function(){
return (<button onClick={thisgetDragonKillingSword}>屠龙宝刀,点击就送</button>);
}
});
这样就实现内部事件的响应了,那如果需要暴露接口怎么办呢?
暴露接口
事实上现在 getDragonKillingSword 已经是一个接口了,如果有一个父组件,想要调用这个接口怎么办呢?
父组件大概长这样:
var ImDaddyComponent = ReactcreateClass({
render: function(){
return (
<div>
//其他组件
<ButtonComponent />
//其他组件
</div>
);
}
});
那么如果想手动调用组件的方法,首先在ButtonComponent上设置一个 ref="" 属性来标记一下,比如这里把子组件设置成 <ButtonComponent ref="getSwordButton"/> ,那么在父组件的逻辑里,就可以在父组件自己的方法中通过这种方式来调用接口方法:
thisrefsgetSwordButtongetDragonKillingSword();
看起来屌屌哒~那么问题又来了,父组件希望自己能够按钮点击时调用的方法,那该怎么办呢?
配置参数
父组件可以直接将需要执行的函数传递给子组件:
<ButtonComponent clickCallback={thisgetSwordButtonClickCallback}/>
然后在子组件中调用父组件方法:
var ButtonComponent = ReactcreateClass({
render: function(){
return (<button onClick={thispropsclickCallback}>屠龙宝刀,点击就送</button>);
}
});
子组件通过 thisprops 能够获取在父组件创建子组件时传入的任何参数,因此 thisprops 也常被当做配置参数来使用
屠龙宝刀每个人只能领取一把,按钮点击一下就应该灰掉,应当在子组件中增加一个是否点击过的状态,这又应当处理呢?
组件状态
在React中,每个组件都有自己的状态,可以在自身的方法中通过 thisstate 取到,而初始状态则通过 getInitialState() 方法来定义,比如这个屠龙宝刀按钮组件,它的初始状态应该是没有点击过,所以 getInitialState 方法里面应当定义初始状态 clicked: false 。而在点击执行的方法中,应当修改这个状态值为 click: true :
var ButtonComponent = ReactcreateClass({
getInitialState: function(){
//确定初始状态
return {
clicked: false
};
},
getDragonKillingSword: function(){
//送宝刀
//修改点击状态
thissetState({
clicked: true
});
},
render: function(){
return (<button onClick={thisgetDragonKillingSword}>屠龙宝刀,点击就送</button>);
}
});
这样点击状态的维护就完成了,那么render函数中也应当根据状态来维护节点的样式,比如这里将按钮设置为 disabled ,那么render函数就要添加相应的判断逻辑:
render: function(){
var clicked = thisstateclicked;
if(clicked)
return (<button disabled="disabled" onClick={thisgetDragonKillingSword}>屠龙宝刀,点击就送</button>);
else
return (<button onClick={thisgetDragonKillingSword}>屠龙宝刀,点击就送</button>);
}
小节
这里简单介绍了通过JSX来管理组件的结构和逻辑,事实上React给组件还定义了很多方法,以及组件自身的生命周期,这些都使得组件的逻辑处理更加强大
资源加载
CSS文件定义了组件的样式,现在的模块加载器通常都能够加载CSS文件,如果不能一般也提供了相应的插件。事实上CSS、可以看做是一种资源,因为加载过来后一般不需要做什么处理。
React对这一方面并没有做特别的处理,虽然它提供了Inline
Style的方式把CSS写在JSX里面,但估计没有多少人会去尝试,毕竟现在CSS样式已经不再只是简单的CSS文件了,通常都会去用Less、
Sass等预处理,然后再用像postcss、myth、autoprefixer、cssmin等等后处理。资源加载一般也就简单粗暴地使用模块加载器
完成了
组件依赖
组件依赖的处理一般分为两个部分:组件加载和组件使用
组件加载
React没有提供相关的组件加载方法,依旧需要通过 <script> 标签引入,或者使用模块加载器加载组件的JSX和资源文件。
组件使用
如果细心,就会发现其实之前已经有使用的例子了,要想在一个组件中使用另外一个组件,比如在 ParentComponent 中使用 ChildComponent ,就只需要在 ParentComponent 的 render() 方法中写上 <ChildComponent /> 就行了,必要的时候还可以传些参数。
疑问
到这里就会发现一个问题,React除了只处理了结构和逻辑,资源也不管,依赖也不管。是的,React将近两万行代码,连个模块加载器都没有提供,更与Angularjs,jQuery等不同的是,他还不带啥脚手架…没有Ajax库,没有Promise库,要啥啥没有…
虚拟DOM
那它为啥这么大?因为它实现了一个虚拟DOM(Virtual DOM)。虚拟DOM是干什么的?这就要从浏览器本身讲起
如我们所知,在浏览器渲染网页的过程中,加载到HTML文档后,会将文档解析并构建DOM树,然后将其与解析CSS生成的CSSOM树一起结合产
生爱的结晶——RenderObject树,然后将RenderObject树渲染成页面(当然中间可能会有一些优化,比如RenderLayer树)。
这些过程都存在与渲染引擎之中,渲染引擎在浏览器中是于JavaScript引擎(JavaScriptCore也好V8也好)分离开的,但为了方便JS
*** 作DOM结构,渲染引擎会暴露一些接口供JavaScript调用。由于这两块相互分离,通信是需要付出代价的,因此JavaScript调用DOM提
供的接口性能不咋地。各种性能优化的最佳实践也都在尽可能的减少DOM *** 作次数。
而虚拟DOM干了什么?它直接用JavaScript实现了DOM树(大致上)。组件的HTML结构并不会直接生成DOM,而是映射生成虚拟的
JavaScript DOM结构,React又通过在这个虚拟DOM上实现了一个 diff
算法找出最小变更,再把这些变更写入实际的DOM中。这个虚拟DOM以JS结构的形式存在,计算性能会比较好,而且由于减少了实际DOM *** 作次数,性能会
有较大提升

由于CSS的规则是全局性的,添加任何一个样式,在全局都有效,优点是方便复用,缺点是会根据 权重的计算 造成样式冲突,非常难以管理。

有了钉子,自然就会有锤子。随着前端的发展出现了各种CSS模块解决方案,主要分两种:
一类是采用JS或者JSON 的方式写CSS,比如 jsxstyle , react-style ,虽然可以采用JS成熟方案来管理css, 但是它无法使用postcss ,sass等css预处理器,并且衍生了大批的api, 使用的代价较大。
另一类还是采用css 来写样式, 不过是通过工具生成CSS作用域的方式实现模块化,比如CSS module。常用的BEM命名技巧或者团队中约定的方案来实现命名空间从而实现模块化,不过约定总会出现问题,于是就出现了通过工具,比如webpack的css-loader根据算法,实现css 模块化。

webpack 内置的 css-loader 自带了CSS modoule, 配置如下:

create-react-app 20以上的版本中内置启动了CSS module, 如果需要特殊配置,则需要eject *** 作, 在webpackconfigjs 中:

CSS module 默认采用局部样式,即给每个css 名添加上了“:local”, 对应的全局性的写法:

compose 组合样式:
对于样式复用,CSS module提供了唯一的方式 "compose":

多CSS class 的写法:

Sass 变量与JS共享

Css module 作者建议:
1不使用选择器,只使用 class 名来定义样式
2不层叠多个 class,只使用一个 class 把所有样式定义好
3不嵌套
4使用 composes 组合来实现复用

采用 classnames 来增强CSS module 在react 中的使用,类似Angular 中的样式指令:

参考链接: >一、选取 DOM 元素
在 jQuery 中,我们已经熟悉了使用 sizzle 选择器来完成 DOM 元素的选取。而在 React 中,我们可以使用 ref 来更有针对性的获取元素。
import React from 'react';class Demo extends ReactCompoent {
getDomNode() { return thisrefsroot; // 获取 Dom Node }
render() { return ( <div ref="root">just a
demo</div> ); }}
这是最简单的获取 node 的方式,如果有多层结构嵌套呢?没有关系。
import React from 'react';class Demo extends ReactCompoent {
getRootNode() { return thisrefsroot; // 获取根节点 Dom Node }
getLeafNode() { return thisrefsleaf; // 获取叶节点 Dom Node }
render() { return ( <div ref="root">
<div ref="leaf">just a demo</div>
</div> ); }}
如果是组件和组件嵌套呢?也没关系,父组件仍然可以拿到子组件的根节点。
import React from 'react';import ReactDOM from 'react-dom';class Sub
extends ReactCompoent { render() { return (
<div>a sub component</div> ); }}class Demo extends
ReactCompoent { getDomNode() { return thisrefsroot; // 获取
Dom Node } getSubNode() { return
ReactDOMfindDOMNode(thisrefssub); // 获取子组件根节点 } render() {
return ( <div ref="root"> <Sub
ref="sub" /> </div> ); }}
上面使用了比较易懂的 API 来解释 Ref 的用法,但里面包含了一些现在 React 不太推荐和即将废弃的方法,如果用 React 推荐的写法,我们可以这样写。
import React from 'react';import ReactDOM from 'react-dom';class Sub
extends ReactCompoent { getDomNode() { return thisrootNode;
} render() { return ( <div ref={(c) =>
thisrootNode = c}>a sub component</div> ); }}class
Demo extends ReactCompoent { getDomNode() { return
thisrootNode; // 获取 Dom Node } getSubNode() { return
thissubgetDomNode(); // 获取子组件根节点 } render() { return (
<div ref={(c) => thisrootNode = c}>
<Sub ref={(c) => thissub = c} /> </div>
); }}
有人可能会问,那子组件怎么拿父组件的 Dom Node 呢,从 React
的单向数据流角度出发,遇到这种情况我们应该通过回调通知给父组件,再由父组件自行判断如何修改 Node,其实父组件拿子组件的 Node
情况也很少,大多数情况下我们是通过 props 传递变化给子组件,获取子组件
Node,更多的情况下是为了避开大量重新渲染去修改一些Node的属性(比如 scrollLeft)。
二、DOM *** 作
jQuery 中提供了丰富的 *** 作方法,但一个个 *** 作 DOM 元素有的时候真的很烦人并且容易出错。React 通过数据驱动的思想,通过改变 view 对应的数据,轻松实现 DOM 的增删 *** 作。
class Demo extends ReactCompoent { constructor(props) {
super(props); thisstate = { list: [1, 2, 3],
}; thisaddItemFromBottom = thisaddItemFromBottombind(this);
thisaddItemFromTop = thisaddItemFromTopbind(this);
thisdeleteItem = thisdeleteItembind(this); }
addItemFromBottom() { thissetState({ list:
thisstatelistconcat([4]), }); } addItemFromTop() {
thissetState({ list: [0]concat(thisstatelist),
}); } deleteItem() { const newList =
[thisstatelist]; newListpop(); thissetState({
list: newList, }); } render() { return (
<div> {thisstatelistmap((item) =>
<div>{item}</div>)} <button
onClick={thisaddItemFromBottom}>尾部插入 Dom 元素</button>
<button onClick={thisaddItemFromTop}>头部插入 Dom
元素</button> <button
onClick={thisdeleteItem}>删除 Dom 元素</button>
</div> ); }} 三、事件的监听
React 通过根节点代理的方式,实现了一套很优雅的事件监听方案,在组件 unmount 时也不需要自己去处理内存回收相关的问题,非常的方便。
import React from 'react';class Demo extends ReactComponent {
constructor(props) { super(props); thishandleClick =
thishandleClickbind(this); } handleClick() {
alert('我是d窗'); } render() { return ( <div
onClick={thishandleClick}>点击我d出d框</div> ); }}
这里有一个小细节就是
bind 的时机,bind 是为了保持相应函数的上下文,虽然也可以在 onClick 那里 bind,但这里选择在 constructor 里
bind 是因为前者会在每次 render 的时候都进行一次 bind,返回一个新函数,是比较消耗性能的做法。


React 的事件监听,毕竟只能监听至 root component,而我们在很多时候要去监听 window/document 上的事件,如果
resize、scroll,还有一些 React 处理不好的事件,比如
scroll,这些都需要我们自己来解决。事件监听为了屏蔽差异性需要做很多的工作,这里像大家推荐一个第三方库来完成这部分的工作,
add-dom-event-listener ,用法和原生的稍有区别,是因为这个库并不旨在做 polyfill,但用法还是很简单。

var addEventListener = require('add-dom-event-listener');var handler =
addEventListener(documentbody, 'click', function(e){
consolelog(etarget); // works for ie consolelog(enativeEvent); //
native dom event});handlerremove(); // detach event listener
另一个选择是 bean ,达到了 IE6+ 级别的兼容性。
四、事件的触发
和事件监听一样,无论是 Dom 事件还是自定义事件,都有很优秀的第三方库帮我们去处理,如果是 DOM 事件,推荐 bean ,如果是自定义事件的话,推荐 PubSubJS 。
五、documentready
React
作为一个 view 层框架,通常情况下页面只有一个用于渲染 React 页面组件的根节点 div,因此
documentready,只需把脚本放在这个 div 后面执行即可。而对于渲染完成后的回调,我们可以使用 React 提供的
componentDidMount 生命周期。
import React from 'react';class Demo
extends ReactComponent { constructor(props) { super(props);
} componentDidMount() { doSomethingAfterRender(); //
在组件渲染完成后执行一些 *** 作,如远程获取数据,检测 DOM 变化等。 } render() { return (
<div>just a demo</div> ); }} 六、attr 方法
jQuery 使用 attr 方法,获取 Dom 元素的属性。在 React 中也可以配合 Ref 直接读取 DOM 元素的属性。
import React from 'react';class Demo extends ReactComponent {
constructor(props) { super(props); }
componentDidMount() { thisrootNodescrollLeft = 10; //
渲染后将外层的滚动调至 10px } render() { return ( <div
ref={(c) => thisrootNode = c}
style={{ width: '100px', overflow: 'auto' }} >
<div style={{ width: '1000px' }}>just a demo</div>
</div> ); }}
但是,在大部分的情况下,我们完全不需要做,因为 React 的单向数据流和数据驱动渲染,我们可以不通过 DOM,轻松拿到和修改大部分我们需要的 DOM 属性。
import React from 'react';class Demo extends ReactComponent {
constructor(props) { super(props); thisstate = {
link: '//>react项目使用less,开发中需要修改antd样式,但又不需要全局修改,记录一下解决方案。

styleName 是外部包裹的className,ant-drawer-content 是antd的样式。

:global{}包裹可以解决module下css样式不被改变名称,styleName包裹,保证只在该div样式下生效。

G6 V310  Github:  >使用 style={} ,如

不同于vue的scoped,react引入的样式未进行模块化处理,因此均为全局样式,需要自行隔离

导入css名改为 modulecss 结尾

对于 create-react-app 创建的应用,直接 npm install --save node-sass 即可在组件中引用scss,无需更改webpack配置


欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/yw/13073579.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-30
下一篇 2023-05-30

发表评论

登录后才能评论

评论列表(0条)

保存