anu - controlledComponent
/**
input, select, textarea这几个元素如果指定了value/checked的**状态属性**,就会包装成受控组件或非受控组件
受控组件是指,用户除了为它指定**状态属性**,还为它指定了onChange/onInput/disabled等用于控制此状态属性
变动的属性
反之,它就是非受控组件,非受控组件会在框架内部添加一些事件,阻止**状态属性**被用户的行为改变,只能被setState改变
*/
import { typeNumber } from "./util"; export function processFormElement(vnode, dom, props) {
var domType = dom.type;
var duplexType = duplexMap[domType];
if (duplexType) {
var data = duplexData[duplexType];
var duplexProp = data[0];
var keys = data[1];
var eventName = data[2];
if (duplexProp in props && !hasOtherControllProperty(props, keys)) {
// eslint-disable-next-line
console.warn(`你为${vnode.type}[type=${domType}]元素指定了${duplexProp}属性,
但是没有提供另外的${ Object.keys(keys)}来控制${duplexProp}属性的变化
那么它即为一个非受控组件,用户无法通过输入改变元素的${duplexProp}值`);
dom[eventName] = data[3];
}
if (duplexType === 3) {
postUpdateSelectedOptions(vnode);
}
}
} function hasOtherControllProperty(props, keys) {
for (var key in props) {
if (keys[key]) {
return true;
}
}
}
var duplexMap = {
color: 1,
date: 1,
datetime: 1,
"datetime-local": 1,
email: 1,
month: 1,
number: 1,
password: 1,
range: 1,
search: 1,
tel: 1,
text: 1,
time: 1,
url: 1,
week: 1,
textarea: 1,
checkbox: 2,
radio: 2,
"select-one": 3,
"select-multiple": 3
}; function preventUserInput(e) {
var target = e.target;
var name = e.type === "textarea" ? "innerHTML" : "value";
target[name] = target._lastValue;
} function preventUserClick(e) {
e.preventDefault();
} function preventUserChange(e) {
var target = e.target;
var value = target._lastValue;
var options = target.options;
if (target.multiple) { updateOptionsMore(options, options.length, value);
} else {
updateOptionsOne(options, options.length, value);
}
} var duplexData = {
1: [
"value",
{
onChange: 1,
onInput: 1,
readOnly: 1,
disabled: 1
},
"oninput",
preventUserInput
],
2: [
"checked",
{
onChange: 1,
onClick: 1,
readOnly: 1,
disabled: 1
},
"onclick",
preventUserClick
],
3: [
"value",
{
onChange: 1,
disabled: 1
},
"onchange",
preventUserChange
]
}; export function postUpdateSelectedOptions(vnode) {
var props = vnode.props,
multiple = !!props.multiple,
value =
typeNumber(props.value) > 1
? props.value
: typeNumber(props.defaultValue) > 1
? props.defaultValue
: multiple ? [] : "",
options = [];
collectOptions(vnode, props, options);
if (multiple) {
updateOptionsMore(options, options.length, value);
} else {
updateOptionsOne(options, options.length, value);
}
} /**
* 收集虚拟DOM select下面的options元素,如果是真实DOM直接用select.options
*
* @param {VNode} vnode
* @param {any} props
* @param {Array} ret
*/
function collectOptions(vnode, props, ret) {
var arr = props.children;
for (var i = 0, n = arr.length; i < n; i++) {
var el = arr[i];
if (el.type === "option") {
ret.push(el);
} else if (el.type === "optgroup") {
collectOptions(el, el.props, ret);
}
}
} function updateOptionsOne(options, n, propValue) {
var selectedValue = "" + propValue;
for (let i = 0; i < n; i++) {
let option = options[i];
let value = getOptionValue(option, option.props);
if (value === selectedValue) {
getOptionSelected(option, true);
return;
}
}
if (n) {
getOptionSelected(options[0], true);
}
} function updateOptionsMore(options, n, propValue) {
var selectedValue = {};
try {
for (let i = 0; i < propValue.length; i++) {
selectedValue["&" + propValue[i]] = true;
}
} catch (e) {
/* istanbul ignore next */
console.warn('<select multiple="true"> 的value应该对应一个字符串数组'); // eslint-disable-line
}
for (let i = 0; i < n; i++) {
let option = options[i];
let value = getOptionValue(option, option.props);
let selected = selectedValue.hasOwnProperty("&" + value);
getOptionSelected(option, selected);
}
} function getOptionValue(option, props) {
if (!props) {
return getDOMOptionValue(option);
}
//这里在1.1.1改动过, props.value === undefined ? props.children[0].text : props.value;
return props.value === undefined ? props.children : props.value;
} function getDOMOptionValue(node) {
if (node.hasAttribute && node.hasAttribute("value")) {
return node.getAttribute("value");
}
var attr = node.getAttributeNode("value");
if (attr && attr.specified) {
return attr.value;
}
return node.innerHTML.trim();
} function getOptionSelected(option, selected) {
var dom = option._hostNode || option;
dom.selected = selected;
}
anu - controlledComponent的更多相关文章
- 发布高性能迷你React框架anu
anu, 读作[安努],原意为苏美尔的主神. anu是我继avalon之后又一个新框架(github仓库为https://github.com/RubyLouvre/anu, 欢迎加星与试用) 此框架 ...
- 利用React/anu编写一个弹出层
本文将一步步介绍如何使用React或anu创建 一个弹出层. React时代,代码都是要经过编译的,我们很多时间都耗在babel与webpack上.因此本文也介绍如何玩webpack与babel. 我 ...
- 高性能迷你React框架anu在低版本IE的实践
理想是丰满的,现实是骨感的,react早期的版本虽然号称支持IE8,但是页面总会不自觉切换到奇异模式下,导致报错.因此必须让react连IE6,7都支持,这才是最安全.但React本身并不支持IE6, ...
- anu小程序快速入门
众所周知,微信推出小程序以来,可谓火遍大江南北,就像当前互联网兴起时,大家忙着抢域名与开私人博客一样.小程序之所以这么火,是因为微信拥有庞大的用户量,并且腾讯帮你搞定后台问题及众多功能问题(如分享,支 ...
- Codeforces Round #618 (Div. 2)C. Anu Has a Function
Anu has created her own function ff : f(x,y)=(x|y)−y where || denotes the bitwise OR operation. For ...
- React/anu实现Touchable
在RN中有一个叫Touchable 的组件,这里我们重演如何实现它. Touchable存在的意义是屏蔽click的问题.移动端与手机的click 在一些浏览器是有差异,比如说著名的300ms延迟. ...
- React/anu实现弹出层2
这次是使用了一个比较罕见的APIReactDOM.unstable_renderSubtreeIntoContainer,ReactDOM.unstable_renderSubtreeIntoCont ...
- anu - browser
import { oneObject, recyclables, typeNumber } from "./util"; //用于后端的元素节点 export function D ...
- anu - reactIE
import { options } from "./util"; import { Children } from "./Children"; import ...
随机推荐
- vue router菜单 存在点哪个但还是会显示active
<router-link to="/" exact>Home</router-link> <router-link to="/add&quo ...
- BeyondCompare
BeyondCompare可对文本,照片,文件夹,注册表等等进行比较 在git看不清楚版本和改动项的时候,直接将生产上的包拉下来和即将发布的包,作对比.
- sublime插件安装及常用插件配置
1.下载 :百度云 工具中 2.注册 sgbteam Single User License EA7E-1153259 8891CBB9 F1513E4F 1A3405C1 A865D53F 115F ...
- Git工作区、暂存区和版本库
基本概念 我们先来理解下Git 工作区.暂存区和版本库概念 工作区:就是你在电脑里能看到的目录. 暂存区:英文叫stage, 或index.一般存放在 ".git目录下" 下的in ...
- R—读取数据(导入csv,txt,excel文件)
导入CSV.TXT文件 read.table函数:read.table函数以数据框的格式读入数据,所以适合读取混合模式的数据,但是要求每列的数据数据类型相同. read.table读取数据非常方便,通 ...
- [.NET开发] C#连接MySQL的两个简单代码示例
实现代码一.使用的是mysql自带的驱动安装一下即可 这是一个简单的例子. 在这里有个问题:dataset如果没设主键的话,可能会引起一些对数库操作的问题,比如会造成updata出现错误. stati ...
- mysql5.7执行sql语句出现only_full_group_by错误
在/etc/my.cnf的[mysqld]组中添加 sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISI ...
- hdu1180 优先队列bfs+判断方向
诡异的楼梯 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others)Total Subm ...
- JDBC连接SQLSERVER
package xhs;import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; im ...
- CISC, RISC 探究
iPhone Simulator Intel iPhone ARM 区别很大, Intel目前的处理器主要为IA架构, IA-32即俗称x86,包括桌面处理器系列(赛扬,奔腾,酷睿等)以及服务器处 ...