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 ...
随机推荐
- C#学习笔记(十五):抽象方法、抽象类、多态和接口
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...
- [Err] 1111 - Invalid use of group function
本文为博主原创,未经允许不得转载: 初衷,本想通过group by sql语句查询出不同id下总数在一定范围内的数据,所以产生如下的sql,及错误sql AND STATDATE < ' GRO ...
- 【TCP/IP详解 卷一:协议】第一章概论 学习笔记
第一章 概述 游览了一下,本章主要是简介OSI模型的低层(1-4层).介绍了TCP/IP协议族的相关知识. TCP/IP的分层 Application <--> TCP / UDP < ...
- input file获取选择图片的本地路径和base64路径
input file获取选择图片的本地路径和base64路径 本地路径: myHeadFile: function (e) { // 这里是input file 的onchange事件 ] const ...
- UOJ #79. 一般图最大匹配
板子: #include<iostream> #include<cstdio> #include<algorithm> #include<vector> ...
- 遇到Io阻塞时会切换任务之【爬虫版】
#! /usr/bin/env python3 # -*- coding:utf- -*- from urllib import request import gevent,time from gev ...
- testNG 学习笔记 Day 3 常用的断言
TestNG中最常用的一个断言类是Assert.java,里面有多个静态方法,这个类我们习惯叫硬断言.对应的还有一个软断言的类,叫SoftAssert.java,这个类是需要创建实例对象,才能调用相关 ...
- R6
RC 的加强版是 R6 , R6 是一个扩展包,能够实现支持公共和私有字段与方法的更有效的引用类,还有一些其他强大的功能.运行以下代码安装这个包:install.packages("R6&q ...
- RabbitMQ入门_09_TTL
参考资料:https://www.rabbitmq.com/ttl.html A. 为队列设置消息TTL TTL 是 Time-To-Live 的缩写,指的是存活时间.RabbitMQ 可以为每一个队 ...
- android--------微信 Tinker 热修复 (二)
前面简单介绍了一下Tinker热修复,今天就来分享一下如何在Android中使用,希望对各位有帮助. 1:Tinker 接入指南 在项目的build.gradle中,添加tinker-patch-gr ...