SOURCE

console 命令行工具 X clear

                    
>
console
(($) => {
    if ($.valHooks.div) {
        return;
    }
    const eleHooks = "div,span,ul,ol,li,table,tr,td,th,tbody,thead,tfoot,a,b,caption,p,pre,label,form,font,i".toLowerCase().split(",").map($.trim);

    function Enumerator(array) {
        if (array == null) {
            return;
        }
        let index = 0;
        this.next = function () {
            if (index < array.length) {
                return array[index++];
            }
        };
        this.reset = function () {
            index = 0;
        };
        this.all = function () {
            return array;
        };
        this.get = function (index) {
            return array[index];
        };
    }

    function Copied(value) { Object.assign(this, value); }

    function assign(values) {
        const result = {};
        for (let value of values) {
            for (let key of Object.keys(value)) {
                if (key in result) {
                    if (!$.isArray(result[key])) {
                        result[key] = [result[key]];
                    }
                    result[key] = result[key].concat(value[key]);
                } else {
                    result[key] = value[key];
                }
            }
        }
        return result;
    }

    const handlers = [
        {
            is(jq) { return jq.is(":checkbox,:radio") },
            getValue(jq) { return jq.is(":checked") ? jq.val() : null; },
            setValue(jq, value) { jq.val([].concat(value)); }
        },
        {
            is(jq) { return jq.is("select[multiple]") },
            getValue(jq) { return [].concat(jq.val()) },
            setValue(jq, value) { jq.val([].concat(value)); }
        },
        {
            is(jq) { return jq.is("[multiple]") },
            getValue(jq) { return jq.val() },
            setValue(jq, value) { jq.val(value); }
        },
        {
            is(jq) { return eleHooks.includes(jq[0].nodeName.toLowerCase()) },
            getValue(jq) { return jq.val(); },
            setValue(jq, value) { jq.val(value); }
        },
        {
            is(jq) { return jq.is(":input,img") || jq.children().length > 0 },
            getValue(jq) { return jq.val(); },
            setValue(jq, value) { jq.val(value); }
        },
        {
            is(jq) { return jq.is("[value]"); },
            getValue(jq) { return jq.attr("value"); },
            setValue(jq, value) { jq.attr("value", value); }
        },
        {
            is(jq) { return true },
            getValue(jq) { return jq.text(); },
            setValue(jq, value) { (jq.is("[name]")) && jq.text(value); }
        },
    ];

    function getValue(jq) {
        for (let handler of handlers) {
            if (handler.is(jq)) {
                return handler.getValue(jq);
            }
        }
    }

    function setValue(jq, value) {
        if (value == null) {
            return;
        }
        const oldValue = getValue(jq);
        for (let handler of handlers) {
            if (handler.is(jq) && !equals(oldValue, value)) {
                handler.setValue(jq, value);
                if (!equals(oldValue, getValue(jq))) {
                    jq.triggerHandler("change");
                }
                return;
            }
        }
    }

    function equals(value1, value2) {
        if (value1 == null || value2 == null) {
            return value1 == value2;
        }
        if ($.isArray(value1) && $.isArray(value2)) {
            if (value1.length !== value2.length) {
                return false;
            }
            value1 = value1.sort();
            value2 = value2.sort();
            for (let i = 0; i < value1.length; i++) {
                if (!equals(value1[i], value2[i])) {
                    return false;
                }
            }
            return true;
        }
        return value1 == value2;
    }

    function getName(jq) {
        const name = $.trim(jq.attr("name"));
        if (!name && jq.is(":input")) {
            return $.trim(jq.attr("id"));
        }
        return name;
    }

    function isPlainObject(obj) {
        try {
            return $.isPlainObject(obj);
        } catch (e) {
            return true;
        }
    }

    const valHook = {
        get(ele) {
            const jq = $(ele);
            const children = jq.children(":not(template)");
            if (children.length === 0) {
                if (jq.is("[name]")) {
                    let value = jq.prop("value");
                    if (value != null) {
                        return value;
                    }
                    value = jq.attr("value");
                    if (value != null) {
                        return value;
                    }
                    return jq.text();
                }
            }
            const values = children.map(function () {
                const jq = $(this);
                if (jq.is(":checkbox,:radio,option") && !jq.is(":checked")) {
                    return null;
                }
                const name = getName(jq);
                if (name) {
                    return { [name]: getValue(jq) };
                }
                const val = jq.val();
                if ($.isPlainObject(val)) {
                    return val;
                }
                return null;
            }).toArray().filter(x => x != null);
            return assign(values);
        },
        set(ele, value) {
            const jq = $(ele);
            const children = jq.children();
            if (children.length === 0) {
                handlers[handlers.length - 1].setValue(jq, value);
                return ele;
            }
            const copied = value instanceof Copied || !isPlainObject(value) || Object.keys(value).length === 0 ? value : new Copied(value);

            return children.each(function () {
                const jq = $(this);
                const name = getName(jq);
                if (!name && eleHooks.includes(this.nodeName.toLowerCase())) {
                    setValue(jq, copied);
                    return this;
                }

                if (copied.hasOwnProperty(name)) {
                    let val = copied[name];
                    if ($.isArray(val)) {
                        val = copied[name] = new Enumerator(val);
                    }
                    if (!(val instanceof Enumerator)) {
                        setValue(jq, val);
                    } else if (jq.is("select[multiple],:checkbox,:radio")) {
                        setValue(jq, val.all());
                    } else {
                        if (jq.is("[reset]")) {
                            val.reset();
                        }
                        setValue(jq, val.next());
                    }
                }
                return this;
            });
        }
    };

    $.extend($.valHooks, assign(eleHooks.map(x => ({ [x]: valHook }))));
    $.extend($.valHooks, {
        img: {
            get(ele) {
                return ele.src;
            },
            set(ele, value) {
                ele.src = value;
            }
        }
    })
})(jQuery);
<!DOCTYPE html>
<html>

