大体思路(九)
本节内容:
1. $mount 挂载函数的实现。
  

  // 将Vue.prototype.$mount 缓存下来
==>mountComponet(this,el) {
// 组建挂载的时候做的事情
var uodateComponent = function(){
// 1. render返回生产的虚拟节点
// 2. _update 将虚拟节点变为正真的dom
}
// 渲染函数的观察者对象 初识 Watcher undateComponent被观察目标
new Watcher(vm,undateComponent,noop,{},true);
} Vue.prototype.$mount= function(){
el = el && query(el)
if(el === document.body || document.documentElement){
warn('禁止将组件挂载到html 和 body上')
}
options = this.$options
if(!options.render){
template = options.template;
// 自定义渲染函数 把模版编译为渲染函数
if(template){
if(typeof template === 'string'){
if(template.charAt(0) === '#'){
template = idToTemplate(template) }
}
}else if(el){
template = getOuterHTML(el)
}
if(template){
// 解析成渲染函数 编译 AST 虚拟DOM
var res = compileToFuntions(template);
options.render = res.render; // 渲染函数
}
}
return mount.call(this,el)
}
query(el) ===> el === 'string'? doeument.querySelector(el):el
idToTemplate(id){
var el = query(id)
return el && el.innerHTML;
}
getOuterHTML(el){
if(el.outerHTML){
return el.outerHTML
}else{
var con = document.createElement('div');
con.appendChild(el.cloneNode(true));
return con.innerHTML }
}
2. 渲染函数的观察者
3. 初识Watcher
 
vue.js 如下
 //  大体思路(九)
