文档章节

React.js的一些淫技

曾建凯
 曾建凯
发布于 2016/12/19 12:39
字数 1421
阅读 193
收藏 0
点赞 0
评论 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 的方法中。

© 著作权归作者所有

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

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

laden666666 ⋅ 05/09 ⋅ 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 ⋅ 0

Apache 禁止使用 Facebook 的“BSD +专利”代码

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

王练 ⋅ 2017/07/17 ⋅ 7

40 行代码内实现一个 React.js

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

胡子大哈 ⋅ 2017/02/23 ⋅ 0

程序员市场需求调查:React.js获前五!

  【IT168 资讯】Upwork的最新技能指数调查显示,与去年同期相比,排名前十的增长最快的自由职业技能列表(包括区块链,比特币,React.js,深度学习等)跃升超过200%。Swift,AngularJS和机器...

it168网站 ⋅ 2017/11/13 ⋅ 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 ⋅ 2

CodingMr.Zhou/Peer-To-Peer

#怎么把项目在本地跑起来? 纠结了很久,考虑到各方面的因素,我决定抛弃!改用,相信我,这样写起代码来,真的很爽! ##先啰嗦几句## 不得不说,react.js + Flux 的编程方式上手也许有点困难...

CodingMr.Zhou ⋅ 2015/06/22 ⋅ 0

React.js 2016 最佳实践 徬梓阅读 1584收藏 71

译者按:近几个月React相关话题依旧火热,相信越来越多的开发者在尝试这样一项技术,我们团队也在PC和移动端不断总结经验。2016来了,这应该是 React走向成熟的一年,不管你是新手,还是已经...

我家有宝 ⋅ 2016/01/27 ⋅ 0

ReactJS 静态网页生成器--Gatsby

Gatsby 可以使用 React.js 把纯文本转换到动态博客或者网站上。 目标: 无需重载页面转换 热重载编辑 为构建静态网站创建 React.js 组件模型和生态系统 直观的基于目录的 URLs 支持 "Starter...

叶秀兰 ⋅ 2015/09/30 ⋅ 0

wengcd/react-start-kit-flux-demo

React Starter Kit — "isomorphic" web app boilerplate React Starter Kit is an opinionated boilerplate for web development built on top of Facebook's React library, Node.js / Exp......

wengcd ⋅ 2015/10/11 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

在java中读取文件(也支持读取jar中的文件)

getClass().getResourceAsStream("文件名.格式"); 这个方法是用于获取当前类所在目录下的文件;需要将文件放到和当前类同一个包下面 比如我有个类在 com.test这个包下, 要读取一个test.jpg的图...

太黑_thj ⋅ 42分钟前 ⋅ 0

CentOS 7 源码编译安装 MySQL 5.7记录

没事瞎折腾,本来可以yum安装,却偏偏去要编译源码。 1. 安装依赖包 1). 安装cmake等依赖 # yum install cmake ncurses ncurses-devel bison bison-devel 2). 安装boost 1.59.0 # wget htt...

admin_qing ⋅ 44分钟前 ⋅ 0

tcp/ip详解-链路层

简介 设计链路层的目的: 为IP模块发送和接收IP数据报 为ARP模块发送ARP请求和接收ARP应答 为RARP模块发送RARP请求和接收RARP应答 TCP/IP支持多种链路层协议,如以太网、令牌环往、FDDI、RS-...

loda0128 ⋅ 今天 ⋅ 0

spring.net aop代码例子

https://www.cnblogs.com/haogj/archive/2011/10/12/2207916.html

whoisliang ⋅ 今天 ⋅ 0

发送短信如何限制1小时内最多发送11条短信

发送短信如何限制1小时内最多发送11条短信 场景: 发送短信属于付费业务,有时为了防止短信攻击,需要限制发送短信的频率,例如在1个小时之内最多发送11条短信. 如何实现呢? 思路有两个 截至到当...

黄威 ⋅ 昨天 ⋅ 0

mysql5.7系列修改root默认密码

操作系统为centos7 64 1、修改 /etc/my.cnf,在 [mysqld] 小节下添加一行:skip-grant-tables=1 这一行配置让 mysqld 启动时不对密码进行验证 2、重启 mysqld 服务:systemctl restart mysql...

sskill ⋅ 昨天 ⋅ 0

Intellij IDEA神器常用技巧六-Debug详解

在调试代码的时候,你的项目得debug模式启动,也就是点那个绿色的甲虫启动服务器,然后,就可以在代码里面断点调试啦。下面不要在意,这个快捷键具体是啥,因为,这个keymap是可以自己配置的...

Mkeeper ⋅ 昨天 ⋅ 0

zip压缩工具、tar打包、打包并压缩

zip 支持压缩目录 1.在/tmp/目录下创建目录(study_zip)及文件 root@yolks1 study_zip]# !treetree 11└── 2 └── 3 └── test_zip.txt2 directories, 1 file 2.yum...

蛋黄Yolks ⋅ 昨天 ⋅ 0

聊聊HystrixThreadPool

序 本文主要研究一下HystrixThreadPool HystrixThreadPool hystrix-core-1.5.12-sources.jar!/com/netflix/hystrix/HystrixThreadPool.java /** * ThreadPool used to executed {@link Hys......

go4it ⋅ 昨天 ⋅ 0

容器之上传镜像到Docker hub

Docker hub在国内可以访问,首先要创建一个账号,这个后面会用到,我是用126邮箱注册的。 1. docker login List-1 Username不能使用你注册的邮箱,要用使用注册时用的username;要输入密码 ...

汉斯-冯-拉特 ⋅ 昨天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部