概述

最近,有客户向我们请求开发一个前端下拉控件,需求是显示了一个列表,其中包含可由用户单独选择的项目控件,该控件将在下拉列表中显示多选TreeView(树形图)。

如今WijmoJS已经实现了该控件——DropDownTree,本文将主要介绍如何创建自定义DropDownTree控件以及其源代码。

DropDownTree 控件源代码

HTML

<div class="container">
<h1>
DropDownTree Control
</h1>
<p>
The <b>DropDownTree</b> control is similar to a
<b>MultiSelect</b>, but it hosts a <b>TreeView</b>
in the drop-down instead of a <b>ListBox</b>.</p>
<p>
The <b>DropDownTree</b>'s object model is also
similar to the <b>MultiSelect</b>'s: you can listen
to the <b>checkedItemsChanged</b> event and get/set
the selection using the <b>checkedItems</b> property:</p> <h3>
Drop-Down-Tree
</h3>
<input id="ddTree" placeholder="multi tree"> <h3>
Multi-Select
</h3>
<input id="multiSelect" placeholder="multi select">
</div>

JavaScript

onload = function() {
// create the DropDownTree
var ddTree = new wijmo.input.DropDownTree('#ddTree', {
displayMemberPath: 'header',
childItemsPath: 'items',
showCheckboxes: true,
itemsSource: getTreeData(),
checkedItemsChanged: function (s, e) {
console.log('dropDownTree.checkedItemsChanged:');
s.checkedItems.forEach(function (item, index) {
console.log(index, item[s.displayMemberPath])
})
}
}); // create the MultiSelect
var multiSelect = new wijmo.input.MultiSelect('#multiSelect', {
itemsSource: 'Austria,Belgium,Chile,Denmark'.split(','),
checkedItemsChanged: function (s, e) {
console.log('multiSelect.checkedItemsChanged:');
s.checkedItems.forEach(function (item, index) {
console.log(index, item)
})
}
}); // get the tree data
function getTreeData() {
return [
{ header: 'Electronics', img: 'resources/electronics.png', items: [
{ header: 'Trimmers/Shavers' },
{ header: 'Tablets' },
{ header: 'Phones', img: 'resources/phones.png', items: [
{ header: 'Apple' },
{ header: 'Motorola', newItem: true },
{ header: 'Nokia' },
{ header: 'Samsung' }
]},
{ header: 'Speakers', newItem: true },
{ header: 'Monitors' }
]},
{ header: 'Toys', img: 'resources/toys.png', items: [
{ header: 'Shopkins' },
{ header: 'Train Sets' },
{ header: 'Science Kit', newItem: true },
{ header: 'Play-Doh' },
{ header: 'Crayola' }
]},
{ header: 'Home', img: 'resources/home.png', items: [
{ header: 'Coffeee Maker' },
{ header: 'Breadmaker', newItem: true },
{ header: 'Solar Panel', newItem: true },
{ header: 'Work Table' },
{ header: 'Propane Grill' }
]}
];
}
} // DropDownTree: transpiled TypeScript
var __extends = (this && this.__extends) || (function () {
var extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var wijmo;
(function (wijmo) {
var input;
(function (input) {
var DropDownTree = /** @class */ (function (_super) {
__extends(DropDownTree, _super);
/**
* Initializes a new instance of the @see:DropDownTree class.
*
* @param element The DOM element that hosts the control, or a CSS selector for the host element (e.g. '#theCtrl').
* @param options The JavaScript object containing initialization data for the control.
*/
function DropDownTree(element, options) {
var _this = _super.call(this, element) || this;
_this._maxHdrItems = 2;
_this._hdrFmt = wijmo.culture.MultiSelect.itemsSelected;
/**
* Occurs when the value of the @see:checkedItems property changes.
*/
_this.checkedItemsChanged = new wijmo.Event();
wijmo.addClass(_this.hostElement, 'wj-dropdowntree');
// make header element read-only
_this._tbx.readOnly = true;
// toggle drop-down when clicking on the header element
// (and not on a containing label element)
_this.addEventListener(_this.inputElement, 'click', function (e) {
if (document.elementFromPoint(e.clientX, e.clientY) == _this.inputElement) {
_this.isDroppedDown = !_this.isDroppedDown;
}
});
// update header now, when the itemsSource changes, and when items are selected
_this._updateHeader();
var tree = _this._tree;
tree.checkedItemsChanged.addHandler(function () {
_this._updateHeader();
_this.onCheckedItemsChanged();
});
tree.selectedItemChanged.addHandler(function () {
if (!tree.showCheckboxes) {
_this._updateHeader();
_this.onCheckedItemsChanged();
}
});
tree.loadedItems.addHandler(function () {
_this._updateHeader();
});
// close tree on enter/escape
tree.addEventListener(tree.hostElement, 'keydown', function (e) {
switch (e.keyCode) {
case wijmo.Key.Enter:
case wijmo.Key.Escape:
_this.isDroppedDown = false;
break;
}
});
// initialize control options
_this.initialize(options);
return _this;
}
Object.defineProperty(DropDownTree.prototype, "treeView", {
/**
* Gets the @see:TreeView control shown in the drop-down.
*/
get: function () {
return this._tree;
},
enumerable: true,
configurable: true
});
Object.defineProperty(DropDownTree.prototype, "itemsSource", {
/**
* Gets or sets the array that contains the @see:TreeView items.
*
* @see:TreeView #see:itemsSource arrays usually have a hierarchical
* structure with items that contain child items. There is no fixed
* limit to the depth of the items.
*
* For details, see the @see:TreeView.itemsSource property.
*/
get: function () {
return this._tree.itemsSource;
},
set: function (value) {
this._tree.itemsSource = value;
},
enumerable: true,
configurable: true
});
Object.defineProperty(DropDownTree.prototype, "displayMemberPath", {
/**
* Gets or sets the name of the property (or properties) to use as
* the visual representation of the nodes.
*
* The default value for this property is the string 'header'.
*
* For details, see the @see:TreeView.displayMemberPath property.
*/
get: function () {
return this._tree.displayMemberPath;
},
set: function (value) {
this._tree.displayMemberPath = value;
},
enumerable: true,
configurable: true
});
Object.defineProperty(DropDownTree.prototype, "childItemsPath", {
/**
* Gets or sets the name of the property (or properties) that contains
* the child items for each node.
*
* The default value for this property is the string 'items'.
*
* For details, see the @see:TreeView.childItemsPath property.
*/
get: function () {
return this._tree.childItemsPath;
},
set: function (value) {
this._tree.childItemsPath = value;
},
enumerable: true,
configurable: true
});
Object.defineProperty(DropDownTree.prototype, "showCheckboxes", {
/**
* Gets or sets a value that determines whether the @see:TreeView should
* add checkboxes to nodes and manage their state.
*
* For details, see the @see:TreeView.showCheckboxes property.
*/
get: function () {
return this._tree.showCheckboxes;
},
set: function (value) {
this._tree.showCheckboxes = value;
},
enumerable: true,
configurable: true
});
Object.defineProperty(DropDownTree.prototype, "checkedItems", {
/**
* Gets or sets an array containing the items that are currently checked.
*/
get: function () {
var tree = this._tree;
if (tree.showCheckboxes) {
return tree.checkedItems;
}
else {
return tree.selectedItem ? [tree.selectedItem] : [];
}
},
set: function (value) {
var tree = this._tree;
if (tree.showCheckboxes) {
tree.checkedItems = wijmo.asArray(value);
}
else {
tree.selectedItem = wijmo.isArray(value) ? value[0] : value;
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(DropDownTree.prototype, "maxHeaderItems", {
/**
* Gets or sets the maximum number of items to display on the control header.
*
* If no items are selected, the header displays the text specified by the
* @see:placeholder property.
*
* If the number of selected items is smaller than or equal to the value of the
* @see:maxHeaderItems property, the selected items are shown in the header.
*
* If the number of selected items is greater than @see:maxHeaderItems, the
* header displays the selected item count instead.
*/
get: function () {
return this._maxHdrItems;
},
set: function (value) {
if (this._maxHdrItems != value) {
this._maxHdrItems = wijmo.asNumber(value);
this._updateHeader();
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(DropDownTree.prototype, "headerFormat", {
/**
* Gets or sets the format string used to create the header content
* when the control has more than @see:maxHeaderItems items checked.
*
* The format string may contain the '{count}' replacement string
* which gets replaced with the number of items currently checked.
* The default value for this property in the English culture is
* '{count:n0} items selected'.
*/
get: function () {
return this._hdrFmt;
},
set: function (value) {
if (value != this._hdrFmt) {
this._hdrFmt = wijmo.asString(value);
this._updateHeader();
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(DropDownTree.prototype, "headerFormatter", {
/**
* Gets or sets a function that gets the HTML in the control header.
*
* By default, the control header content is determined based on the
* @see:placeholder, @see:maxHeaderItems, and on the current selection.
*
* You may customize the header content by specifying a function that
* returns a custom string based on whatever criteria your application
* requires.
*/
get: function () {
return this._hdrFormatter;
},
set: function (value) {
if (value != this._hdrFormatter) {
this._hdrFormatter = wijmo.asFunction(value);
this._updateHeader();
}
},
enumerable: true,
configurable: true
});
/**
* Raises the @see:checkedItemsChanged event.
*/
DropDownTree.prototype.onCheckedItemsChanged = function (e) {
this.checkedItemsChanged.raise(this, e);
};
//** overrides
// switch focus to the tree when the drop-down opens
DropDownTree.prototype.onIsDroppedDownChanged = function (e) {
if (this.containsFocus() && this.isDroppedDown) {
this._tree.focus();
}
_super.prototype.onIsDroppedDownChanged.call(this, e);
};
// create the drop-down element
DropDownTree.prototype._createDropDown = function () {
// create child TreeView control
var lbHost = wijmo.createElement('<div style="width:100%;border:none"></div>', this._dropDown);
this._tree = new wijmo.nav.TreeView(lbHost, {
showCheckboxes: true,
});
// let base class do its thing
_super.prototype._createDropDown.call(this);
};
Object.defineProperty(DropDownTree.prototype, "isReadOnly", {
// override since our input is always read-only
get: function () {
return this._readOnly;
},
set: function (value) {
this._readOnly = wijmo.asBoolean(value);
wijmo.toggleClass(this.hostElement, 'wj-state-readonly', this.isReadOnly);
},
enumerable: true,
configurable: true
});
// update header when refreshing
DropDownTree.prototype.refresh = function (fullUpdate) {
if (fullUpdate === void 0) { fullUpdate = true; }
_super.prototype.refresh.call(this, fullUpdate);
this._updateHeader();
};
//** implementation
// update the value of the control header
DropDownTree.prototype._updateHeader = function () {
// get selected items
var items = this.checkedItems;
// update the header
if (wijmo.isFunction(this._hdrFormatter)) {
this.inputElement.value = this._hdrFormatter();
}
else {
var hdr = '';
if (items.length > 0) {
if (items.length <= this._maxHdrItems) {
if (this.displayMemberPath) {
var binding_1 = new wijmo.Binding(this.displayMemberPath);
items = items.map(function (item) {
return binding_1.getValue(item);
});
}
hdr = items.join(', ');
}
else {
hdr = wijmo.format(this.headerFormat, {
count: items.length
});
}
}
this.inputElement.value = hdr;
}
// update wj-state attributes
this._updateState();
};
return DropDownTree;
}(input.DropDown));
input.DropDownTree = DropDownTree;
})(input = wijmo.input || (wijmo.input = {}));
})(wijmo || (wijmo = {}));
//# sourceMappingURL=DropDownTree.js.map

CSS

body {

margin-bottom: 24pt;

}

控件准备就绪后,它将如下所示:

本控件使用两个独立的WijmoJS模块:输入和导航。所需的步骤与开发MultiSelect控件时所采用的步骤相同:

选择基类

在这种场景下,我们可以将DropDown控件进行扩展,该控件包含使用下拉按钮实现输入元素所需的所有逻辑以及可用于托管任何控件的通用下拉列表。 DropDown控件用作ComboBox,InputColor和InputDate控件的基类。

定义对象模型

因为DropDownTree控件在其下拉列表中托管TreeView,所以我们决定直接从DropDownTree公开TreeView控件的主要属性:

  • TreeView获取对下拉列表中显示的TreeView控件的引用。
  • ItemsSource获取或设置对用于填充TreeView的对象数组的引用。
  • DisplayMemberPath获取或设置用作项目可视化表示的属性名称(默认为“header”)。
  • ChildItemsPath获取或设置包含数据源中每个项的子项的属性的名称(默认为“items”)。
  • ShowCheckboxes获取或设置一个值,该值确定控件是否应为每个项添加复选框,以便用户可以选择多个项(默认为true)。

我们还添加了一些额外的属性和事件来定义当前选择以及它在控制头中的表示方式。这些属性镜像MultiSelect控件中的相应属性:

  • CheckedItems获取或设置包含当前所选项目的数组。
  • CheckedItemsChanged是CheckedItems属性值更改时发生的事件。
  • MaxHeaderItems是控件头中显示的最大选定项数。
  • 当控件具有超过*maxHeaderItems项目选项时,headerFormat获取或设置用于创建标题内容的格式字符串。
  • HeaderFormatter获取或设置一个函数,该函数获取控件头中显示的文本。 这将覆盖maxHeaderItems和headerFormat属性的设置。

实现控件

我们首先将控件声明为基类的扩展:

namespace wijmo.input {
export class DropDownTree extends DropDown {
}
}

“extendsDropDown”语句确保我们的控件继承基本DropDown类的所有功能,包括属性,事件,方法和所有内部/私有成员。

创建树视图

接下来,我们覆盖DropDown类中的_createDropDown方法,以创建将在下拉列表中显示的TreeView控件。

除了创建TreeView之外,我们还会覆盖onIsDroppedDownChanged方法,以便在下拉列表打开且控件具有焦点时将焦点转移到树。 这允许用户使用键盘导航树。 他们可以通过键入内容来搜索项目,通过按空格键来检查项目,或使用光标键导航树。

namespace wijmo.input {
export class DropDownTree extends DropDown {
private _tree: wijmo.nav.TreeView; // create the drop-down element
protected _createDropDown() { // create child TreeView control
let lbHost = document.createElement('div');
setCss(lbHost, {
width: '100%',
border: 'none'
});
this._tree = new wijmo.nav.TreeView(lbHost, {
showCheckboxes: true
});
} // switch focus to the tree when the drop-down opens
onIsDroppedDownChanged(e?: EventArgs) {
if (this.containsFocus() && this.isDroppedDown) {
this._tree.focus();
}
super.onIsDroppedDownChanged(e);
}
}
}

公开TreeView及其属性

下一步是添加公开TreeView及其主要属性:

namespace wijmo.input {
export class DropDownTree extends DropDown {
private _tree: wijmo.nav.TreeView; get treeView(): wijmo.nav.TreeView {
return this._tree;
}
get itemsSource(): any[] {
return this._tree.itemsSource;
}
set itemsSource(value: any[]) {
this._tree.itemsSource = value;
}
// same for displayMemberPath, childItemsPath,
// and showCheckboxes // create the drop-down element
protected _createDropDown() {…}
}
}

这些属性只是获取或设置包含的TreeView上的相应属性的快捷方式。 因此,它们非常简单,我们甚至不启用类型检查,因为TreeView将为我们处理。

CheckedItems属性

控件的主要属性是CheckedItems,它用来表示用户当前已获取和自定义的数组。 我们可以用它实现上面那样的传递属性,也可以实现多选和单选功能。比如想实现其单选功能时,我们需要检查ShowCheckboxes属性的值并使用树的checkedItems或selectedItem属性。

除了CheckedItems属性,我们还实现了checkedItemsChanged事件及其伴随方法onCheckedItemsChanged。 这是WijmoJS事件的标准模式。 每个事件X都有一个相应的onX方法,负责触发事件。

namespace wijmo.input {
export class DropDownTree extends DropDown {
private _tree: wijmo.nav.TreeView; // TreeView pass-through properties… get checkedItems(): any[] {
let tree = this._tree;
if (tree.showCheckboxes) {
return tree.checkedItems;
} else {
return tree.selectedItem
? [tree.selectedItem] : [];
}
}
set checkedItems(value: any[]) {
let tree = this._tree;
if (tree.showCheckboxes) {
tree.checkedItems = asArray(value);
} else {
tree.selectedItem = isArray(value)
? value[0] : value;
}
} readonly checkedItemsChanged = new Event();
onCheckedItemsChanged(e?: EventArgs) {
this.checkedItemsChanged.raise(this, e);
} // create the drop-down element
protected _createDropDown() {…}
}

请注意,即使在单个选择的情况下,checkedItems属性也会返回一个数组(该数组为空或包含单个元素)。

更新控件头

这里不会重点讨论maxHeaderItems,headerFormat或headerFormatter属性的实现方式,因为它们很简单。我们需要将目光聚焦在_updateHeader函数的逻辑中,该函数使用这些属性,并在其值或选择更改时自动调用以更新控件头:

namespace wijmo.input {
export class DropDownTree extends DropDown {
private _tree: wijmo.nav.TreeView; // TreeView pass-through properties…
// checketItems property… private _updateHeader() {
let items = this.checkedItems;
if (isFunction(this._hdrFormatter)) {
this.inputElement.value = this._hdrFormatter();
} else {
let hdr = '';
if (items.length > 0) {
if (items.length <= this._maxHdrItems) {
if (this.displayMemberPath) {
let dmp = this.displayMemberPath,
binding = new Binding(dmp);
items = items.map((item) => {
return binding.getValue(item);
});
}
hdr = items.join(', ');
} else {
hdr = format(this.headerFormat, {
count: items.length
});
}
}
this.inputElement.value = hdr;
}
} // create the drop-down element
protected _createDropDown() {…}
}
}

构造函数

到此为止,我们几乎已经完成了控件架构。最后一步是实现构造函数,该构造函数将部件与事件侦听器连接,并调用initialize方法以使用options参数中的用户提供的值初始化属性和事件处理程序:

namespace wijmo.input {
export class DropDownTree extends DropDown {
private _tree: wijmo.nav.TreeView;
private _readOnly: boolean;
private _maxHdrItems = 2;
private _hdrFmt = wijmo.culture.MultiSelect.itemsSelected;
private _hdrFormatter: Function; constructor(element: HTMLElement, options?: any) {
super(element);
addClass(this.hostElement, 'wj-dropdowntree'); // make header element read-only
this._tbx.readOnly = true; // update header now, when the itemsSource changes,
// and when items are selected
this._updateHeader();
let tree = this._tree;
tree.checkedItemsChanged.addHandler(() => {
this._updateHeader();
this.onCheckedItemsChanged();
});
tree.selectedItemChanged.addHandler(() => {
if (!tree.showCheckboxes) {
this._updateHeader();
this.onCheckedItemsChanged();
}
});
tree.loadedItems.addHandler(() => {
this._updateHeader();
}); // initialize control options
this.initialize(options);
} // TreeView pass-through properties…
// checketItems property…
// _updateHeader implementation…
// _createDropDown implementation…
}
}

测试控件

现在控件已准备好,我们可以测试它,并检查它是否按照我们想要的方式运行。

运行DropDownTree 控件源代码,单击下拉按钮以打开TreeView。 打开后,单击几个项目以选择它们,并注意控件头的更新方式:

我们由衷希望DropDownTree控件对您产生帮助。更重要的是,我们希望您现在可以放心地将DropDown控件扩展为托管其他类型的元素,同时创建自己的自定义控件。


WijmoJS:灵活高效的前端开发工具包,可快速搭建企业 Web 应用程序

本文转载于:使用前端开发工具包WijmoJS - 创建自定义DropDownTree控件(包含源代码)

使用前端开发工具包WijmoJS - 创建自定义DropDownTree控件(包含源代码)的更多相关文章

  1. 前端开发工具包 WijmoJS 2019V1正式发布:全新的在线 Demo 系统,助您快速上手,开发无忧

    ​ 前端开发工具包WijmoJS在2019年的第一个主要版本2019V1已经发布,本次发布包括了更加易用的在线Demo系统.各控件新增功能.NPM 包的改动,以及全新的浏览器API组件. WijmoJ ...

  2. iOS开发UI篇—Quartz2D(自定义UIImageView控件)

    iOS开发UI篇—Quartz2D(自定义UIImageView控件) 一.实现思路 Quartz2D最大的用途在于自定义View(自定义UI控件),当系统的View不能满足我们使用需求的时候,自定义 ...

  3. iOS开发之通过代码自定义一个控件

    关于控件的继承关系(面试重点): (1)所有的控件都继承自UIView. (2)能监听事件的都是先继承自UIControl,UIControl再继承自UIView.比如UIButton. (3)能整体 ...

  4. Android开发(二)——自定义圆形控件的使用CircleImageView

    CircleImageView,a fast circular ImageView perfect for profile images. 主要的类CircleImageView: package d ...

  5. Android自定义组合控件详细示例 (附完整源码)

    在我们平时的Android开发中,有时候原生的控件无法满足我们的需求,或者经常用到几个控件组合在一起来使用.这个时候,我们就可以根据自己的需求创建自定义的控件了,一般通过继承View或其子类来实现. ...

  6. 【使用指南】WijmoJS 前端开发工具包

    为方便广大前端开发人员更好的使用 WijmoJS 前端开发工具包,葡萄城专门推出了 WijmoJS 使用指南,该指南详细地介绍了如何把 WijmoJS 各种强大的功能应用到您自己的 Web 项目中,助 ...

  7. python 全栈开发,Day90(Vue组件,前端开发工具包)

    昨日内容回顾 1. Vue使用 1. 生成Vue实例和DOM中元素绑定 2. app.$el --> 取出该vue实例绑定的DOM标签 3. app.$data --> 取出该vue实例绑 ...

  8. 【Android开发日记】之入门篇(十四)——Button控件+自定义Button控件

        好久不见,又是一个新的学期开始了,为什么我感觉好惆怅啊!这一周也发生了不少事情,节假日放了三天的假(好久没有这么悠闲过了),实习公司那边被组长半强制性的要求去解决一个后台登陆的问题,结果就是把 ...

  9. Android开发之自定义组合控件

    自定义组合控件的步骤1.自定义一个View,继承ViewGroup,比如RelativeLayout2.编写组合控件的布局文件,在自定义的view中加载(使用View.inflate())3.自定义属 ...

随机推荐

  1. C# HttpClient类库

    示例代码: 1 using System.Net.Http; 2 using System.Net.Http.Headers; 3 using System.Threading.Tasks; 4 5 ...

  2. matlab图形中添加文本框

    图形中添加文本框,自己目前了解到了两种方法:1.用legend函数就可以对图形标注,形成一个文本框: 2.就是用annotation('textbox',[0.2,0.2.0.1,0.3],'Line ...

  3. 程序语言与编程实践2-> 蓝桥杯C/C++备赛记录1 | 入门了解与首周训练

    寒假前班主任帮我们报了名,是得好好准备准备.作为一个CSer,coding能力一定不能太弱.我反思,好久没写C/C++代码了,净是些随手写的python脚本,刚开始上手题目bug一大堆. 由于也不是啥 ...

  4. 【工程应用五】 opencv中linemod模板匹配算法诸多疑惑和自我解读。

    研究这个前前后后也有快两三个月了,因为之前也一直在弄模板匹配方面的东西,所以偶尔还是有不少朋友咨询或者问你有没有研究过linemod这个算法啊,那个效率啥的还不错啊,有段时间一直不以为然,觉得我现在用 ...

  5. 谈谈 Kubernetes Operator

    简介 你可能听过Kubernetes中Operator的概念,Operator可以帮助我们扩展Kubernetes功能,包括管理任何有状态应用程序.我们看到了它被用于有状态基础设施应用程序的许多可能性 ...

  6. Material Design with the Android Design Support Library

    Material Design with the Android Design Support Library 原文http://www.sitepoint.com/material-design-a ...

  7. 假如 Redis 里面有 1 亿个 key,其中有 10w 个 key 是以 某个固定的已知的前缀开头的,如果将它们全部找出来?

    使用 keys 指令可以扫出指定模式的 key 列表. 对方接着追问:如果这个 redis 正在给线上的业务提供服务,那使用 keys 指令会 有什么问题? 这个时候你要回答 redis 关键的一个特 ...

  8. kafka 保证消息被消费和消息只消费一次

    1. 保证消息被消费 即使消息发送到了消息队列,消息也不会万无一失,还是会面临丢失的风险. 我们以 Kafka 为例,消息在Kafka 中是存储在本地磁盘上的, 为了减少消息存储对磁盘的随机 I/O, ...

  9. 202A 202B 202C 202D 202E字符的作用及解释

    这里你会发现在值的前后有2个\u开头的控制字符:转换网址:http://www.jsons.cn/utf8/ 解释:https://blog.csdn.net/haiyan1111/article/d ...

  10. Scanner几个问题与正则简介

    Pre:最近做了头条的在线笔试,对Scanner输入的处理有些特殊,当时是一脸懵逼态,遂由此随笔(/@_@\),java小白,有错难免! 查了下Scanner的源码,没有头绪,但是其中用到了正则的知识 ...