百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

重复造轮子,开发了个快速录单场景的轻量级可编辑表格插件

toyiye 2024-06-21 12:06 10 浏览 0 评论

首先预览一下演示效果,是一个GIF的录屏动画(加载慢,稍等一会):

etable 适用于快速录单场景的可编辑表格插件 演示

上图演示了上方插入行、下方插入行、删除行、上下左右方向键操作,最后单元格TAB键新增行等功能。

工作中经常碰到一种需求场景,当我们在添加数据记录的时候,其附带的一些数据需要以关联数据(在数据库中表现为关联的数据表)形式一同添加,比如在采购单录单、添加人员基本信息时需要一同填写人员的履历、经验和获奖证书等情况,而这些关联数据本身又是一条一条的记录,所以亟需一种可编辑的子表格,能方便嵌入到现有表单中。

网络上这种类似的功能其实很多,但是不是太复杂就是操作太繁琐,也往往和录单本身需要的功能初心相悖,故老早就想自己做一个类似的插件,以便可以重复使用。借着这次新冠疫情管控,本人被要求居家办公,所以有时间空下来写了这个插件,基本功能都实现了,待后续在优化和完善下。

这个插件完全是用在web前端页面的,可方便嵌入到web应用中,考虑到时间问题(搞不好随时被召唤回去上班),所以主要用了jQuery实现,其实有点类似于easyui的datagrid,但是easyui的datagrid默认不支持键盘操作和新增删除列,需要自己扩展,索性就自己单独实现一个轻量的datagrid,应该说适合自己的才是最好的。

下面具体介绍一下该插件,如上图所示:

已实现的列类型

  1. 序号列(不可编辑,但是用插件去维护序号)
  2. 原始数据列(不可编辑,保持原有td元素的值,或者可选择设置空字符串值)
  3. 复选框checkbox列(编辑列,始终居中,可传入默认值,支持常用样式定义)
  4. 下拉选择select列(编辑列,可传入默认值和下拉数据源,支持常用样式定义)
  5. 普通文本text列(编辑列,可传入默认值,支持常用样式定义)
  6. 日期选择date列(编辑列,普通文本text列的变种,默认只选不写)

待实现的列类型

  1. 整数int列(计划支持正整数,适用于采购数量等使用场景)
  2. 数字number列(计划包含整数和小数,适用于金额的小数使用场景)

插件特点

  1. 支持列配置,通过传入对象数组配置列,有点类似于datagrid的传参方式
  2. 支持参数配置,通过调用config方法,传入json对象格式的参数
  3. 支持工具按钮,目前实现了上方插入行、下方插入行、删除行这三个功能
  4. 支持键盘按键操作,支持上下左右方向键、回车键、TAB键等操作
  5. 支持最后一个元素上按TAB键新增行功能(这点在快速录单中特别需要)
  6. 支持获取列数据,可用于表单提交
  7. 支持序号自维护(这点也是客户特别需要的)
  8. 支持某行某列不启用编辑功能
  9. 另外还支持是否启用按键、是否启用工具按钮等独立配置参数

插件使用条件

  1. 需要有jQuery支持
  2. 有些语法用了ES6的东东,待后续转一下ES5
  3. date类型列因为偷懒,用了laydate插件

插件不足之处

  1. 还有好多功能没实现,请有心的朋友在评论区提提意见,或者私信我
  2. 兼容性没做测试,开发时只在chrome89环境下,其他环境待后续优化
  3. 性能也没过多去考虑
  4. 代码有点乱,需要整理下
  5. 其他应该还有很多

插件使用方法

  1. 初始化
funsent.etable.init({
    table_target: '#etable',
    row_number: 3,
    enable_keyboard: true,
    enable_tab_insert: true,
    enable_button: true,
    columns: [
        {type:'checkbox', name:'id', value:'', readonly:false},
        {type:'text', name:'name', value:'', align:'left', readonly:false},
        {type:'text', name:'certno', value:'', align:'left', readonly:false},
        {type:'date', name:'issue_time', value:'', align:'center', readonly:true},
        {type:'text', name:'issue_body', value:'', align:'left', readonly:false},
        {type:'select', name:'remark', value:'', align:'left', readonly:false, values:{0:'ok', 1:'no'}, style:{padding:'4px 4px 5px'}},
    ]
});
  1. 收集表单数据(提交保存前的操作,用于表单请求前的数据收集)
