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 ...
随机推荐
- require的压缩命令
注意点 node r.js -o baseUrl=js name=main out=js/build.js paths.jquery=empty: 注:baseUrl是可选的 取决于页面是否有写这个入 ...
- 【TCP/IP详解 卷一:协议】第十二章 广播和多播
建议参考:广播和多播 IGMP 12.1 引言 IP地址知识点回顾: IP地址分为三种:(1)单播地址 (2)广播地址 (3)多播地址 另外一种是,IP地址一般划分成五类:A-E类. 单播 考虑 类似 ...
- C++课程上 有关“指针” 的小结
上完了C++的第二节课以后,觉得应该对这个内容进行一个小结,巩固知识点,并对我的心情进行了一个侧面烘托... 开始上课的老师: 正在上课的我: 上去敲代码的我: 过程是这样的: 下来的我: 非常的尴尬 ...
- stm32 pwm 电调 电机
先上代码 python 树莓派版本,通俗表现原理.stm32 C语言版本在后面 import RPi.GPIO as GPIO import time mode=2 IN1=11 def setup( ...
- apiCloud检出代码出现以下图示错误:
问题如下: Initialized empty Git repository in H:/simlpe/.git/ 已经在 H:\simlpe 完成必要的项目初始化工作正在尝试从代码服务器获取数据.. ...
- UVa 1395 苗条的生成树(Kruskal+并查集)
https://vjudge.net/problem/UVA-1395 题意: 给出一个n结点的图,求苗条度(最大边减最小边的值)尽量小的生成树. 思路: 主要还是克鲁斯卡尔算法,先仍是按权值排序,对 ...
- 会员通过消费攒积分,升级RENEW以及降级的需求
需求看上去及其简单,如下: 用文字描述就开始不容易了. 先按等级排个序,根据下一个等级,推前一个等级: --C---B----V-----A 在计算一下升级需要的积分:--C表示普通会员-----需要 ...
- 告诉maven,我真的不需要web.xml
<!-- 告诉maven,我真的不需要web.xml --> <plugin> <groupId>org.apache.maven.plugins</grou ...
- Lua面向对象 --- 多态
多态,简单的理解就是事物的多种形态.专业的术语说就是:同一个实现接口,使用不同的实例而执行不同的操作. 工程结构: BaseRoom.lua: BaseRoom = {} function BaseR ...
- Linux后台日志定时清理脚本
一. 简介 linux是一个很能自动产生文件的系统,日志.邮件.备份等.虽然现在硬盘廉价,我们可以有很多硬盘空间供这些文件浪费,让系统定时清理一些不需要的文件很有一种爽快的事情.不用你去每天惦记着是否 ...