概述
Leaflet 框架中的 Util
模块,提供了许多实用工具函数,用于简化开发、处理常见任务(如对象操作、函数绑定、字符串处理等),并支持跨浏览器兼容性.
源码分析
源码实现如下
js
export function extend(dest) {
var i, j, len, src;
for (j = 1, len = arguments.length; j < len; j++) {
src = arguments[j];
for (i in src) {
dest[i] = src[i];
}
}
return dest;
}
export var create =
Object.create ||
(function () {
function F() {}
return function (proto) {
F.prototype = proto;
return new F();
};
})();
export function bind(fn, obj) {
var slice = Array.prototype.slice;
if (fn.bind) {
return fn.bind.apply(fn, slice.call(arguments, 1));
}
var args = slice.call(arguments, 2);
return function () {
return fn.apply(
obj,
args.length ? args.concat(slice.call(arguments)) : arguments
);
};
}
export var lasted = 0;
export function stamp(obj) {
if (!("_leaflet_id" in obj)) {
obj["_leaflet_id"] = ++lasted;
}
return obj._leaflet_id;
}
export function throttle(fn, time, context) {
var lock, args, wrapperFn, later;
later = function () {
lock = false;
if (args) {
wrapperFn.apply(context, args);
args = false;
}
};
wrapperFn = function () {
if (lock) {
args = arguments;
} else {
fn.apply(context, arguments);
setTimeout(later, time);
lock = true;
}
};
return wrapperFn;
}
export function wrapNum(x, range, includeMax) {
var max = range[1],
min = range[0],
d = max - min;
return x === max && includeMax ? x : ((((x - min) % d) + d) % d) + min;
}
export function falseFn() {
return false;
}
export function formatNum(num, precision) {
if (precision === false) {
return num;
}
var pow = Math.pow(10, precision === undefined ? 6 : precision);
return Math.round(num * pow) / pow;
}
export function trim(str) {
return str.trim ? str.trim() : str.replace(/^\s+|\s+$/g, "");
}
export function splitWords(str) {
return trim(str).split(/\s+/);
}
export function setOptions(obj, options) {
if (!Object.prototype.hasOwnProperty.call(obj, "options")) {
obj.options = obj.options ? create(obj.options) : {};
}
for (var i in options) {
obj.options[i] = options[i];
}
return obj.options;
}
export function getParamString(obj, existingUrl, uppercase) {
var params = [];
for (var i in obj) {
params.push(
encodeURIComponent(uppercase ? i.toUpperCase() : i) +
"=" +
encodeURIComponent(obj[i])
);
}
return (
(!existingUrl || existingUrl.indexOf("?") === -1 ? "?" : "&") +
params.join("&")
);
}
var templateRe = /\{*([\w_-]+)*\}/g;
export function template(str, data) {
return str.replace(templateRe, function (str, key) {
var value = data[key];
if (value === undefined) {
throw new Error("No value provided for variable " + str);
} else if (typeof value === "function") {
value = value(data);
}
return value;
});
}
export var isArray =
Array.isArray ||
function (obj) {
return Object.prototype.toString.call(obj) === "[object Array]";
};
export function indexOf(arr, el) {
for (var i = 0, len = arr.length; i < len; i++) {
if (arr[i] === el) {
return i;
}
}
return -1;
}
export var emptyImageUrl =
"data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=";
function getPrefixed(name) {
return window["webkit" + name] || window["moz" + name] || window["ms" + name];
}
var lastTime = 0;
function timeoutDefer(fn) {
var time = +new Date(),
timeToCall = Math.max(0, 16 - (time - lastTime));
lastTime = time + timeToCall;
return window.setTimeout(fn, timeToCall);
}
export var requestFn =
window.requestAnimationFrame ||
getPrefixed("RequestAnimationFrame") ||
timeoutDefer;
export var cancelFn =
window.cancelAnimationFrame ||
getPrefixed("CancelAnimationFrame") ||
getPrefixed("CancelRequestAnimationFrame") ||
function (id) {
window.clearTimeout(id);
};
export function requestAnimFrame(fn, context, immediate) {
if (immediate && requestFn === timeoutDefer) {
fn.call(context);
} else {
return requestFn.call(window, bind(fn, context));
}
}
export function cancelAnimFrame(id) {
if (id) {
cancelFn.call(window, id);
}
}
函数详细介绍
extend(dest,...src)
-
功能:将多个对象的属性合并到目标对象中.
-
参数:
dest
:目标对象src
:源对象(可传入多个)
-
返回值:合并后的目标对象
-
示例
js
const obj = { a: 1 };
Util.extend(obj, { b: 2 }, { c: 3 });
console.log(obj); // { a: 1, b: 2, c: 3 }
create(proto)
-
功能:创建一个新对象,并继承指定原型.
-
参数:
proto
:新对象的原型
-
返回值:新创建的对象.
-
示例
js
const obj = { a: 1 };
const newObj = Util.create(obj);
console.log(newObj.__proto__ === obj); // true
bind(fn,obj,...args)
-
功能 :创建一个新函数,该函数的
this
值被绑定到指定的对象,同时可以传入额外的参数. -
参数:
-
fn
:要绑定的函数 -
obj
:绑定的对象 -
args
:额外的参数(可选)
-
-
返回值:绑定后的函数
-
示例
js
const obj = { value: 10 };
const fn = function (a, b) { return this.value + a + b; };
const boundFn = Util.bind(fn, obj, 1);
console.log(boundFn(2)); // 13
- stamp(obj)
-
功能:为对象生成唯一标识符(ID),如果对象已有标识符则直接返回.
-
参数:
obj
:需要生成标识符的对象
-
返回值: 对象的唯一标识符
-
示例
js
const obj = {};
console.log(Util.stamp(obj)); // 1
console.log(Util.stamp(obj)); // 1 (相同对象返回相同 ID)
- throttle(fn,time,context)
-
功能:节流函数,限制函数在指定时间间隔内最多只执行一次.
-
参数:
fn
:需要节流的函数time
:时间间隔(毫秒)context
:函数的上下文(this
指向)
-
返回值:节流后的函数
-
示例
js
const throttledFn = Util.throttle(() => console.log('Throttled!'), 1000);
window.addEventListener('resize', throttledFn);
- wrapNum(x,range,includeMax)
-
功能 :将数值限制在指定范围内,支持循环(例如,经度范围在
-180
到180
) -
参数
x
:需要处理的数值range
:范围数组,如[min,max]
includeMax
:是否包含最大值,默认为false
-
返回值:处理后的数值
-
示例
js
console.log(Util.wrapNum(190, [-180, 180])); // -170
- falseFn()
-
功能 :返回
false
的函数 -
返回值 :
false
-
示例
js
console.log(Util.falseFn()); // false
- formatNum(num,precision)
-
功能:格式化数字,保留指定精度
-
参数
num
:需要格式化的数字precision
:小数位数(可选,默认为6
)
-
返回值:格式化后的数值
-
示例
js
console.log(Util.formatNum(3.1415926535, 2)); // 3.14
- trim(str)
-
功能 :去除字符串两端的空白字符。
-
参数:
str
:需要处理的字符串。
-
返回值 :处理后的字符串。
-
示例:
js
console.log(Util.trim(' Hello, Leaflet! ')); // 'Hello, Leaflet!'
- splitWords(str)
-
功能 :将字符串按空白字符分割为单词数组。
-
参数:
str
:需要处理的字符串。
-
返回值 :单词数组。
-
示例:
js
console.log(Util.splitWords('Hello World')); // ['Hello', 'World']
- setOptions(obj, options)
- 功能 :为对象设置选项(
options
),如果options
不存在则创建。 - 参数 :
obj
:目标对象。options
:需要设置的选项。
- 返回值 :设置后的
options
对象。
- 示例:
js
const obj = {};
Util.setOptions(obj, { a: 1 });
console.log(obj.options); // { a: 1 }
- getParamString(obj, existingUrl, uppercase)
-
功能 :将对象转换为
URL
参数字符串。
-
参数:
-
obj
:需要转换的对象。 -
existingUrl
:已存在的URL
(可选)。 -
uppercase
:是否将参数名转换为大写(可选)。 -
返回值 :
URL
参数字符串。
-
示例:
js
console.log(Util.getParamString({ a: 1, b: 2 })); // '?a=1&b=2'
- template(str, data)
- 功能 :将字符串中的占位符替换为数据。
- 参数 :
str
:模板字符串。data
:数据对象。
- 返回值 :替换后的字符串。
- 示例:
js
console.log(Util.template('Hello, {name}!', { name: 'Leaflet' })); // 'Hello, Leaflet!'
- isArray(obj)
- 功能 :检查对象是否为数组。
- 参数 :
obj
:需要检查的对象。
- 返回值 :布尔值。
- 示例:
js
console.log(Util.isArray([1, 2, 3])); // true
- indexOf(arr, el)
-
功能:查找元素在数组中的索引。
-
参数:
-
arr
:数组。 -
el
:需要查找的元素。
-
返回值:元素的索引(如果未找到则返回 -1)。
-
示例:
js
console.log(Util.indexOf([1, 2, 3], 2)); // 1
- requestAnimFrame(fn, context, immediate)
-
功能 :请求动画帧,支持立即执行。
-
参数:
fn
:需要执行的函数。context
:函数的上下文(this
指向)。immediate
:是否立即执行(可选)。
-
返回值 :动画帧 ID。
-
示例:
js
Util.requestAnimFrame(() => console.log('Frame!'));
- cancelAnimFrame(id)
- 功能 :取消动画帧。
- 参数:
id
:动画帧 ID。- 示例:
js
const id = Util.requestAnimFrame(() => console.log('Frame!'));
Util.cancelAnimFrame(id);
总结
Util
模块是 Leaflet 的核心工具模块,提供了许多实用函数,用于简化开发、处理常见任务(如对象操作、函数绑定、字符串处理等),并支持跨浏览器兼容性。这些函数在 Leaflet 的内部实现中被广泛使用,同时也可以被开发者直接调用