<head>
	<meta charset="utf-8" />
	<title></title>
</head>

<body>
    <div class="container">
        <input type="hidden" name="ID" value="" />
        <div>
            <label>姓名</label><input name="Name" />
        </div>
        <div>
            <label>性别</label>
            <label><input type="radio" name="Sex" value="男" /></label>
            <label><input type="radio" name="Sex" value="女" /></label>
        </div>
        <div>
            <label>爱好</label>
            <select multiple name="Like">
                <option value="唱歌">唱歌</option>
                <option value="跳舞">跳舞</option>
                <option value="写代码">写代码</option>
            </select>
        </div>
        <div>
            <label>标签</label>
            <label>80后<input type="checkbox" name="Tags" value="80后" /></label>
            <label>码农<input type="checkbox" name="Tags" value="码农" /></label>
            <label>富二代<input type="checkbox" name="Tags" value="富二代" /></label>
        </div>
        <label>账户</label>
        <ol>
            <li name="Account">
                <div>
                    <label>卡号</label><input name="CardNo" />
                </div>
                <div>
                    <label>余额</label><input name="Balance" />
                </div>
                <div>
                    <label>关联</label><input multiple name="Links" />
                </div>
            </li>
            <li name="Account">
                <div>
                    <label>卡号</label><input name="CardNo" />
                </div>
                <div>
                    <label>余额</label><input name="Balance" />
                </div>
                <div>
                    <label>积分</label><input name="Score" />
                </div>
            </li>
        </ol>
        <div>
            <label>电话1</label><input name="Phone" value="" />
        </div>
        <div>
            <label>电话2</label><input name="Phone" value="" />
        </div>
        <div>
            <label>电话3</label><input name="Phone" value="" />
        </div>
        <HR />
        <button type="button" onclick="setModel()">赋值 $(".container").val({...});</button>
        <button type="button" onclick="getModel()">取值 $(".container").val();</button>
        <HR />
    </div>
    <pre>
    </pre>
    <script>
        function setModel() {
            $(".container").val({
                ID: "1",
                Name: "zijian666",
                Like: ["唱歌", "写代码"],
                Sex: "男",
                Tags: ["80后", "码农"],
                Account: [
                    { CardNo: "0001", Balance: 100, Links: ["x"] },
                    { CardNo: "0002", Balance: 123456789, Score: 1 },
                    { CardNo: "---" },
                ],
                Phone: ["131", "132"]
            });
        }

        function getModel() {
            var model = $(".container").val();
            $("pre").text(JSON.stringify(model, null, "  "))
        }
    </script>
</body>
</html>

本项目引用的自定义外部资源