文档章节

React.js的一些淫技

曾建凯
 曾建凯
发布于 2016/12/19 12:39
字数 1421
阅读 228
收藏 0

React.js的确很好用,可是我相信,除非是整个团队,彻底使用React.js重写全部UI组件,React.js才可能用得比较顺手。多数情况下,仍是半React.js组件,半传统JS技术架构的模式。

而React.js的组件,本身是一个比较封闭的状态,除了通过setState的方式从外部和组件进行交互,并不推荐使用传统OOP的方式,对组件属性进行强行修改(真的不建议,这么做你就是找死),当然,你可以把setState方法写n个接口,这样仍然属于setState范畴。

那么问题来了,传统前端JS技术架构下,如何和React.js进行交互呢?这篇文章就针对这个问题,进行一些简单的介绍,解决思路其实都是很简单的土办法。

中间代理对象

假定,我做了一个React.js的组件,这个组件用于选定公司的ID。在组件显示上,我们需要显示一个按钮,按钮的文字是选中的公司的名称,点击按钮,可以显示挑选公司的弹出层。而按钮的后面有一个隐藏域,放的是实际的公司ID。

那么因为种种原因,这个弹出层,没有用React.js封装,而是传统的html,采用ajax的方式加载,且这个弹出层要加载的页面内容、交互都已经完成了,不想再额外用React.js重新做一个组件了。

所以这时候的需求是,点击按钮,ajax加载公司列表,然后选中公司,将数据反馈回给React.js组件。问题的难点就在最后,何如将数据反馈回React.js组件。

这时候,可以考虑使用中间代理对象的模式,将React.js的组件实例,传递给中间代理对象,然后在ajax的页面,判定中间代理对象是否具有这个React.js实例,如果存在,则执行组件实例的setState方法。

下面举个实际的例子。

初始的界面如下:

这里有一个【选择供应商】的按钮,当点击供应商按钮后,会弹出如下的界面:

这个界面是用传统的html做的,采用ajax的方式进行加载。当用户点击【选中】按钮,则会关闭这个弹出层,且将用户选定的供应商名称和ID传回给刚才的React.js的组件。

代码部分如下:

React.js的组件叫做ClientSearchInput.jsx

import * as _ from 'lodash';
import * as React from 'react';
import * as ReactDOM from 'react-dom';

import Erp from 'page/erp/Erp';
import UI from 'module/UI';

let erp = Erp.getInstance();

let copy = false;

class ClientSearchInput extends React.Component {

	index = 0;

	constructor(props) {
		super(props);
		this.index += 1;
		this.state = {
			value: this.props.value || '',
			name: '',
		};
	}

	getColumn() {
		return this.props.column
	}

	getType() {
		let column = this.getColumn();
		if (column.type !== 'client' && column.type !== 'supplier')
			return 'client';
		return column.type;
	}

	getTypeName() {
		if (this.state.name)
			return this.state.name;
		return '选择' + (this.getType() === 'client' ? '客户' : '供应商');
	}

	getPlaceholder() {
		return '输入' + (this.getType() === 'client' ? '客户' : '供应商') + '名称或者简称';
	}

	openLayer() {
		let uri = erp.uri('ui_search_client').setData({ type: this.getType() }) + '';
		let ajax = $.ajax(uri);
		ajax.done((html) => {
			UI.modal('ui_search_client', {
				header: '搜索' + this.getTypeName(),
				content: html,
				component: this,
			}).show(html);
		});
	}

	clean() {
		this.setState({
			value: '',
			name: '',
		});
	}

	copy() {
		copy = {
			name: this.state.name,
			value: this.state.value,
		}
	}

	paste() {
		if (copy) {
			this.setState(copy);
			console.log(copy);
		}
	}

	render() {
		let editable = !!this.props.editable;
		return (
			<div>
				<div className="ui tiny buttons">
					<button type="button" disabled={!editable} className="ui button tiny blue" onClick={e => this.openLayer()}>{this.getTypeName()}</button>
					<button type="button" disabled={!this.state.value} className="ui button tiny green" onClick={e => this.copy()}>复制</button>
					<button type="button" disabled={!this.state.value} className="ui button tiny red" onClick={e => this.paste()}>粘贴</button>
					<button type="button" disabled={!this.state.value} className="ui button tiny black" onClick={e => this.clean()}>清除</button>
				</div>
				<input
					type="hidden"
					name={this.props.name}
					value={this.state.value}/>
			</div>
		);
	}
}

module.exports = ClientSearchInput;

openLayer函数部分,是触发打开弹出层的位置。UI这个类的源代码在这篇文章里面《Semantic UI带你飞——Modal》,当时因为还没开始接触React.js,所以这个Modal没有做成是React.js的组件。这里UI.modal('ui_search_client')实际上就充当了中间代理对象,当然,实际上我们也没有需要额外做什么,只是把组件实例传过去而已。

而在ajax的页面js中,重新加载回这个组件:

