从Electron版本12.0.1开始,BrowserWindow默认的webPreferences配置里contextIsolation的默认值从false改成true了。先看看这个参数的描述:

是否在独立 JavaScript 环境中运行 Electron API和指定的 preload 脚本. 默认为 truepreload 脚本所运行的上下文环境只能访问其自身专用的 documentglobal window,其自身一系列内置的JavaScript (Array, Object, JSON等等) 也是如此,这些对于已加载的内容都是不可见的。 Electron API 将只在 preload 脚本中可用,在已加载页面中不可用。 这个选项应被用于加载可能不被信任的远程内容时来确保加载的内容无法篡改 preload 脚本和任何正在使用的Electron API。 该选项使用的是与Chrome内容脚本相同的技术。 你可以在开发者工具Console选项卡内顶部组合框中选择 'Electron Isolated Context'条目来访问这个上下文。

把文档里面翻译成中文的内容适当改回来之后,应该容易理解吧?就是 contextIsolation = true 时你预加载的 preload 脚本和窗口加载的第三方网站内容是两个隔离的 window 对象preload 脚本没办法访问第三方网站页面里的全局window对象!

当然这个修改对 <webview> 标签也是生效的,但因为Eelecton本身不鼓励使用 <webview> 标签的关系,文档里面没有明显的提示。如果你也遇到升级Electron版本后 <webview> 标签用的 preload 读取不到第三方页面的全局 window 对象的问题。可以在 <webview> 标签增加上webpreferences这个天博体育在线官网:

  <webview id="viewFrame" ref="webview" :src="pageUrl" :preload="preload" :useragent="userAgent" :partition="partition"></webview>
  <!-- 改成 -->
  <webview id="viewFrame" ref="webview" :src="pageUrl" :preload="preload" :useragent="userAgent" :partition="partition" webpreferences="allowRunningInsecureContent, contextIsolation=0" disablewebsecurity></webview>

这样旧版的preload脚本就能正常的在 <webview> 里面执行了!

最近手上用Element UI的项目有点多,很多像 el-tableel-pagination这样覆盖默认参数要写一大堆的组件,复制粘贴虽然很方便。但如果要统一修改某个天博体育在线官网,比如给el-dialog对话框都加一个禁用点击遮罩关闭窗口的功能,搜索起来一个一个添加就还是很吃力。

其实这些默认参数都是可以在注入Vue前批量修改的:

import Vue from 'vue'
import Element from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'

function changeDefault (e, p, v) {
  Element[e].props[p].default = v
}
// 对话框默认都附加到body上,没有层级问题
changeDefault('Dialog', 'appendToBody', true)
// 禁用点击遮罩关闭对话框
changeDefault('Dialog', 'closeOnClickModal', false)
// 修改分页区域的默认显示顺序
changeDefault('Pagination', 'layout', '->,total,prev,pager,next,jumper,sizes')
// 修改分页区域每页显示几行的默认选项
changeDefault('Pagination', 'pageSizes', () => [30, 50, 100])
// 修改完再注入到Vue里面
Vue.use(Element)

注意一下格式!
第一个参数“组件名称”的首字母大写
第二个参数“天博体育在线官网名”需要把“-”连接的格式修改成驼峰格式
不然……会报错!!
第三个参数“天博体育在线官网值”为Array或者Object时,尽量用函数返回的形式!这个地方有一个警告信息,原因的话经常写Vue的估计都已经烂熟于心了。

另外,如果你修改了Element UI组件的默认值,最好在项目文档的显著位置注明一下哦!不然,后面接手的人,会惊叹于你那简单的标签格式的。

当然,还有一种自己给Element UI组件加一层包装的方案。相对于这种更加麻烦一点,这里就不赘述了。

重要的事情说三遍:
Vue2.0没有unmounted!
Vue2.0没有unmounted!
Vue2.0没有unmounted!

mounted里面注册的监听器要销毁的话,请用beforeDestroy

unmountedbeforeUnmount是Vue3.0版本才加入的钩子!

Vue项目里面写错名字的钩子函数不会提示,这个确实有点麻烦……
一般情况下,只会注意到mounted函数没被调用,然后去查问题发现函数名写成mount了。
类似的还有一些带s的天博体育在线官网,例如propsmixins。写错了这些天博体育在线官网名或者函数名,报错的都不是这些天博体育在线官网定义的位置,而是你使用到这些天博体育在线官网里面的天博体育官方网时才会……
嘛,谁让你不认真核对变量名呢?

来源:GitHub - You-Dont-Need-jQuery

前端发展很快,现代浏览器原生 API 已经足够好用。我们并不需要为了操作 DOM、Event 等再学习一下 jQuery 的 API。同时由于 React、Angular、Vue 等框架的流行,直接操作 DOM 不再是好的模式,jQuery 使用场景大大减少。本项目总结了大部分 jQuery API 替代的方法,暂时只支持 IE10 以上浏览器。