funsent.etable.serializeArray()

返回的是json对象数组,如果提交到服务器,需要自行处理

最后代码完整奉上,记得使用前要引入jQuery:

/**
 * @author   yanggf <2018708@qq.com>
 * @version  $Id: etable.js 223 2021-12-14 11:25:50Z yanggf $
 */
// 可编辑表格插件
; (function ($, global) {
    let defaults = {
        table_target: null, //表格
        row_number: 0, // 空表格时为可编辑行数,非空表格时为多出的可编辑行数
        column_number: 0, // 空表格时为可编辑列数
        enable_keyboard: false, // 启用键盘操作,适用快速录单等场景
        enable_tab_insert: false, // 焦点在最后一个元素上时按TAB键插入新行,enable_keyboard为true时有效
        enable_button: false, // 启用操作按钮
        no_edit_rows: [], // 不启用编辑的行索引, 如果为数字,表示前几行都不启用编辑
        columns: [
            // 复选框类型,此时width、height、align等字段无效,且永远水平居中    
            // {type:'checkbox', name:'', value:'', width:'100%', height:'100%', align:'', readonly:false},
            // 文本类型,默认的类型
            // {type:'text', name:'', value:'', width:'100%', height:'100%', align:'', readonly:false},
            // select多出一个下拉数据源的字段values,且必须为数组形式给出
            // {type:'select', name:'', value:'', width:'100%', height:'100%', align:'', readonly:false, values:[]},
            // 日期类型,一种点击弹出日期选择框的文本类型
            // {type:'date', name:'', value:'', width:'100%', height:'100%', align:'', readonly:true},
            // 整数类型,positive字段确定是否只能为正数,negtive字段确定是否只能为负数,zero字段确定是否包含0。待实现
            // {type:'integer', positive:true, negtive:false, zero:true, name:'', value:'', width:'100%', height:'100%', align:'', readonly:false},
            // 数字类型,positive字段确定是否只能为正数,negtive字段确定是否只能为负数,zero字段确定是否允许包含0。待实现
            // {type:'number', positive:true, negtive:false, zero:true, name:'', value:'', width:'100%', height:'100%', align:'', readonly:false},
        ],
    };

    let configs = {};
    let oldDataRows = []; // 已存在的行
    let editableRows = []; // 可编辑的所有行

    let etable = {
        // 参数配置
        config: function (opts) {
            if (typeof opts === 'string') {
                return configs[opts];
            } else if (typeof opts === 'undefined') {
                return configs;
            }
            if (!this.isJsonObject(opts)) {
                configs = defaults;
                return configs;
            }
            configs = Object.assign({}, defaults, opts);
            return configs;
        },

        // 初始化
        init: function (opts) {
            this.config(opts);
            this.resetOldDataRows();
            this.resetEditableRows();
            this.render();
            this.setToolBtns();
            this.setKeyboard();
        },

        resetOldDataRows: function () {
            oldDataRows = [];
        },
        getOldDataRows: function () {
            return oldDataRows;
        },
        getOldDataRow: function (index) {
            return oldDataRows[index] || undefined;
        },
        setOldDataRow: function ($row) {
            oldDataRows.push($row);
        },

        resetEditableRows: function () {
            editableRows = [];
        },
        getEditableRows: function () {
            return editableRows;
        },
        getEditableRow: function (index) {
            return editableRows[index] || undefined;
        },
        setEditableRow: function ($row) {
            editableRows.push($row);
        },
        insertEditableRow: function (index, direct) {
            let $row = editableRows[index];
            if ($row) {
                let $target = $(this.config('table_target')),
                    $tbody = $target.find('tbody');
                let i = editableRows.length + 1;
                let $tds = $row.find('td'), columnCnt = $tds.length;
                let $tr = $('<tr></tr>');
                for (let j = 0; j < columnCnt; j++) {
                    let $td = $('<td></td>'), textValue = '', textAlign = $tds.eq(j).css('textAlign');
                    let $editor = this.editor('insert', i, j, textValue, textAlign);
                    $td.html($editor).css({ padding: 0, textAlign: textAlign });
                    $tr.append($td);
                }
                if (direct == 'after') {
                    $tbody.find('tr:eq(' + index + ')').after($tr);
                    editableRows.splice(index + 1, 0, $tr);
                } else if (direct == 'before') {
                    $tbody.find('tr:eq(' + index + ')').before($tr);
                    editableRows.splice(index, 0, $tr);
                }
            }
        },
        removeEditableRow: function (index) {
            let $row = editableRows[index];
            if ($row) {
                $row.remove();
                editableRows.splice(index, 1);
            }
        },

        // 渲染表格单元格为编辑器
        render: function () {
            let $target = $(this.config('table_target')),
                $thead = $target.find('thead'),
                $tbody = $target.find('tbody');

            let $rows = $tbody.find('tr'),
                rowCnt = $rows.size(),
                columnCnt = $thead.find('tr > th').size();

            let textAligns = [];

            // 已有行变成可编辑行
            let noEditRows = this.config('no_edit_rows');
            if (rowCnt > 0 && columnCnt > 0) {
                for (let i = 0; i < rowCnt; i++) {

                    let $tr = $rows.eq(i);
                    this.setOldDataRow($tr);

                    if (this.isArray(noEditRows)) {
                        // 行索引数组
                        if (this.inArray(i, noEditRows)) {
                            continue;
                        }
                    } else if (typeof noEditRows === 'number') {
                        // 前几行
                        if (i < Math.ceil(noEditRows)) {
                            continue;
                        }
                    }

                    let $tds = $tr.find('td');
                    for (let j = 0; j < columnCnt; j++) {
                        let $td = $tds.eq(j), textValue = $td.text(), textAlign = $td.css('textAlign');
                        let $editor = this.editor('modify', i, j, textValue, textAlign);
                        $td.html($editor).css({ padding: 0, textAlign: textAlign });

                        // 临时保存该列td原有的对齐方式
                        textAligns[j] = textAlign;
                    }

                    this.setEditableRow($tr);
                }
            }

            // 新编辑行
            if (rowCnt = this.config('row_number')) {
                if (columnCnt == 0) {
                    columnCnt = this.config('column_number');
                }
                for (let i = 0; i < rowCnt; i++) {
                    let $tr = $('<tr></tr>');
                    for (let j = 0; j < columnCnt; j++) {
                        let column = this.config('columns')[j] || {}, columnAlign = column['align'] || '';
                        let $td = $('<td></td>'), textValue = '', textAlign = textAligns[j] || columnAlign;
                        let $editor = this.editor('insert', i, j, textValue, textAlign);
                        $td.html($editor).css({ padding: 0, textAlign: textAlign });
                        $tr.append($td);
                    }
                    $tbody.append($tr);

                    // 保存行
                    this.setEditableRow($tr);
                }
            }
        },

        // 序列化表格数据,返回json对象数组的表单数据
        serializeArray: function () {
            let arr = [];
            let rows = this.getEditableRows();
            if (!rows.length) {
                return arr;
            }

            let editableEles = 'input,select,textarea';
            for (let key in rows) {
                let $columns = rows[key].find('td');
                let inputs = {};
                $columns.each(function () {
                    let $childrens = $(this).children(editableEles);
                    if ($childrens.length) {
                        let $children = $childrens.eq(0);
                        let key = $children.prop('name');
                        let value = $children.val();
                        inputs[key] = value;
                    }
                });
                arr.push(inputs);
            }

            return arr;
        },

        // 设置键盘操作
        setKeyboard: function () {
            if (!this.config('enable_keyboard')) {
                return;
            }

            let rows = this.getEditableRows(), rowCnt = rows.length;
            if (!rowCnt) {
                return;
            }

            // 所有编辑元素、所有编辑元素个数、每行可编辑元素的列数
            let editableEles = 'input,select,textarea';
            let inputs = [], inputCnt = 0;
            for (let key in rows) {
                let row = rows[key];
                let $columns = row.find('td');
                $columns.each(function () {
                    let $childrens = $(this).children(editableEles);
                    if ($childrens.length) {
                        inputs.push($childrens.eq(0));
                        inputCnt++;
                    }
                });
            }
            let editableColumnCnt = inputCnt / rowCnt;

            let that = this;
            for (let i = 0; i < inputCnt; i++) {
                let $input = inputs[i], index = i;
                $input.unbind('keydown').bind('keydown', function (e) {
                    let k = e.keyCode;

                    if (k == 32) {
                        // 空格键按下时,如果碰到日期选择框,则触发click事件,以便能够弹出日期选择框
                        if ($input.hasClass('funsent-etable-input-date')) {
                            $input.trigger('click');
                        }
                        return;
                    }

                    if (k == 9 || k == 39 || k == 13) {
                        // 焦点在最后一个元素上时按TAB键插入新行,enable_keyboard为true时有效
                        if (k == 9 && that.config('enable_tab_insert') && index == inputCnt - 1) {
                            let rowIndex = rowCnt - 1;
                            that.insertEditableRow(rowIndex, 'after');
                            that.setToolBtns();
                            that.resetOrder();
                            that.setKeyboard();
                            return;
                        }
                        // TAB键、右方向键和回车键
                        if (index < inputCnt - 1) {
                            let tmpIndex = index + 1, $input = inputs[tmpIndex];
                            $input.focus();
                            if ($input.prop('tagName').toLowerCase() != 'select') {
                                $input.select();
                            }
                        }
                        // 修复问题:1.防止TAB键时跳2次;2.防止右方向键改变select的值
                        (k == 9 || k == 39) && e.preventDefault();
                    } else if (k == 37) {
                        // 左方向键
                        if (index >= 1) {
                            let tmpIndex = index - 1, $input = inputs[tmpIndex];
                            $input.focus();
                            if ($input.prop('tagName').toLowerCase() != 'select') {
                                $input.select();
                            }
                        }
                        // 修复问题:1.防止左方向键改变select的值 
                        e.preventDefault();
                    } else if (k == 38) {
                        // 上方向键
                        // 计算上一行同一个位置的索引
                        let tmpIndex = index - editableColumnCnt;
                        if (tmpIndex >= 0) {
                            let $input = inputs[tmpIndex];
                            $input.focus();
                            if ($input.prop('tagName').toLowerCase() != 'select') {
                                $input.select();
                            }
                        }
                        // 修复问题:1.防止上方向键改变select的值
                        e.preventDefault();
                    } else if (k == 40) {
                        // 下方向键
                        // 计算下一行同一个位置的索引
                        let tmpIndex = index + editableColumnCnt;
                        if (tmpIndex <= inputCnt - 1) {
                            let $input = inputs[tmpIndex];
                            $input.focus();
                            if ($input.prop('tagName').toLowerCase() != 'select') {
                                $input.select();
                            }
                        }
                        // 修复问题:1.防止下方向键改变select的值
                        e.preventDefault();
                    }
                });
            }
        },

        // 设置工具按钮
        setToolBtns: function () {
            let rows = this.getEditableRows(), rowCnt = rows.length;
            if (!this.config('enable_button') || !rowCnt) {
                return;
            }

            let btnPseudoStyle = '<style>.funsent-etable-btn:active{positon:relative;left:1px;top:1px;}</style>',
                btnCss = {
                    fontSize: '12px',
                    width: '14px',
                    height: '14px',
                    display: 'inline-block',
                    textAlign: 'center',
                    backgroundColor: '#eff8fd',
                    color: '#06f',
                    padding: '0',
                    margin: '0 2px 0 0',
                    border: '1px solid #06f',
                    boxSizing: 'border-box',
                    borderRadius: '2px',
                    boxShadow: '0 0 2px 0 #999',
                    cursor: 'pointer'
                },
                groupCss = {
                    position: 'absolute',
                    left: '2px',
                    boxSizing: 'border-box',
                    display: 'block',
                    padding: '0',
                    margin: '0',
                    width: '48px',
                    height: '16px',
                    overflow: 'hidden',
                    backgroundColor: 'transparent',
                    opacity: 0.3
                };

            const over = function () {
                $(this).css({ backgroundColor: '#06f', color: '#eff8fd' });
            };
            const out = function () {
                $(this).css({ backgroundColor: '#eff8fd', color: '#06f' });
            };

            let $target = $(this.config('table_target')), $thead = $target.find('thead'), theadHeight = $thead.outerHeight();
            let $parent = $target.closest('div').css('position', 'relative');

            // 删除之前的所有工具按钮
            $parent.find('div.funsent-etable-btnGroup').remove();

            let that = this;
            for (let i = 0; i < rowCnt; i++) {

                let $btn1 = $('<a class="funsent-etable-btn" href="javascript:;" title="上方插入新行">▲</a>').css(btnCss).hover(over, out),
                    $btn2 = $('<a class="funsent-etable-btn" href="javascript:;" title="下方插入新行">▼</a>').css(btnCss).hover(over, out),
                    $btn3 = $('<a class="funsent-etable-btn" href="javascript:;" title="删除当前行">?</a>').css(btnCss).hover(over, out);

                let $row = rows[i], top = theadHeight + ($row.outerHeight() * i) + 2;
                let $group = $('<div class="funsent-etable-btnGroup"></div>').css(groupCss).append(btnPseudoStyle, $btn1, $btn2, $btn3);
                $group.css('top', top);

                // 上方插入新行
                $btn1.bind('click', function () {
                    that.insertEditableRow(i, 'before');
                    that.setToolBtns();
                    that.resetOrder();
                    that.setKeyboard();
                });
                // 下方插入新行
                $btn2.bind('click', function () {
                    that.insertEditableRow(i, 'after');
                    that.setToolBtns();
                    that.resetOrder();
                    that.setKeyboard();
                });
                // 删除当前行
                $btn3.bind('click', function () {
                    if (that.getEditableRows().length == 1) {
                        layer.msg('不能删除唯一行');
                        return;
                    }
                    $group.remove();
                    that.removeEditableRow(i);
                    that.setToolBtns();
                    that.resetOrder();
                    that.setKeyboard();
                });

                $group.appendTo($parent);
            }
        },

        // 重置行序号
        resetOrder: function () {
            let columns = this.config('columns')

            // 没有序号列
            if (!this.isArray(columns)) {
                return;
            }
            let length = columns.length;
            if (length == 0) {
                return;
            }

            // 计算哪几列是序号列
            let orderColumns = [];
            for (let i = 0; i < length; i++) {
                let column = columns[i];
                if (typeof column === 'number') {
                    orderColumns.push(i);
                }
            }

            // 序号值重新按连续数字显示
            let rows = this.getEditableRows();
            let rowCnt = rows.length, columnCnt = rows[0].find('td').length;
            for (let i = 0; i < rowCnt; i++) {
                for (let j = 0; j < columnCnt; j++) {
                    if (this.inArray(j, orderColumns)) {
                        let $td = rows[i].find('td:eq(' + j + ')');
                        $td.html(this.renderOrder(i + 1));
                    }
                }
            }
        },

        // 返回序号列内容
        renderOrder: function (order) {
            return '<div style="text-align:center;">' + order + '</div>';
        },

        // 是否为数组
        isArray: function (obj) {
            return (typeof obj === 'object' && JSON.stringify(obj).indexOf('[') == 0);
        },

        // 元素是否在数组中
        inArray: function (value, arr) {
            if (!this.isArray(arr)) {
                return false;
            }
            return arr.indexOf(value) !== -1;
        },

        // 是否为json对象
        isJsonObject: function (obj) {
            return (typeof obj === 'object' && JSON.stringify(obj).indexOf('{') == 0);
        },

        // 是否为空的json对象
        isEmptyJsonObject: function (obj) {
            if (!this.isJsonObject(obj)) {
                return false;
            }
            return JSON.stringify(obj) == '{}';
        },

        // 创建编辑器,参数分别为:模式(修改行还是插入行),行索引,列索引,列原始数据,列原始对其方式
        editor: function (mode, rowIndex, colIndex, textValue, textAlign) {
            let columns = this.config('columns'), column = columns[colIndex];

            // 布尔型表示不编辑,仅显示空字符串
            // 数字型表示不编辑,仅显示序号
            // 字符型表示不编辑,仅直接显示该字符串
            if (typeof column === 'boolean') {
                return '';
            } else if (typeof column === 'number') {
                let oldDataRowCnt = this.getOldDataRows().length, order = 1;
                if (mode == 'modify') {
                    order = oldDataRowCnt;
                } else if (mode == 'insert') {
                    order = oldDataRowCnt + rowIndex + 1;
                }
                return this.renderOrder(order);
            } else if (typeof column === 'string') {
                return column;
            }

            // 判断是否为json对象
            if (!this.isJsonObject(column)) {
                column = {};
            }

            let style = {
                width: '100%',
                height: '100%',
                textAlign: textAlign,
                boxSizing: 'border-box'
            };

            // 空的JSON对象
            if (JSON.stringify(column) == '{}') {
                let name = this.config('table_target') + '_row' + rowIndex + '_col' + colIndex,
                    value = textValue;
                return this.textEditor(name, value, column, style);
            }

            let type = column['type'] || 'text',
                name = column['name'] || '',
                value = textValue || (column['value'] || '');

            // 样式覆盖
            style = Object.assign({}, style, column['style'] || {});
            style['width'] = column['width'] || '100%';
            style['height'] = column['height'] || '100%';
            style['textAlign'] = textAlign || (column['align'] || '');

            let $editor;
            if (type == 'date') {
                $editor = this.dateEditor(name, value, column, style);
            } else if (type == 'select') {
                $editor = this.selectEditor(name, value, column, style);
            } else if (type == 'checkbox') {
                $editor = this.checkboxEditor(name, value, column, style);
            } else {
                $editor = this.textEditor(name, value, column, style);
            }
            return $editor;
        },

        // 文本框
        textEditor: function (name, value, column, style) {
            let readonly = column['readonly'] || false;
            let $editor = $('<input type="text" name="' + name + '" value="' + value + '" />').css(style).prop('readonly', readonly);
            return $editor;
        },

        // 下拉选择框
        selectEditor: function (name, value, column, style) {
            let readonly = column['readonly'] || false;
            let values = column['values'] || [];
            let options = '<option value=""></option>', optionValueCnt = 0;
            if (typeof values === 'object') {
                for (let v in values) {
                    let selected = (value == v ? ' selected="selected"' : '');
                    let text = values[v];
                    options += '<option value="' + v + '"' + selected + '>' + text + '</option>';
                    optionValueCnt++;
                }
            }
            let $editor = $('<select name="' + name + '">' + options + '</select>').css(style).prop('readonly', readonly);
            return $editor;
        },

        // 复选框
        checkboxEditor: function (name, value, column, style) {
            let readonly = column['readonly'] || false;
            let $checkbox = $('<input type="checkbox" name="' + name + '" value="' + value + '" />').prop('readonly', readonly);
            let $editor = $('<div class="checkbox"><label></label></div>').css('textAlign', 'center').prepend($checkbox);
            return $editor;
        },

        // 日期选择框
        dateEditor: function (name, value, column, style) {
            let readonly = column['readonly'] || true;
            let $editor = $('<input class="funsent-etable-input-date" type="text" name="' + name + '" value="' + value + '" />').css(style).prop('readonly', readonly);
            laydate.render({ elem: $editor.get(0) });
            return $editor;
        },

        //TODO 整数框
        integerEditor: function (name, value, column, style) { },

        //TODO 数字框(含小数)
        numberEditor: function (name, value, column, style) { }
    };

    // 插件对象暴露出去
    !('funsent' in global) && (global.funsent = {});
    !('etable' in global.funsent) && (global.funsent.etable = etable);
})(jQuery, window);

