博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Vue 源码中的一些辅助函数
阅读量:2198 次
发布时间:2019-05-03

本文共 6117 字,大约阅读时间需要 20 分钟。

在回顾Vue源码的时候,经常看到Vue中一些辅助函数,总结一些日常中会用到的,和一些js代码片段

Vue 源码中的一些辅助函数

是否定义

function isDef (v){ return v !== undefined && v !== null}

已经定义的值判断是否是原始类型

function isPrimitive (value){ return ( typeof value === 'string' || typeof value === 'number' || typeof value === 'symbol' || typeof value === 'boolean' )}

是否是 promise 类型

`function isPromise (val){ return ( isDef(val) && typeof val.then === 'function' && typeof val.catch === 'function' )} ### 转换为数字 `// 将输入值转换为数字。如果转换失败,则返回原始字符串。 function toNumber (val){ const n = parseFloat(val) return isNaN(n) ? val : n} ### 创建一个 map,返回一个函数去检测一个 key 值是否存在与这个 map `function makeMap ( str, expectsLowerCase){ const map = Object.create(null) const list = str.split(',') for (let i = 0; i < list.length; i++) { map[list[i]] = true } return expectsLowerCase ? val => map[val.toLowerCase()] : val => map[val]} vue 源码中的使用var isHTMLTag = makeMap( 'html,body,base,head,link,meta,style,title,' + 'address,article,aside,footer,header,h1,h2,h3,h4,h5,h6,hgroup,nav,section,' + 'div,dd,dl,dt,figcaption,figure,picture,hr,img,li,main,ol,p,pre,ul,' + 'a,b,abbr,bdi,bdo,br,cite,code,data,dfn,em,i,kbd,mark,q,rp,rt,rtc,ruby,' + 's,samp,small,span,strong,sub,sup,time,u,var,wbr,area,audio,map,track,video,' + 'embed,object,param,source,canvas,script,noscript,del,ins,' + 'caption,col,colgroup,table,thead,tbody,td,th,tr,' + 'button,datalist,fieldset,form,input,label,legend,meter,optgroup,option,' + 'output,progress,select,textarea,' + 'details,dialog,menu,menuitem,summary,' + 'content,element,shadow,template,blockquote,iframe,tfoot'); var isSVG = makeMap( 'svg,animate,circle,clippath,cursor,defs,desc,ellipse,filter,font-face,' + 'foreignObject,g,glyph,image,line,marker,mask,missing-glyph,path,pattern,' + 'polygon,polyline,rect,switch,symbol,text,textpath,tspan,use,view', true); var isReservedTag = function (tag) { return isHTMLTag(tag) || isSVG(tag)};var isBuiltInTag = makeMap('slot,component', true) function validateComponentName (name) { if (!new RegExp(("^[a-zA-Z][\\-\\.0-9_" + (unicoderegexp.source) + "]\*\$")).test(name)) { warn( 'Invalid component name: "' + name + '". Component names ' + 'should conform to valid custom element name in html5 specification.' ); } if (isBuiltInTag(name) || config.isReservedTag(name)) { warn( 'Do not use built-in or reserved HTML elements as component ' + 'id: ' + name ); }} ### 从数组中移除一项 `function remove (arr, item){if (arr.length) { const index = arr.indexOf(item) if (index > -1) { return arr.splice(index, 1) } }}vue 源码中的使用Dep.prototype.removeSub = function removeSub (sub) { remove(this.subs, sub);}; ### 转换一个类数组为真实数组 `function toArray (list, start){ start = start || 0 let i = list.length - start const ret = new Array(i) while (i--) { ret[i] = list[i + start] } return ret}vue 源码中的使用Vue.prototype.$emit = function (event) { const vm = this; ... let cbs = vm._events[event]; if (cbs) { cbs = cbs.length > 1 ? toArray(cbs) : cbs; const args = toArray(arguments, 1); ... } return vm}; ### 将属性混合到目标对象中 `function extend (to, _from): Object { for (const key in _from) { to[key] = _from[key] } return to} ### 将对象数组合并为单个对象 `function toObject (arr) { var res = {}; for (var i = 0; i < arr.length; i++) { if (arr[i]) { extend(res, arr[i]); } } return res } vue 源码中的使用 function updateStyle (oldVnode: VNodeWithData, vnode: VNodeWithData) { ... if (Array.isArray(style)) { style = vnode.data.style = toObject(style) }} ### 确保一个函数仅被调用一次 `function once (fn) { var called = false; return function () { if (!called) { called = true; fn.apply(this, arguments); } }}vue 源码中的使用const reject = once(reason => { warn( `Failed to resolve async component: ${String(factory)}` + (reason ? `\nReason: ${reason}` : '') ); if (isDef(factory.errorComp)) { factory.error = true; forceRender(true); }}); `定义一个属性function def (obj, key, val, enumerable) { Object.defineProperty(obj, key, { value: val, enumerable: !!enumerable, writable: true, configurable: true });} 通过使用__proto__的原型链拦截来增强目标对象或数组 function protoAugment (target, src) { target.__proto__ = src;}通过定义来增强目标对象或数组隐藏的属性。function copyAugment (target, src, keys) { for (var i = 0, l = keys.length; i < l; i++) { var key = keys[i]; def(target, key, src[key]); }}vue 源码中的使用export class Observer { value: any; dep: Dep; vmCount: number; constructor (value: any) { this.value = value this.dep = new Dep() this.vmCount = 0 def(value, '__ob__', this) if (Array.isArray(value)) { if (hasProto) { protoAugment(value, arrayMethods) } else { copyAugment(value, arrayMethods, arrayKeys) } this.observeArray(value) } else { this.walk(value) } } ...} ## 日常使用的js代码片段### 取数组相同项(不同项同理取不包含)选择一个数组创建  Set,然后使用  Array.filter()  过滤 Set 中包含的另一个数组值 `const intersection = (ary1, ary2) => { const s = new Set(ary2); return ary1.filter(item => s.has(item)) };//如果确定数组中不会有重复部分const intersection = (ary1, ary2) => ary1.filter(v => ary2.includes(v));// intersection([32,43,543], [32,12,55,43]) -> [32,43] ### 统计数组中出现指定值的次数用 reduce 查询数组,符合条件时+1 `const countOccurrences = (ary, value) => ary.reduce((res, val) => val === value ? ++res : res + 0, 0);//countOccurrences([2,4,11,'a','a','b',32], 'a') -> 2 ### 扁平化数组(扁平所有)递归数组,reduce 展开数组并合并 `const deepFlatten = arr => arr.reduce((a, v) => a.concat(Array.isArray(v) ? deepFlatten(v) : v), []);// deepFlatten(['a',['b'],[['c'],'d']]) -> ['a','b','c','d']//如果所要展开的只有一层 可以直接使用 es6 的 Array.flat(),且只能展开一层['a',['b'],['c'],'d'].flat() -> ['a','b','c','d']'a',['b'],[['c'],'d']].flat() -> ["a", "b", ['c'], "d"] ### 扁平化指定深度的数组在上一个的基础上改造一下,增加一个深度参数 `const flattenDepth = (ary, depth = 1) =>depth != 1 ? ary.reduce((a, v) => a.concat(Array.isArray(v) ? flattenDepth(v, depth - 1) : v), []): ary.flat();// flattenDepth(['a','b',['c'],[['d','e',['f'] ]]], 2) ->  ["a", "b", "c", "d", "e", ['f']] ### 滚动到顶部 `const scrollToTop = _ => {const c = document.documentElement.scrollTop || document.body.scrollTop; //获取到顶端的距离if (c > 0) { window.requestAnimationFrame(scrollToTop);//滚动动画效果 window.scrollTo(0, c - c / 8);}}; ### 取两个日期之间相差的天数 `const getDaysDiffBetweenDates = (beginDate, endDate) => ( endDate - beginDate) / (1000 _ 3600 _ 24);// getDaysDiffBetweenDates(new Date("2020-09-22"), new Date("2020-10-01")) -> 9

转载地址:http://vuqub.baihongyu.com/

你可能感兴趣的文章
【学习方法】如何分析源代码
查看>>
【LEETCODE】61- Rotate List [Python]
查看>>
【LEETCODE】82- Remove Duplicates from Sorted List II [Python]
查看>>
【LEETCODE】86- Partition List [Python]
查看>>
【LEETCODE】147- Insertion Sort List [Python]
查看>>
【算法】- 动态规划的编织艺术
查看>>
用 TensorFlow 让你的机器人唱首原创给你听
查看>>
对比学习用 Keras 搭建 CNN RNN 等常用神经网络
查看>>
深度学习的主要应用举例
查看>>
word2vec 模型思想和代码实现
查看>>
怎样做情感分析
查看>>
用深度神经网络处理NER命名实体识别问题
查看>>
用 RNN 训练语言模型生成文本
查看>>
RNN与机器翻译
查看>>
用 Recursive Neural Networks 得到分析树
查看>>
RNN的高级应用
查看>>
TensorFlow-7-TensorBoard Embedding可视化
查看>>
轻松看懂机器学习十大常用算法
查看>>
一个框架解决几乎所有机器学习问题
查看>>
特征工程怎么做
查看>>