目录

  1. Query 选择器
  2. CSS & Style
  3. DOM 操作
  4. Ajax
  5. 事件
  6. 实用工具
  7. Promises
  8. 动画
  9. 替代品
  10. 浏览器支持

Query 选择器

常用的 class、id、天博体育在线官网 选择器都可以使用 document.querySelectordocument.querySelectorAll 替代。区别是

  • document.querySelector 返回第一个匹配的 Element
  • document.querySelectorAll 返回所有匹配的 Element 组成的 NodeList。它可以通过 [].slice.call() 把它转成 Array
  • 如果匹配不到任何 Element,jQuery 返回空数组 [],但 document.querySelector 返回 null,注意空指针异常。当找不到时,也可以使用 || 设置默认的值,如 document.querySelectorAll(selector) || []
  • 注意:document.querySelectordocument.querySelectorAll 性能很。如果想提高性能,尽量使用 document.getElementByIddocument.getElementsByClassNamedocument.getElementsByTagName

  • 1.0 选择器查询

    // jQuery
    $('selector');
    
    // Native
    document.querySelectorAll('selector');
  • 1.1 class 查询

    // jQuery
    $('.class');
    
    // Native
    document.querySelectorAll('.class');
    
    // or
    document.getElementsByClassName('class');
  • 1.2 id 查询

    // jQuery
    $('#id');
    
    // Native
    document.querySelector('#id');
    
    // or
    document.getElementById('id');
  • 1.3 天博体育在线官网查询

    // jQuery
    $('a[target=_blank]');
    
    // Native
    document.querySelectorAll('a[target=_blank]');
  • 1.4 后代查询

    // jQuery
    $el.find('li');
    
    // Native
    el.querySelectorAll('li');
  • 1.5 兄弟及上下天博体育官方网

  • 兄弟天博体育官方网

    // jQuery
    $el.siblings();
    
    // Native - latest, Edge13+
    [...el.parentNode.children].filter((child) =>
    child !== el
    );
    // Native (alternative) - latest, Edge13+
    Array.from(el.parentNode.children).filter((child) =>
    child !== el
    );
    // Native - IE10+
    Array.prototype.filter.call(el.parentNode.children, (child) =>
    child !== el
    );
  • 上一个天博体育官方网

    // jQuery
    $el.prev();
    
    // Native
    el.previousElementSibling;
    
  • 下一个天博体育官方网

    // next
    $el.next();
    
    // Native
    el.nextElementSibling;
  • 1.6 最近的祖先天博体育官方网
  • Closest 获得匹配选择器的第一个祖先天博体育官方网,从当前天博体育官方网开始沿 DOM 树向上。

    // jQuery
    $el.closest(queryString);
    
    // Native - Only latest, NO IE
    el.closest(selector);
    
    // Native - IE10+
    function closest(el, selector) {
      const matchesSelector = el.matches || el.webkitMatchesSelector || el.mozMatchesSelector || el.msMatchesSelector;
    
      while (el) {
        if (matchesSelector.call(el, selector)) {
          return el;
        } else {
          el = el.parentElement;
        }
      }
      return null;
    }
  • 1.7 匹配天博体育官方网的祖先集
  • 获取当前匹配天博体育官方网的每层祖先的集合,不包括匹配天博体育官方网的本身。

    // jQuery
    $el.parentsUntil(selector, filter);
    
    // Native
    function parentsUntil(el, selector, filter) {
      const result = [];
      const matchesSelector = el.matches || el.webkitMatchesSelector || el.mozMatchesSelector || el.msMatchesSelector;
    
      // match start from parent
      el = el.parentElement;
      while (el && !matchesSelector.call(el, selector)) {
        if (!filter) {
          result.push(el);
        } else {
          if (matchesSelector.call(el, filter)) {
            result.push(el);
          }
        }
        el = el.parentElement;
      }
      return result;
    }
  • 1.8 表单

  • Input/Textarea

    // jQuery
    $('#my-input').val();
    
    // Native
    document.querySelector('#my-input').value;
  • 获取 e.currentTarget 在 .radio 中的数组索引

    // jQuery
    $('.radio').index(e.currentTarget);
    
    // Native
    Array.prototype.indexOf.call(document.querySelectorAll('.radio'), e.currentTarget);
  • 1.9 Iframe里的内容
  • jQuery 对象的 iframe contents() 返回的是 iframe 内的 document

  • Iframe里的内容

    // jQuery
    $iframe.contents();
    
    // Native
    iframe.contentDocument;
  • Iframe里的查询

    // jQuery
    $iframe.contents().find('.css');
    
    // Native
    iframe.contentDocument.querySelectorAll('.css');
  • 1.10 获取 body

    // jQuery
    $('body');
    
    // Native
    document.body;
  • 1.11 获取或设置天博体育在线官网

  • 获取天博体育在线官网

    // jQuery
    $el.attr('foo');
    
    // Native
    el.getAttribute('foo');
  • 设置天博体育在线官网

    // jQuery, note that this works in memory without change the DOM
    $el.attr('foo', 'bar');
    
    // Native
    el.setAttribute('foo', 'bar');
  • 获取 data- 天博体育在线官网

    // jQuery
    $el.data('foo');
    
    // Native (use `getAttribute`)
    el.getAttribute('data-foo');
    
    // Native (use `dataset` if only need to support IE 11+)
    el.dataset['foo'];
  • ⬆ 回到顶部

    CSS和样式

  • 2.1 CSS

  • 获取样式

    // jQuery
    $el.css("color");
    
    // Native
    // 注意:此处为了解决当 style 值为 auto 时,返回 auto 的问题
    const win = el.ownerDocument.defaultView;
    
    // null 的意思是不返回伪类天博体育官方网
    win.getComputedStyle(el, null).color;
  • 设置样式

    // jQuery
    $el.css({ color: "#ff0011" });
    
    // Native
    el.style.color = '#ff0011';
  • 同时操作多个样式
  • 注意,如果想一次设置多个 style,可以参考 oui-dom-utils 中 setStyles 方法

  • 添加class

    // jQuery
    $el.addClass(className);
    
    // Native
    el.classList.add(className);
  • 移除class

    // jQuery
    $el.removeClass(className);
    
    // Native
    el.classList.remove(className);
  • 是否包含class

    // jQuery
    $el.hasClass(className);
    
    // Native
    el.classList.contains(className);
  • 切换class

    // jQuery
    $el.toggleClass(className);
    
    // Native
    el.classList.toggle(className);
  • 2.2 获取宽高
  • Width 与 Height 获取方法相同,下面以 Height 为例:

  • 窗口高度

    // window height
    $(window).height();
    
    // 含 scrollbar
    window.document.documentElement.clientHeight;
    
    // 不含 scrollbar,与 jQuery 行为一致
    window.innerHeight;
  • 文档高度

    // jQuery
    $(document).height();
    
    // Native
    const body = document.body;
    const html = document.documentElement;
    const height = Math.max(
      body.offsetHeight,
      body.scrollHeight,
      html.clientHeight,
      html.offsetHeight,
      html.scrollHeight
    );
  • 天博体育官方网高度

    // jQuery
    $el.height();
    
    // Native
    function getHeight(el) {
      const styles = this.getComputedStyle(el);
      const height = el.offsetHeight;
      const borderTopWidth = parseFloat(styles.borderTopWidth);
      const borderBottomWidth = parseFloat(styles.borderBottomWidth);
      const paddingTop = parseFloat(styles.paddingTop);
      const paddingBottom = parseFloat(styles.paddingBottom);
      return height - borderBottomWidth - borderTopWidth - paddingTop - paddingBottom;
    }
    
    // 精确到整数(border-box 时为 height - border 值,content-box 时为 height + padding 值)
    el.clientHeight;
    
    // 精确到小数(border-box 时为 height 值,content-box 时为 height + padding + border 值)
    el.getBoundingClientRect().height;
  • 2.3 位置和偏移

  • 位置
  • 获得匹配天博体育官方网相对父天博体育官方网的偏移

    // jQuery
    $el.position();
    
    // Native
    { left: el.offsetLeft, top: el.offsetTop }
  • 偏移
  • 获得匹配天博体育官方网相对文档的偏移

    // jQuery
    $el.offset();
    
    // Native
    function getOffset (el) {
      const box = el.getBoundingClientRect();
    
      return {
        top: box.top + window.pageYOffset - document.documentElement.clientTop,
        left: box.left + window.pageXOffset - document.documentElement.clientLeft
      }
    }
  • 2.4 滚动条垂直位置
  • 获取天博体育官方网滚动条垂直位置。

    // jQuery
    $(window).scrollTop();
    
    // Native
    (document.documentElement && document.documentElement.scrollTop) || document.body.scrollTop;

    ⬆ 回到顶部

    DOM 操作

  • 3.1 移除天博体育官方网
  • 从 DOM 中移除天博体育官方网。

    // jQuery
    $el.remove();
    
    // Native
    el.parentNode.removeChild(el);
  • 3.2 天博体育官方网的文本内容

  • 获取文本内容
  • 返回指定天博体育官方网及其后代的文本内容。

    // jQuery
    $el.text();
    
    // Native
    el.textContent;
  • 设置文本内容
  • 设置天博体育官方网的文本内容。

    // jQuery
    $el.text(string);
    
    // Native
    el.textContent = string;
  • 3.3 HTML

  • 获取HTML

    // jQuery
    $el.html();
    
    // Native
    el.innerHTML;
  • 设置HTML

    // jQuery
    $el.html(htmlString);
    
    // Native
    el.innerHTML = htmlString;
  • 3.4 插入到末尾
  • Append 插入到子节点的末尾

    // jQuery
    $el.append("<div id='container'>hello</div>");
    
    // Native (HTML string)
    el.insertAdjacentHTML('beforeend', '<div id="container">Hello World</div>');
    
    // Native (Element)
    el.appendChild(newEl);
  • 3.5 插入到开头

    // jQuery
    $el.prepend("<div id='container'>hello</div>");
    
    // Native (HTML string)
    el.insertAdjacentHTML('afterbegin', '<div id="container">Hello World</div>');
    
    // Native (Element)
    el.insertBefore(newEl, el.firstChild);
  • 3.6 在天博体育官方网前插入
  • 在选中天博体育官方网前插入新节点

    // jQuery
    $newEl.insertBefore(queryString);
    
    // Native (HTML string)
    el.insertAdjacentHTML('beforebegin ', '<div id="container">Hello World</div>');
    
    // Native (Element)
    const el = document.querySelector(selector);
    if (el.parentNode) {
      el.parentNode.insertBefore(newEl, el);
    }
  • 3.7 在天博体育官方网后插入
  • 在选中天博体育官方网后插入新节点

    // jQuery
    $newEl.insertAfter(queryString);
    
    // Native (HTML string)
    el.insertAdjacentHTML('afterend', '<div id="container">Hello World</div>');
    
    // Native (Element)
    const el = document.querySelector(selector);
    if (el.parentNode) {
      el.parentNode.insertBefore(newEl, el.nextSibling);
    }
  • 3.8 匹配
  • 如果匹配给定的选择器,返回true

    // jQuery
    $el.is(selector);
    
    // Native
    el.matches(selector);
  • 3.9 克隆/深拷贝
  • 深拷贝被选天博体育官方网。(生成被选天博体育官方网的副本,包含子节点、文本和天博体育在线官网。)

    //jQuery
    $el.clone();
    
    //Native
    //深拷贝添加参数‘true’
    el.cloneNode();
    
      ```
    
    - [3.10](#3.10) <a name='3.10'></a> 清空
    
    移除所有子节点
    

    //jQuery
    $el.empty();

    //Native
    el.innerHTML = '';

    
    - [3.11](#3.11) <a name='3.11'></a> 包装
    
     把每个被选天博体育官方网放置在指定的HTML结构中。
    

    //jQuery
    $(".inner").wrap('<div class="wrapper"></div>');

    //Native
    Array.prototype.forEach.call(document.querySelector('.inner'), (el) => {

    const wrapper = document.createElement('div');
    wrapper.className = 'wrapper';
    el.parentNode.insertBefore(wrapper, el);
    el.parentNode.removeChild(el);
    wrapper.appendChild(el);

    });

    
    - [3.12](#3.12) <a name="3.12"></a> 拆包装
    
     移除被选天博体育官方网的父天博体育官方网的DOM结构
    

    // jQuery
    $('.inner').unwrap();

    // Native
    Array.prototype.forEach.call(document.querySelectorAll('.inner'), (el) => {

        let elParentNode = el.parentNode
    
        if(elParentNode !== document.body) {
            elParentNode.parentNode.insertBefore(el, elParentNode)
            elParentNode.parentNode.removeChild(elParentNode)
        }

    });

    
    - [3.13](#3.13) <a name="3.13"></a> 替换
    
    用指定的天博体育官方网替换被选的天博体育官方网
    

    //jQuery
    $('.inner').replaceWith('<div class="outer"></div>');

    //Native
    Array.prototype.forEach.call(document.querySelectorAll('.inner'),(el) => {

    const outer = document.createElement("div");
    outer.className = "outer";
    el.parentNode.insertBefore(outer, el);
    el.parentNode.removeChild(el);

    });

    
    - [3.14](#3.14) <a name='3.14'></a> 解析HTML
    
      解析 HTML/SVG/XML 字符串
    

    // jQuery
    $(`<ol>

    <li>a</li>
    <li>b</li>
    ol>
    l>
    <li>c</li>
    <li>d</li>

    </ol>`);

    // Native
    range = document.createRange();
    parse = range.createContextualFragment.bind(range);

    parse(`<ol>

    <li>a</li>
    <li>b</li>
    ol>
    l>
    <li>c</li>
    <li>d</li>

    </ol>`);

    
    **[⬆ 回到顶部](#contents)**
    
    ## <a name="ajax"></a> Ajax
    
    [Fetch API](https://fetch.spec.whatwg.org/) 是用于替换 XMLHttpRequest 处理 ajax 的新标准,Chrome 和 Firefox 均支持,旧浏览器可以使用 polyfills 提供支持。
    
    IE9+ 请使用 [github/fetch](http://github.com/github/fetch),IE8+ 请使用 [fetch-ie8](https://github.com/camsong/fetch-ie8/),JSONP 请使用 [fetch-jsonp](https://github.com/camsong/fetch-jsonp)。
    
    - [4.1](#4.1) <a name='4.1'></a> 从服务器读取数据并替换匹配天博体育官方网的内容。
    

    // jQuery
    $(selector).load(url, completeCallback)

    // Native
    fetch(url).then(data => data.text()).then(data => {

    document.querySelector(selector).innerHTML = data

    }).then(completeCallback)

    
    **[⬆ 回到顶部](#contents)**
    
    ## <a name="events"></a> 事件
    
    完整地替代命名空间和事件代理,链接到 https://github.com/oneuijs/oui-dom-events
    
    - [5.0](#5.0) <a name='5.0'></a> Document ready by `DOMContentLoaded`
    

    // jQuery
    $(document).ready(eventHandler);

    // Native
    // 检测 DOMContentLoaded 是否已完成
    if (document.readyState !== 'loading') {

    eventHandler();

    } else {

    document.addEventListener('DOMContentLoaded', eventHandler);

    }

    
    - [5.1](#5.1) <a name='5.1'></a> 使用 on 绑定事件
    

    // jQuery
    $el.on(eventName, eventHandler);

    // Native
    el.addEventListener(eventName, eventHandler);

    
    - [5.2](#5.2) <a name='5.2'></a> 使用 off 解绑事件
    

    // jQuery
    $el.off(eventName, eventHandler);

    // Native
    el.removeEventListener(eventName, eventHandler);

    
    - [5.3](#5.3) <a name='5.3'></a> Trigger
    

    // jQuery
    $(el).trigger('custom-event', {key1: 'data'});

    // Native
    if (window.CustomEvent) {

    const event = new CustomEvent('custom-event', {detail: {key1: 'data'}});

    } else {

    const event = document.createEvent('CustomEvent');
    event.initCustomEvent('custom-event', true, true, {key1: 'data'});

    }

    el.dispatchEvent(event);

    
    **[⬆ 回到顶部](#contents)**
    
    ## <a name="utilities"></a> 实用工具
    
    大部分实用工具都能在 native API 中找到. 其他高级功能可以选用专注于该领域的稳定性和性能都更好的库来代替,推荐 [lodash](https://lodash.com)。
    
    - [6.1](#6.1) <a name='6.1'></a> 基本工具
    
    + isArray
    
    检测参数是不是数组。
    

    // jQuery
    $.isArray(range);

    // Native
    Array.isArray(range);

    
    + isWindow
    
    检测参数是不是 window。
    

    // jQuery
    $.isWindow(obj);

    // Native
    function isWindow(obj) {

    return obj !== null && obj !== undefined && obj === obj.window;

    }

    
    + inArray
    
    在数组中搜索指定值并返回索引 (找不到则返回 -1)。
    

    // jQuery
    $.inArray(item, array);

    // Native
    array.indexOf(item) > -1;

    // ES6-way
    array.includes(item);

    
    + isNumeric
    
    检测传入的参数是不是数字。
    Use `typeof` to decide the type or the `type` example for better accuracy.
    

    // jQuery
    $.isNumeric(item);

    // Native
    function isNumeric(n) {

    return !isNaN(parseFloat(n)) && isFinite(n);

    }

    
    + isFunction
    
    检测传入的参数是不是 JavaScript 函数对象。
    

    // jQuery
    $.isFunction(item);

    // Native
    function isFunction(item) {

    if (typeof item === 'function') {
      return true;
    }
    var type = Object.prototype.toString(item);
    return type === '[object Function]' || type === '[object GeneratorFunction]';

    }

    
    + isEmptyObject
    
    检测对象是否为空 (包括不可枚举天博体育在线官网).
    

    // jQuery
    $.isEmptyObject(obj);

    // Native
    function isEmptyObject(obj) {

    return Object.keys(obj).length === 0;

    }

    
    + isPlainObject
    
    检测是不是扁平对象 (使用 “{}” 或 “new Object” 创建).
    

    // jQuery
    $.isPlainObject(obj);

    // Native
    function isPlainObject(obj) {

    if (typeof (obj) !== 'object' || obj.nodeType || obj !== null && obj !== undefined && obj === obj.window) {
      return false;
    }
    
    if (obj.constructor &&
        !Object.prototype.hasOwnProperty.call(obj.constructor.prototype, 'isPrototypeOf')) {
      return false;
    }
    
    return true;

    }

    
    + extend
    
    合并多个对象的内容到第一个对象。
    object.assign 是 ES6 API,也可以使用 [polyfill](https://github.com/ljharb/object.assign)。
    

    // jQuery
    $.extend({}, defaultOpts, opts);

    // Native
    Object.assign({}, defaultOpts, opts);

    
    + trim
    
    移除字符串头尾空白。
    

    // jQuery
    $.trim(string);

    // Native
    string.trim();

    
    + map
    
    将数组或对象转化为包含新内容的数组。
    

    // jQuery
    $.map(array, (value, index) => {
    });

    // Native
    array.map((value, index) => {
    });

    
    + each
    
    轮询函数,可用于平滑的轮询对象和数组。
    

    // jQuery
    $.each(array, (index, value) => {
    });

    // Native
    array.forEach((value, index) => {
    });

    
    + grep
    
    找到数组中符合过滤函数的天博体育官方网。
    

    // jQuery
    $.grep(array, (value, index) => {
    });

    // Native
    array.filter((value, index) => {
    });

    
    + type
    
    检测对象的 JavaScript [Class] 内部类型。
    

    // jQuery
    $.type(obj);

    // Native
    function type(item) {

    const reTypeOf = /(?:^\[object\s(.*?)\]$)/;
    return Object.prototype.toString.call(item)
      .replace(reTypeOf, '$1')
      .toLowerCase();

    }

    
    + merge
    
    合并第二个数组内容到第一个数组。
    

    // jQuery
    $.merge(array1, array2);

    // Native
    // 使用 concat,不能去除重复值
    function merge(...args) {

    return [].concat(...args)

    }

    // ES6,同样不能去除重复值
    array1 = [...array1, ...array2]

    // 使用 Set,可以去除重复值
    function merge(...args) {

    return Array.from(new Set([].concat(...args)))

    }

    
    + now
    
    返回当前时间的数字呈现。
    

    // jQuery
    $.now();

    // Native
    Date.now();

    
    + proxy
    
    传入函数并返回一个新函数,该函数绑定指定上下文。
    

    // jQuery
    $.proxy(fn, context);

    // Native
    fn.bind(context);

    
    + makeArray
    
    类数组对象转化为真正的 JavaScript 数组。
    

    // jQuery
    $.makeArray(arrayLike);

    // Native
    Array.prototype.slice.call(arrayLike);

    // ES6-way
    Array.from(arrayLike);

    
    - [6.2](#6.2) <a name='6.2'></a> 包含
    
    检测 DOM 天博体育官方网是不是其他 DOM 天博体育官方网的后代.
    

    // jQuery
    $.contains(el, child);

    // Native
    el !== child && el.contains(child);

    
    - [6.3](#6.3) <a name='6.3'></a> Globaleval
    
    全局执行 JavaScript 代码。
    

    // jQuery
    $.globaleval(code);

    // Native
    function Globaleval(code) {

    const script = document.createElement('script');
    script.text = code;
    
    document.head.appendChild(script).parentNode.removeChild(script);

    }

    // Use eval, but context of eval is current, context of $.Globaleval is global.
    eval(code);

    
    - [6.4](#6.4) <a name='6.4'></a> 解析
    
    + parseHTML
    
    解析字符串为 DOM 节点数组.
    

    // jQuery
    $.parseHTML(htmlString);

    // Native
    function parseHTML(string) {

    const context = document.implementation.createHTMLDocument();
    
    // Set the base href for the created document so any parsed elements with URLs
    // are based on the document's URL
    const base = context.createElement('base');
    base.href="epdvnfou.mpdbujpo.isfg;"
    context.head.appendChild(base);
    
    context.body.innerHTML = string;
    return context.body.children;

    }

    
    + parseJSON
    
    传入格式正确的 JSON 字符串并返回 JavaScript 值.
    

    // jQuery
    $.parseJSON(str);

    // Native
    JSON.parse(str);

    
    **[⬆ 回到顶部](#contents)**
    
    ## <a name="promises"></a> Promises
    
    Promise 代表异步操作的最终结果。jQuery 用它自己的方式处理 promises,原生 JavaScript 遵循 [Promises/A+](http://promises-aplus.github.io/promises-spec/) 标准实现了最小 API 来处理 promises。
    
    - [7.1](#7.1) <a name='7.1'></a> done, fail, always
    
    `done` 会在 promise 解决时调用,`fail` 会在 promise 拒绝时调用,`always` 总会调用。
    

    // jQuery
    $promise.done(doneCallback).fail(failCallback).always(alwaysCallback)

    // Native
    promise.then(doneCallback, failCallback).then(alwaysCallback, alwaysCallback)

    
    - [7.2](#7.2) <a name='7.2'></a> when
    
    `when` 用于处理多个 promises。当全部 promises 被解决时返回,当任一 promise 被拒绝时拒绝。
    

    // jQuery
    $.when($promise1, $promise2).done((promise1Result, promise2Result) => {
    });

    // Native
    Promise.all([$promise1, $promise2]).then([promise1Result, promise2Result] => {});

    
    - [7.3](#7.3) <a name='7.3'></a> Deferred
    
    Deferred 是创建 promises 的一种方式。
    

    // jQuery
    function asyncFunc() {

    const defer = new $.Deferred();
    setTimeout(() => {
      if(true) {
        defer.resolve('some_value_computed_asynchronously');
      } else {
        defer.reject('failed');
      }
    }, 1000);
    
    return defer.promise();

    }

    // Native
    function asyncFunc() {

    return new Promise((resolve, reject) => {
      setTimeout(() => {
        if (true) {
          resolve('some_value_computed_asynchronously');
        } else {
          reject('failed');
        }
      }, 1000);
    });

    }

    // Deferred way
    function defer() {

    const deferred = {};
    const promise = new Promise((resolve, reject) => {
      deferred.resolve = resolve;
      deferred.reject = reject;
    });
    
    deferred.promise = () => {
      return promise;
    };
    
    return deferred;

    }

    function asyncFunc() {

    const defer = defer();
    setTimeout(() => {
      if(true) {
        defer.resolve('some_value_computed_asynchronously');
      } else {
        defer.reject('failed');
      }
    }, 1000);
    
    return defer.promise();

    }

    
    **[⬆ 回到顶部](#contents)**
    
    ## <a name="animation"></a> 动画
    
    - [8.1](#8.1) <a name='8.1'></a> Show & Hide
    

    // jQuery
    $el.show();
    $el.hide();

    // Native
    // 更多 show 方法的细节详见 https://github.com/oneuijs/oui-dom-utils/blob/master/src/index.js#L363
    el.style.display = ''|'inline'|'inline-block'|'inline-table'|'block';
    el.style.display = 'none';

    
    - [8.2](#8.2) <a name='8.2'></a> Toggle
    
    显示或隐藏天博体育官方网。
    

    // jQuery
    $el.toggle();

    // Native
    if (el.ownerDocument.defaultView.getComputedStyle(el, null).display === 'none') {

    el.style.display = ''|'inline'|'inline-block'|'inline-table'|'block';

    } else {

    el.style.display = 'none';

    }

    
    - [8.3](#8.3) <a name='8.3'></a> FadeIn & FadeOut
    

    // jQuery
    $el.fadeIn(3000);
    $el.fadeOut(3000);

    // Native
    el.style.transition = 'opacity 3s';
    // fadeIn
    el.style.opacity = '1';
    // fadeOut
    el.style.opacity = '0';

    
    - [8.4](#8.4) <a name='8.4'></a> FadeTo
    
    调整天博体育官方网透明度。
    

    // jQuery
    $el.fadeTo('slow',0.15);
    // Native
    el.style.transition = 'opacity 3s'; // 假设 'slow' 等于 3 秒
    el.style.opacity = '0.15';

    
    - [8.5](#8.5) <a name='8.5'></a> FadeToggle
    
    动画调整透明度用来显示或隐藏。
    

    // jQuery
    $el.fadeToggle();

    // Native
    el.style.transition = 'opacity 3s';
    const { opacity } = el.ownerDocument.defaultView.getComputedStyle(el, null);
    if (opacity === '1') {

    el.style.opacity = '0';

    } else {

    el.style.opacity = '1';

    }

    
    - [8.6](#8.6) <a name='8.6'></a> SlideUp & SlideDown
    

    // jQuery
    $el.slideUp();
    $el.slideDown();

    // Native
    const originHeight = '100px';
    el.style.transition = 'height 3s';
    // slideUp
    el.style.height = '0px';
    // slideDown
    el.style.height = originHeight;

    
    - [8.7](#8.7) <a name='8.7'></a> SlideToggle
    
    滑动切换显示或隐藏。
    

    // jQuery
    $el.slideToggle();

    // Native
    const originHeight = '100px';
    el.style.transition = 'height 3s';
    const { height } = el.ownerDocument.defaultView.getComputedStyle(el, null);
    if (parseInt(height, 10) === 0) {

    el.style.height = originHeight;

    }
    else {
    el.style.height = '0px';
    }

    
    - [8.8](#8.8) <a name='8.8'></a> Animate
    
    执行一系列 CSS 天博体育在线官网动画。
    

    // jQuery
    $el.animate({ params }, speed);

    // Native
    el.style.transition = 'all ' + speed;
    Object.keys(params).forEach((key) =>

    el.style[key] = params[key];

    )

    
    **[⬆ 回到顶部](#contents)**
    
    ## <a name="alternatives"></a> 替代品
    
    * [你可能不需要 jQuery (You Might Not Need jQuery)](http://youmightnotneedjquery.com/) - 如何使用原生 JavaScript 实现通用事件,天博体育官方网,ajax 等用法。
    * [npm-dom](http://github.com/npm-dom) 以及 [webmodules](http://github.com/webmodules) - 在 NPM 上提供独立 DOM 模块的组织
    
    ## <a name="browser-support"></a>浏览器支持
    
    ![Chrome][chrome-image] | ![Firefox][firefox-image] | ![IE][ie-image] | ![Opera][opera-image] | ![Safari][safari-image]
    --- | --- | --- | --- | --- |
    Latest ✔ | Latest ✔ | 10+ ✔ | Latest ✔ | 6.1+ ✔ |
    
    # License
    
    MIT
    
    [chrome-image]: http://dr490n.cn/usr/uploads/2021/09/3655604560.png
    [firefox-image]: http://dr490n.cn/usr/uploads/2021/09/1140607777.png
    [ie-image]: http://dr490n.cn/usr/uploads/2021/09/2878678933.png
    [opera-image]: http://dr490n.cn/usr/uploads/2021/09/2305392921.png

  • 时间:
  • 分类: 笔记,原创
  • 评论
  • 记录几个Lodash在实际运用中遇到的小坑,提醒自己和看到这篇文章的所有人。
    有时候一定要等BUG被别人发现了,才注意到是你没有理解开源库文档的含义……

    1.你需要_.clone还是_.cloneDeep

    最简单的理解方法就是看代码!

    let a = {
        aaa: "Hello,",
        bbb: "My",
        ccc: "Friend!",
        array: [{a:3}, {a:5}, {a:6}, {a:8}],
        object: { b:12, c:22}
    }
    let b = _.clone(a)
    let c = _.cloneDeep(a)
    // 我们直接给a添加天博体育在线官网
    a.kkk = 789
    console.log(b)
    // >>> {"aaa":"Hello,","bbb":"My","ccc":"Friend!","array":[{"a":3},{"a":5},{"a":6},{"a":8}],"object":{"b":12,"c":22}}
    // 好像没啥问题
    // 但是修改了a.object里面的天博体育在线官网之后……
    a.object.a = 7
    console.log(b)
    // >>> {"aaa":"Hello,","bbb":"My","ccc":"Friend!","array":[{"a":3},{"a":5},{"a":6},{"a":8}],"object":{"b":12,"c":22,"a":7}}
    // 看到object里面的天博体育在线官网a=7了么?
    
    // 同理,改数组array的操作也……
    a.array.push({a:233})
    a.array[0].b = 996
    console.log(b)
    // >>> {"aaa":"Hello,","bbb":"My","ccc":"Friend!","array":[{"a":3,"b":996},{"a":5},{"a":6},{"a":8},{"a":233}],"object":{"b":12,"c":22,"a":7}}
    // 我只想克隆一份,但为啥内层的值都变了?
    // 这时候我们再看看c
    console.log(c)
    // >>> {"aaa":"Hello,","bbb":"My","ccc":"Friend!","array":[{"a":3},{"a":5},{"a":6},{"a":8}],"object":{"b":12,"c":22}}

    为啥要用深克隆(cloneDeep)就很明显了吧?

    2._.extend_.merge也有深浅的关系!

    _.extend来对配置进行合并,结果……

    let a = {
      aaa: 1,
      bbb: 2,
      ccc: 3,
      object: {
        ddd: 4,
        eee: 5,
        fff: 6,
        sub: {
          ggg: 7,
          hhh: 8,
          iii: 9
        }
      }
    }
    
    let b = {
      ccc: 15,
      bbb: 19,
      kkk: 13,
      object: {
        eee: 26,
        zzz: 32,
        sub: {
          ccc: 19,
          kkk: 26
        }
      }
    }
    console.log(_.extend({}, a, b))
    // >>> {"aaa":1,"bbb":19,"ccc":15,"object":{"eee":26,"zzz":32,"sub":{"ccc":19,"kkk":26}},"kkk":13}
    // object里面的ddd和fff天博体育在线官网都没了?

    如果要保留a的默认值,又要用b等子集去覆盖,建议使用_.merge

    console.log(_.merge({}, a, b))
    // >>> {"aaa":1,"bbb":19,"ccc":15,"object":{"ddd":4,"eee":26,"fff":6,"sub":{"ggg":7,"hhh":8,"iii":9,"ccc":19,"kkk":26},"zzz":32},"kkk":13}
    // 这样才符合我的需求