开发时的代码片段

后续本人还将继续使用和优化该插件,希望在将此轻量级的可编辑表格插件继续发展下去,如有意见建议,请评论区见或私信!

相关推荐

为何越来越多的编程语言使用JSON(为什么编程)

JSON是JavascriptObjectNotation的缩写,意思是Javascript对象表示法,是一种易于人类阅读和对编程友好的文本数据传递方法,是JavaScript语言规范定义的一个子...

何时在数据库中使用 JSON(数据库用json格式存储)

在本文中,您将了解何时应考虑将JSON数据类型添加到表中以及何时应避免使用它们。每天?分享?最新?软件?开发?,Devops,敏捷?,测试?以及?项目?管理?最新?,最热门?的?文章?,每天?花?...

MySQL 从零开始:05 数据类型(mysql数据类型有哪些,并举例)

前面的讲解中已经接触到了表的创建,表的创建是对字段的声明,比如:上述语句声明了字段的名称、类型、所占空间、默认值和是否可以为空等信息。其中的int、varchar、char和decimal都...

JSON对象花样进阶(json格式对象)

一、引言在现代Web开发中,JSON(JavaScriptObjectNotation)已经成为数据交换的标准格式。无论是从前端向后端发送数据,还是从后端接收数据,JSON都是不可或缺的一部分。...