// 本节内容:
// 1. $mount 挂载函数的实现。
// // 将Vue.prototype.$mount 缓存下来
// ==>mountComponet(this,el) {
// // 组建挂载的时候做的事情
// var uodateComponent = function(){
// // 1. render返回生产的虚拟节点
// // 2. _update 将虚拟节点变为正真的dom
// }
// // 渲染函数的观察者对象 初识 Watcher undateComponent被观察目标
// new Watcher(vm,undateComponent,noop,{},true);
// } // Vue.prototype.$mount= function(){
// el = el && query(el)
// if(el === document.body || document.documentElement){
// warn('禁止将组件挂载到html 和 body上')
// }
// options = this.$options
// if(!options.render){
// template = options.template;
// // 自定义渲染函数 把模版编译为渲染函数
// if(template){
// if(typeof template === 'string'){
// if(template.charAt(0) === '#'){
// template = idToTemplate(template) // }
// }
// }else if(el){
// template = getOuterHTML(el)
// }
// if(template){
// // 解析成渲染函数 编译 AST 虚拟DOM
// var res = compileToFuntions(template);
// options.render = res.render; // 渲染函数
// }
// }
// return mount.call(this,el)
// }
// query(el) ===> el === 'string'? doeument.querySelector(el):el
// idToTemplate(id){
// var el = query(id)
// return el && el.innerHTML;
// }
// getOuterHTML(el){
// if(el.outerHTML){
// return el.outerHTML
// }else{
// var con = document.createElement('div');
// con.appendChild(el.cloneNode(true));
// return con.innerHTML // }
// }
// 2. 渲染函数的观察者
// 3. 初识Watcher (function (global, factory) {
// 兼容 cmd
typeof exports === 'object' && module !== 'undefined' ? module.exports = factory() :
// Amd
typeof define === 'function' && define.amd ? define(factory) : global.Vue = factory();
})(this, function () {
var uip = 0; function warn(string) {
console.error('Vue Wran:' + string)
} function warnNonpresent(target, key) {
warn('属性方法' + key + '未在实例对象上定义,渲染功能正在尝试访问这个不存在的属性!')
} function resolveConstructorOptions(Con) {
var options = Con.options;
// 判断是否为vm的实例 或者是子类
return options
}
var hasOwnPropeerty = Object.prototype.hasOwnProperty function hasOwn(obj, key) {
return hasOwnPropeerty.call(obj, key)
} function makeMap(str, expectsLoweraseC) {
if (expectsLoweraseC) {
str = str.toLowerCase()
}
var map = Object.create(null)
var list = str.split(',')
for (var i = 0; i < list.length; i++) {
map[list[i]] = true
}
return function (key) {
return map[key]
}
}
var isbuiltInTag = makeMap('slot,component', true)
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 ASSET_TYPES = [
'component',
'directive',
'filter'
]; var LIFECYCLE_HOOKS = [
'beforeCreate',
'created',
'beforeMount',
'mounted',
'beforeUpdate',
'updated',
'beforeDestroy',
'destroyed',
'activated',
'deactivated',
'errorCaptured'
];
var methods = [
'push',
'pop',
'shift',
'unshift',
'splice',
'sort',
'reverse'
];
var cacheArrProto = Array.prototype
var shell = Object.create(Array.prototype)
methods.forEach(function(method){
var cacheMethod = cacheArrProto[method]
def(shell,method,function(){
var args = []
var len = arguments.length
while(len--) args[len] = arguments[len]
var result = cacheMethod.apply(this,args) // 调用原来的方法
var ob = this.__ob__;
var inserted ;
switch(method){
case 'push' :
case 'unshift':
inserted = args
case 'splice':
inserted = args.slice(2);
}
if(inserted){
ob.observeArray(inserted) // 奖新加入的数组加入到显示系统里面。
}
ob.dep.notify();
return result; //返回数组原来的答案,
})
})
var arrayKeys = Object.getOwnPropertyNames(shell)
var hasProto = '__proto__' in {}
var noop = function () {}
var isReservedTag = function (key) {
return isHTMLTag(key) || isSVG(key)
}
// 检测data的属性名称是否为 _ 或者$ 开始的,这些的话是vue的其他属性的值。
function isReserved(key) {
var c = key.charCodeAt(0)
return c === 0x24 || c === 0x5F
}
// 检查是否为对象
function isObject(val) {
return val !== null && typeof val === 'object'
} function validataComponentName(key) {
//检测component 的自定义名称是否合格
// 只能是字母开头或下划线,必须是字母开头
if (!(/^[a-zA-Z][\w-]*$/g.test(key))) {
warn('组件的名称必须是字母或中横线,必须由字母开头')
}
// 1. 不能为内置对象,2.不能是html ,和avg的内部标签
if (isbuiltInTag(key) || isReservedTag(key)) {
warn('不能为html标签或者avg的内部标签')
}
} function checkComonpents(child) {
for (var key in child.components) {
validataComponentName(key)
}
}
// 配置对象
var config = {
// 自定义的策略
optionMergeStrategies: {}
}
var strats = config.optionMergeStrategies
strats.el = function (parent, child, key, vm) { if (!vm) {
warn('选项' + key + '只能在vue实例用使用')
}
return defaultStrat(parent, child, key, vm)
} function mergeData(to, form) {
// 终极合并
if (!form) {
return to
}
// 具体合并。
} function mergeDataorFn(parentVal, childVal, vm) {
// 合并 parentVal childVal 都是函数
if (!vm) {
if (!childVal) {
return parentVal
}
if (!parentVal) {
return childVal
}
return function mergeDataFn(parentVal, childVal, vm) { //只是一个函数 什么样的情况下调用 加入响应式系统
// 合并子组件对应的data 和 父组件对应的data
return mergeData(
typeof parentVal === 'function' ? parentVal.call(this, this) : parentVal, // -----忘记写
typeof childVal === 'function' ? childVal.call(this, this) : childVal) // -----忘记写
}
} else { // vue实例
return function mergeInstanceDataFn() { //只是一个函数 什么样的情况下调用 加入响应式系统
var InstanceData = typeof childVal === 'function' ? childVal.call(vm, vm) : childVal; // -----忘记写
var defaultData = typeof parentVal === 'function' ? parentVal.call(vm, vm) : parentVal; // -----忘记写
if (InstanceData) {
return mergeData(InstanceData, defaultData)
} else { // -----忘记写
return defaultData
} }
}
}
strats.data = function (parent, child, key, vm) {
if (!vm) {
// console.log(typeof child === 'function')
if (child && !(typeof child === 'function')) {
warn('data必须返回是一个function')
}
return mergeDataorFn(parent, child)
}
return mergeDataorFn(parent, child, vm)
}
// 生命周期策略的合并,值等于一个function 如果是有两个,放到一个数组里面。
function mergeHook(parentVal, childVal, key, vm) {
// console.log(key)
// console.log(parentVal.concat(childVal) )
return childVal ? parentVal ? parentVal.concat(childVal) :
Array.isArray(childVal) ? childVal : [childVal] : parentVal
}
LIFECYCLE_HOOKS.forEach(function (key) {
strats[key] = mergeHook
});
// 检测是否为object
function isPlainObject(obj) {
return Object.prototype.toString.call(obj) === '[object Object]'
} function assetObjectType(obj) {
if (!isPlainObject(obj)) {
warn('选项的值' + obj + '无效:必须是一个对象的')
}
}
// 对parent实现链式调用。
function extend(to, form) {
for (key in form) { to[key] = form[key]
}
return to
}
// 实现Assets 的策略合并 conmponents filter diretive
function mergeAssets(parentVal, childVal, key, vm) {
var parent = Object.create(parentVal || null) // 保证子类的每个值的指向都是一个新的object。否则回出现相互引用的现象。
if (childVal) {
assetObjectType(childVal)
return extend(parent, childVal)
}
return parent
}
ASSET_TYPES.forEach(function (key) {
strats[key + 's'] = mergeAssets
})
// 实现watch的策略和并,将相同的属性放到一个数组里面。
strats.watch = function (parentVal, childVal, key, vm) {
if (!childVal) {
return Object.create(parentVal)
}
var res = {}
res = extend(res, parentVal)
for (var key in childVal) {
var parent = res[key]
var child = childVal[key]
res[key] = parent ? Array.isArray(parent) ? parent.concat(child) : [parent].concat(child) :
Array.isArray(child) ? child : [child];
}
return res
}
// 实现props指令的合并策略
strats.props = function (parentVal, childVal, key, vm) {
if (!childVal) {
return parentVal
}
var res = Object.create(null)
extend(res, parentVal)
if (childVal) {
extend(res, childVal)
}
return res
} function defaultStrat(parent, child, key, vm) {
return child === undefined ? parent : child;
}
var cmalizeRE = /-(\w)/g function camelize(val) {
return val.replace(cmalizeRE, function (c, m) {
return m ? m.toUpperCase() : ""
})
} function normalizeProps(options) {
var props = options.props
if (!props) {
return
}
var i, val, name
var res = {}
if (Array.isArray(props)) {
i = props.length
while (i--) {
val = props[i]
if (toString.call(val) === '[object String]') {
name = camelize(val)
res[name] = {
type: null
}
} else {
warn('使用数组愈发时props成员' + val + '必须时一个数组')
} }
} else if (isPlainObject(props)) {
for (var key in props) {
val = props[key]
name = camelize(key)
res[name] = isPlainObject(val) ? val : {
type: val
}
}
} else {
warn('选项props的值必须是一个对象或者是数组')
}
options.props = res
} function mormalizeDirectives(options) {
var dir = options.directives
var res = {}
if (!dir) {
return
}
if (dir) {
for (var key in dir) {
var val = dir[key]
var name = camelize(key)
if (isPlainObject(val)) {
res[name] = val
}
if (toString.call(val) === '[object Function]') {
res[name] = {
bind: val,
upata: val
}
}
}
}
options.directives = res } function mergeOptions(parent, child, vm) {
var options = {}
// 检测是component 是否是合法的
checkComonpents(child)
// 规范props
normalizeProps(child)
// 规范 dirctives
mormalizeDirectives(child) // console.log(parent, child)
for (key in parent) {
magerField(key)
}
for (key in child) {
if (!hasOwn(parent, key)) { // parent 中循环过地方不进行循环
magerField(key) // ----忘记写
} }
// 默认合并策略
function magerField(key) {
// 自定义策略 默认策略
// console.log(key)
var result = strats[key] || defaultStrat // ---忘记写
options[key] = result(parent[key], child[key], key, vm)
}
// console.log(options)
return options
} var allowedGlobals = makeMap(
'Infinity,undefined,NaN,isFinite,isNaN,' +
'parseFloat,parseInt,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,' +
'Math,Number,Date,Array,Object,Boolean,String,RegExp,Map,Set,JSON,Intl,' +
'require' // for Webpack/Browserify
); function isNative(Ctor) {
return typeof Ctor !== undefined && /native code/.test(toString.call(Ctor))
}
var hasproxy = typeof Proxy !== undefined && isNative(Proxy)
var hasHeadler = {
has: function (target, key) {
var val = key in target
// key 是否是全局对象 或者内置方法 _
var isAllowed = allowedGlobals(key) || (typeof key === 'string' && key.charAt(0) === '_')
if (!val && !isAllowed) {
warnNonpresent(target, key)
}
return val || !isAllowed
}
}
var getHeadler = {
get: function (target, key) {
if (typeof key === 'string' && !(key in target)) {
warnNonpresent(target, key)
}
return target[key]
}
} // 数据代理
function initProxy(vm) {
var options = vm.$options
// 判断是否是es6 是否存在Proxy
if (hasproxy) {
// 渲染函数拦截那些操作。 1. has 查询 2. get 或者
var headler = options.render && options.render._withStripeed ?
getHeadler :
hasHeadler;
vm._renderPorxy = new proxy(vm, headler)
} else {
// 如果不支es6 Proxy
vm._renderPorxy = vm
}
} // 初始化当前实例的$children 和$parent 的指向
function initLifeCycle(vm) {
var options = vm.$options
// 当前组件 父实例
var parent = options.parent // 组件的实例对象
// 是否抽象组件
if (parent && !parent.abstrat) {
while (parent.$options.abstrat && parent.$parent) {
parent = parent.$options.parent
}
parent.$children.push(vm)
}
vm.$parent = parent
vm.$root = parent ? parent.$root : vm; vm.$children = [];
vm.$refs = {}; vm._watcher = null;
vm._inactive = null;
vm._directInactive = false;
vm._isMounted = false; // 是否挂载
vm._isDestroyed = false; // 是否销毁
vm._isBeingDestroyed = false; // 是否正在销毁 } function callHook(vm, hook) {
var options = vm.$options
var obj = options[hook]
if (obj) {
for (var i = 0; i < obj.length; i++) {
obj[i].call(vm)
}
} } function getData(data, vm) {
return data.call(vm, vm)
} //共享的访问器对象
var sharedProperty = {
enumerable: true,
configurable: true,
get: noop,
set: noop
}; function proxy(vm, data, key) { sharedProperty.get = function () {
// console.log("我监听到你访问了我")
return this[data][key]
},
sharedProperty.set = function (newVal) {
console.log("我设置了data的值" + key + "==" + newVal)
this[data][key] = newVal }
Object.defineProperty(vm, key, sharedProperty)
} function initData(vm) {
var opts = vm.$options
var data = vm.$options.data
// 通过之前strats 里面合成好的数据,data是一个function ,为了独立数据调用的空间。拿到data的值。
data = vm._data = typeof data === 'function' ? getData(data, vm) : data || {}
if (!isPlainObject(data)) {
data = {}
warn('data选项应该是object对象')
}
// data methods props 里面属性名称不能相同
var props = opts.props
var methods = opts.methods
for (let key in data) {
if (props && hasOwn(props, key)) {
warn("props " + key + "选项已经定义为data的属性.")
} else if (methods && hasOwn(methods, key)) {
warn("methods: " + key + "选项已经定义为data的属性.")
} else if (!isReserved(key)) {
proxy(vm, "_data", key)
} }
observe(data, true)
}
var shouldObserve = true
var toggleObserving = function (value) {
shouldObserve = value
} function Dep() {
this.subs = []
}
Dep.prototype.addSub = function (sub) {
this.subs.push(sub)
}
Dep.prototype.depend = function () {
console.log("收集依赖"); //Watch 观察者
}
Dep.prototype.notify = function () {
var subs = this.subs.slice()
for (var i = 0; i < subs.length; i++) {
subs[i].updata() // 数据更新的操作 Watch
}
}
Dep.target = null function def(obj, key, val) { // data._ob_ 实例对象 指向 Observer
Object.defineProperty(obj, key, {
value: val,
enumerable: false, //不可枚举
configrable: true
})
} function Observe(value) {
this.value = value;
this.vmCount = 0;
this.dep = new Dep() //回调列表 依赖在什么情况调用
def(value, '_ob_', this)
if(Array.isArray(value)){
var augment = hasProto ? protoAugment : copyAugment ;
augment(value,shell,arrayKeys)
}else{
this.walk(value)
} }
function protoAugment(target,src){
target.__proto__ = src
}
function copyAugment(target,src,keys){
for(var i =0, j=keys.length; i<j; i++){
var key = keys[i];
def(target, key, src[key]);
}
console.log(target)
}
// 加入响应式系统 添加 setter getter
function defindReactive(obj, key, val, shallow) {
var dep = new Dep() // 收集依赖 回调列表
var property = Object.getOwnPropertyDescriptor(obj, key)
var getter = property && property.get
var setter = property && property.set
// getter 和 setter 都不存在。或者都存在则为 true ===》 (!getter || setter)
// console.log((!getter || setter),arguments)
if ((!getter || setter) && arguments.length === 2) {
val = obj[key] // 深度观测
}
var childOb = !shallow && observe(val)
Object.defineProperty(obj, key, {
get: function () {
var value = getter ? getter.call(obj) : val
if (Dep.target) {
dep.depend() // 收集依赖
if (childOb) {
childOb.dep.depend() // 收集依赖
}
}
return value
},
set: function (newVal) {
var value = setter ? setter.call(obj) : val
// is NaN !== NaN
if (newVal === value || (value !== value && newVal !== newVal)) {
return
}
if (setter) {
setter.call(obj, newVal)
} else {
val = newVal
}
console.log('我监听到data变化' + newVal)
// 如果改变的新值为 object 或者Array 就在进行深度检测,递归。
childOb = !shallow && observe(val)
dep.notify() //通知依赖更新
}
})
}
Observe.prototype.walk = function (value) {
var keys = Object.keys(value)
for (var i = 0; i < keys.length; i++) {
defindReactive(value, keys[i])
}
}
Observe.prototype.observeArray = function(items){
items.forEach(function(item){
observe(item)
})
}
// 响应式系统
function observe(value, asRootData) {
var ob
if (!isObject(value)) {
return;
}
if(hasOwn(value,'_ob_') && value._ob_ instanceof Observe){
ob= value._ob_ }else if (shouldObserve && (Array.isArray(value) || isPlainObject(value)) && Object.isExtensible(value) && !value._isVue) {
ob = new Observe(value)
}
if (ob && asRootData) {
ob.vmCount++
} return ob
} function initState(vm) {
var opts = vm.$options
// 初始化props
if (opts.props) {
initProps(vm, opts.props)
}
// 初始化methods
if (opts.methods) {
initMethods(vm, opts.methods)
}
// 初始化computed
if (opts.computed) {
initComputed(vm, opts.computed)
}
// 初始化data 如果存在就initData
if (opts.data) {
initData(vm)
} else {
// 放在响应式系统里面
observe(vm._data = {}, true)
}
} function initMinxin(options) {
Vue.prototype._init = function (options) {
var vm = this
// 记录生成的vue实例对象
vm._uip = uip++ // //-------忘记写
// 是否可扩展
vm.is_Vue = true;
//合并选项
vm.$options = mergeOptions(resolveConstructorOptions(vm.constructor), options, vm)
// // 初始化数值代理
initProxy(vm)
// 初始化当前实例的$children 和$parent 的指向
initLifeCycle(vm)
// 调用beforeCreate 的钩子函数
callHook(vm, 'beforeCreate')
// 初始化数据
initState(vm)
//调用created钩子
callHook(vm,'created')
// 挂载组件
if(vm.$options.el){
vm.$mount(vm.$options.el)
} }
}
// 检查是否为正确的el
function query(el){
if(typeof el === 'string'){
var element = document.querySelector(el)
if(!element){
warn('connet fined element' + el)
}
return element
}else {
return el
}
}
// 输出html的模版
function isToTemplate(el){
var el = el && query(el)
return el && el.innerHTML
}
// 输出html的模版
function getOuterHTML(el){
if(el.outerHTML){
return el.outerHTML
}else {
var dom = document.createElement('div')
dom.appendChild(el.clone(true))
return dom.innerHTML
}
}
// 挂载转体统
function mountComponent(){
// 组建挂载的时候做的事情
var uodateComponent = function(){
// 1. render返回生产的虚拟节点
// 2. _update 将虚拟节点变为正真的dom
}
// 渲染函数的观察者对象 初识 Watcher undateComponent被观察目标
new Watcher(vm,undateComponent,noop,{},true);
}
// 挂载系统
Vue.prototype.$mount = function(el){
var el = el && query(el)
// 挂载组件, 生成虚拟dom 编译为真实dom节点
return mountComponent(this,el)
}
var mount = Vue.prototype.$mount
// 重写了$mount
Vue.prototype.$mount = function(el){
var el = el && query(el)
// console.log(el)
// 不能绑定在body 和html上。
if(el === document.body || el === document.documentElement){
warn('禁止组件挂载在html 或者body上')
}
var options = this.$options
// 自定义渲染函数 把模版编译为渲染函数
if(!options.render){
var template = options.template
if(template){
if(typeof template === 'string' && template.charAt(0) === "#"){
template = isToTemplate(template)
}
}else if(el){
template = getOuterHTML(el)
}
if(template){
//解析成渲染函数 编译 AST 虚拟DOM var res = compileToFunctions(template)
this.render = res.render //渲染函数
}
}
return mount.call(this.el)
}
function Vue(options) {
// 安全机制
if (!(this instanceof Vue)) { //-------忘记写
warn('Vue是一个构造函数,必须是由new关键字调用')
}
this._init(options)
}
initMinxin() // 初始化选项1: 规范 2: 合并策略。
Vue.options = {
components: {
transtions: {},
keepAlive: {},
solt: {},
transtionsGroup: {}
},
directives: {},
_bash: Vue
} function initExend(Vue) {
Vue.extend = function (extendOptions) {
extendOptions = extendOptions || {} // -----忘记写
var Super = this
var Child = function VueComponent(options) {
this._init(options)
}
Child.prototype = Object.create(Super.prototype)
Child.prototype.constructor = Child // 改变constructor 的指向
Child.options = mergeOptions(Super.options, extendOptions)
// 子类继承父类的静态方法。
Child.extend = Vue.extend
// console.log(new Child({}))
return Child
}
}
initExend(Vue)
return Vue
})