requirejs(['module/UI'], function(UI) {
	// 前面省略
	var modal = UI.modal('ui_search_client'), opts = modal.options;
	if (opts && opts.component) {
		parent.find('button.select-client-button').click(function() {
			var button = $(this);
			var id = button.data('id'), name = button.data('name');
			opts.component.setState({
				value: id,
				name: name
			}, function() {
				modal.hide();
			})
		});
	}
});

哦,其实一切都很简单,是不是?

对象快捷链接

现在前端开发,大多是遵循amd规范,或者npm那样的模式(这是什么md来着,忘记了),即不直接写入全局对象的环境,而采用exports的方法,将需要的元素对外暴露,所以每个js脚本等于实际上都是一个密闭的scope。我们通过暴露接口的方法,提供一个读取、写入的接口,数据存放在密闭的scope中,不直接被外部访问。

这样做,的确保证了一定的安全性,但频繁的使用接口,有时候也加大了代码调试过程中繁琐。那么现在提供一种很直接的方式。

假定读取、写入的接口,明确写入的是一个对象接口,这时候我们可以利用JS对象的特性,做直接的链接操作。

即假定有,这样一个set/get的接口:

var storage = {}

any.set = function(key, object) {
    storage[key] = object || {};
}

any.get = function(key) {
    return storage[key] || false;
}

我们在另外一个scope中,确保了某个key的对象必然存在。

var localObject = any.get('local');
if (localObject === false) {
    localObject = {}
    any.set('local', localObject);
}

这样,localObject实际上已经直接指向了storage['local'],之后,我们可以对localObject,进行直接的对象访问或操作,而在别的scope中,取回local,已经是实时更新的状态,这样是不是顿时明朗了很多呢?

这实际上是JS的好处,也是JS的弊端,可以适用于如jQuery的 $(id).prop 的方法中。

© 著作权归作者所有

共有 人打赏支持
曾建凯
粉丝 324
博文 57
码字总数 90297
作品 0
广州
技术主管
laden666666/vue-element-resize-event

vue-element-resize-event 一个扩展vue的时间,使其可以监听普通元素的resize事件。HTML中如果在窗口或框架被调整大小时发生resize事件,但是元素尺寸变化的时候却没有对应的事件。但是基于j...

laden666666
05/09
0
0
本年度好技能

《认清Android框架 MVC,MVP和MVVM》 http://blog.csdn.net/jdsjlzx/article/details/51174396 《精通 Android Data Binding》 https://github.com/LyndonChin/MasteringAndroidDataBinding ......

jiangwu
2016/08/06
29
0
Apache 禁止使用 Facebook 的“BSD +专利”代码

据 react-etc.net 报道,关于 React.js 的开源许可证从去年 7 月份争议到现在,Apache 基金会终于确认了立场,反对使用 React.js 和 Facebook 其他使用此许可证(BSD+Patents licensed)的流...

王练
2017/07/17
3K
7
40 行代码内实现一个 React.js

作者:胡子大哈 原文链接:http://huziketang.com/blog/posts/detail?postId=58aea515204d50674934c3ac 转载请注明出处,保留原文链接和作者信息。 ================================== 目录...

胡子大哈
2017/02/23
0
0
基于 React.js + Redux + Bootstrap 的 Ruby China 示例

最近在学习前端的各大流行框架, 主要学习了 Vue.js 和 React.js, 前段时间用 Vue.js + uikit 实现了 V2EX 的克隆版本, 最近又用 React.js + redux + bootstrap 实现了 RubyChina 的克隆版本,...

rina_liuzhen
2016/10/21
975
2

没有更多内容

加载失败,请刷新页面

加载更多

你为什么在Redis里读到了本应过期的数据

一个事故的故事 晚上睡的正香突然被电话吵醒,对面是开发焦急的声音:我们的程序在访问redis的时候读到了本应过期的key导致整个业务逻辑出了问题,需要马上解决。 看到这里你可能会想:这是不...

IT--小哥
今天
2
0
祝大家节日快乐,阖家幸福! centos GnuTLS 漏洞

yum update -y gnutls 修复了GnuTLS 漏洞。更新到最新 gnutls.x86_64 0:2.12.23-22.el6 版本

yizhichao
昨天
5
0
Scrapy 1.5.0之选择器

构造选择器 Scrapy选择器是通过文本(Text)或 TextResponse 对象构造的 Selector 类的实例。 它根据输入类型自动选择最佳的解析规则(XML vs HTML): >>> from scrapy.selector import Sele...

Eappo_Geng
昨天
4
0
Windows下Git多账号配置,同一电脑多个ssh-key的管理

Windows下Git多账号配置,同一电脑多个ssh-key的管理   这一篇文章是对上一篇文章《Git-TortoiseGit完整配置流程》的拓展,所以需要对上一篇文章有所了解,当然直接往下看也可以,其中也有...

morpheusWB
昨天
5
0
中秋快乐!!!

HiBlock
昨天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部