深入理解 JSON 和 Form-data(json和formdata提交区别)

在讨论现代网络开发与API设计的语境下,理解客户端和服务器间如何有效且可靠地交换数据变得尤为关键。这里,特别值得关注的是两种主流数据格式:...

JSON 语法(json 语法 priority)

JSON语法是JavaScript语法的子集。JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔花括号保存对象方括号保存数组JS...

JSON语法详解(json的语法规则)

JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔大括号保存对象中括号保存数组注意:json的key是字符串,且必须是双引号,不能是单引号...

MySQL JSON数据类型操作(mysql的json)

概述mysql自5.7.8版本开始,就支持了json结构的数据存储和查询,这表明了mysql也在不断的学习和增加nosql数据库的有点。但mysql毕竟是关系型数据库,在处理json这种非结构化的数据...

JSON的数据模式(json数据格式示例)

像XML模式一样,JSON数据格式也有Schema,这是一个基于JSON格式的规范。JSON模式也以JSON格式编写。它用于验证JSON数据。JSON模式示例以下代码显示了基本的JSON模式。{"...

前端学习——JSON格式详解(后端json格式)

JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScriptProgrammingLa...

什么是 JSON:详解 JSON 及其优势(什么叫json)

现在程序员还有谁不知道JSON吗?无论对于前端还是后端,JSON都是一种常见的数据格式。那么JSON到底是什么呢?JSON的定义...

PostgreSQL JSON 类型:处理结构化数据

PostgreSQL提供JSON类型,以存储结构化数据。JSON是一种开放的数据格式,可用于存储各种类型的值。什么是JSON类型?JSON类型表示JSON(JavaScriptO...

JavaScript:JSON、三种包装类(javascript 包)

JOSN:我们希望可以将一个对象在不同的语言中进行传递,以达到通信的目的,最佳方式就是将一个对象转换为字符串的形式JSON(JavaScriptObjectNotation)-JS的对象表示法...

Python数据分析 只要1分钟 教你玩转JSON 全程干货

Json简介:Json,全名JavaScriptObjectNotation,JSON(JavaScriptObjectNotation(记号、标记))是一种轻量级的数据交换格式。它基于J...

比较一下JSON与XML两种数据格式?(json和xml哪个好)

JSON(JavaScriptObjectNotation)和XML(eXtensibleMarkupLanguage)是在日常开发中比较常用的两种数据格式,它们主要的作用就是用来进行数据的传...

取消回复欢迎 发表评论:

请填写验证码