html代码如下

 <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>第九课</title>
</head>
<body>
<div id="app">
<!-- <huml></huml> --> </div>
<script src="vue.js"></script>
<!-- <script src="vue2.5.1.js"></script> -->
<script type="text/javascript">
var componentA = {
el: "#app"
}
var vm = new Vue({
el:"#app",
data: {
message: "hello Vue",
key: "wodow",
test: 1, list: {
b:1
},
aa:{
b: [1,2,3]
}
},
beforeCreate: function(){
console.log('我钩子函数beforeCreate') },
mounted: function(){
this.url = 'eeeee'
},
components:{
humle: componentA
}
})
vm.test = 2;
// console.log(vm.aa)
</script>
</body>
</html>

【js】vue 2.5.1 源码学习 (十) $mount 挂载函数的实现的更多相关文章

  1. 如何实现全屏遮罩(附Vue.extend和el-message源码学习)

    [Vue]如何实现全屏遮罩(附Vue.extend和el-message源码学习) 在做个人项目的时候需要做一个类似于电子相册浏览的控件,实现过程中首先要实现全局遮罩,结合自己的思路并阅读了(饿了么) ...

  2. 【js】 vue 2.5.1 源码学习(五) props directives规范化 props 合并策略

    大体思路 (四) 上节回顾: A: 对于生命周期函数将父子组件的函数放到一个数组里面,特定时间点调用,保证父子组件函数都调用到. B: 对于directive,filters,components 等 ...

  3. 【js】vue 2.5.1 源码学习 (四) 钩子函数 资源选项 watch 的合并策略

    大体思路 (三)    1.钩子函数 自定义策略       LIFECYCLE_HOOKS= []      created = [function(){} , function(){}] 组装方法 ...

  4. 【js】vue 2.5.1 源码学习 (三) Vue.extend 和 data的合并策略

    大体思路 (三)  1. 子类父类  2.Vue.extend()      //创建vue的子类 组件的语法器 Vue.extend(options) Profile().$mount('#app' ...

  5. 【js】 vue 2.5.1 源码学习(十二)模板编译

    大体思路(十) 本节内容: 1. baseoptions 参数分析 2. options 参数分析 3. parse 编译器 4. parseHTNL 函数解析 // parse 解析 parser- ...

  6. 【js】 vue 2.5.1 源码学习(六) initProxy initLifeCycle 渲染函数的作用域代理

    大体思路 (五) 1. initProxy 渲染函数的作用域代理 ==> es6 如果支持proxy (hasProxy) 就用proxy 不支持就用 defineProperty() prox ...

  7. 【 js 性能优化】【源码学习】underscore throttle 与 debounce 节流

    在看 underscore.js 源码的时候,接触到了这样两个方法,很有意思: 我先把实现的代码撂在下面,看不懂的可以先跳过,但是跳过可不是永远跳过哦- 一个是 throttle: _.throttl ...

  8. vue系列---Mustache.js模板引擎介绍及源码解析(十)

    mustache.js(3.0.0版本) 是一个javascript前端模板引擎.官方文档(https://github.com/janl/mustache.js) 根据官方介绍:Mustache可以 ...

  9. [Go语言]从Docker源码学习Go——结构和函数的定义

    Docker在最近很火,而作为Docker的开发语言-Go也再次被大家提到. 已经使用Docker一段时间了,但是对于源码,尤其是其开发语言Go却一直是一知半解. 最近准备利用空余时间从Docker源 ...

随机推荐

  1. PLUTO平台是由美林数据技术股份有限公司下属西安交大美林数据挖掘研究中心自主研发的一款基于云计算技术架构的数据挖掘产品,产品设计严格遵循国际数据挖掘标准CRISP-DM(跨行业数据挖掘过程标准),具备完备的数据准备、模型构建、模型评估、模型管理、海量数据处理和高纬数据可视化分析能力。

    http://www.meritdata.com.cn/article/90 PLUTO平台是由美林数据技术股份有限公司下属西安交大美林数据挖掘研究中心自主研发的一款基于云计算技术架构的数据挖掘产品, ...

  2. python控制台输出带颜色文字的方法

    目地:提高重要信息的可读性,方便用户阅读了. 书写格式如下: #格式: 设置颜色开始 :\033[显示方式;前景色;背景色m #说明: 前景色 背景色 颜色 --------------------- ...

  3. Contacts源码分析(一、概述)

    代码版本: Contact code version: 4.4.2 一 打开Log开关:如if (Log.isLoggable(Constants.PERFORMANCE_TAG, Log.DEBUG ...

  4. 使用哈工大LTP进行文本命名实体识别并保存到txt

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明.本文链接:https://blog.csdn.net/broccoli2/article/det ...

  5. 你在用 JWT 代替 Session?

    现在,JSON Web Tokens (JWT) 是非常流行的.尤其是 Web 开发领域. 流行 安全 稳定 易用 支持 JSON 所有这些因素,令 JWT 名声大振. 但是,今天我要来说说使用 JW ...

  6. sql —— top

    用于规定要返回的记录的数目 原表: 我们如果只想看前三个学生信息的话:

  7. js+canvas制作前端验证码

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  8. notepad++最有用的快捷键

    Ctrl+Tab  实现在多个打开的窗口间切换 Ctrl+Shift+Q 区块注释 Ctrl+K  行注释 Tab 缩进 Shift+Tab 删除缩进 先按住键盘上的“ctrl”键不放,然后滚动鼠标的 ...

  9. SDUT-2134_数据结构实验之栈与队列四:括号匹配

    数据结构实验之栈与队列四:括号匹配 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 给你一串字符,不超过50个字符,可能 ...

  10. python 实现A*算法

    A*作为最常用的路径搜索算法,值得我们去深刻的研究.路径规划项目.先看一下维基百科给的算法解释:https://en.wikipedia.org/wiki/A*_search_algorithm A ...