145  
查询码:00001071
vue(基于2.X)源码分析(一)
作者: 朱凡 于 2020年05月02日 发布在分类 / FM组 / FM_App 下,并于 2020年05月02日 编辑

vue(基于2.X)源码分析(一)

内容:vue选项规范化;vue选项合并策略

注:下面的代码是自定义,非官方源码,仅供参考,不可放到项目上使用,5月中旬将补充源码注释

(function(global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global.Vue = factory());
})(this, function() {
var warn = function(msg) {
console.error("[Vue Warn]: " + msg);
}
var hasOwnProperty = Object.prototype.hasOwnProperty;
var hasOwn = function(obj, key) {
hasOwnProperty.call(obj, key);
}
var uid = 0;
function resolveConstructorOptions(Con) {
var options = Con.options;
/*
判断  Con.super   ==  Vue
*/
return options;
}
/**
* 检测组件名的规范
* @param {Object} options
*/
function checkComponents(options) {
//循环遍历当前options的components
for (var key in options.components) {
//检测组件的名字
validataComponentName(key);
}
}
//检测key 是否在makeMap
function makeMap(str, toLowerCase) {
var map = {};
var list = str.split(","); //["slot","component"]
for (var i = 0; i < list.length; i++) {
map[list[i]] = true;
}
return toLowerCase ? function(val) {
return map[val.toLowerCase()];
} : function(val) {
return map[val];
}
}
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 config = {
//自定义的策略
optionMergeStrategies: {}
}
var strats = config.optionMergeStrategies;
strats.el = function(parent, child, vm, key) {
if (!vm) {
warn("选项" + key + "只能Vue在实例中使用");
}
return defaultStrat(parent, child);
}
//内置标签
var isbuiltInTag = makeMap("slot,component", true);
var isReservedTag = function(tag) {
return isSVG(tag) || isHTMLTag(tag);
}
function defaultStrat(parent, child) {
return child === undefined ? parent : child;
}
/**
* 检测组件的名称
* @param {Object} key
*/
function validataComponentName(key) {
//1:不能使用Vue内置标签 slot  component  2:  不能使用html || svg属性名称 
//2: 规范组件的名称必须是由字母或中横线组成, 且必须是由字母开头
if (!/^[a-zA-Z][\w-]*$/.test(key)) {
warn("组件的名称必须是由字母或中横线组成, 且必须是由字母开头");
}
//isbuiltInTag:内置组件元素,isReservedTag:svg元素
if (isbuiltInTag(key) || isReservedTag(key)) {
warn("不要把内置组件或者保留的html ||svg 元素作为组件的id: " + key);
}
}
//选项合并     一个或者多个对象合并并且生成一个新的对象
/**
* @param {Object} parent  vue的option的option对象
* @param {Object} child 用户自定义的option对象
* @param {Object} vm 当前vue对象
*/
function mergeOptions(parent, child, vm) {
/**
* 规范的检测   
* components 组件的规范
* props 属性的规范
* inject  传值的规范
* directives指令的规范
*/
checkComponents(child);
var options = {};
var key;
for (key in parent) {
mergeField(key); //components  directives  _base
}
//监测parent中是否有这个属性
for (key in child) { //自定义的选项配置
if (!hasOwn(parent, key)) {
mergeField(key); //components el data  name
}
}
//默认策略
function mergeField(key) {
//默认策略  自定义的策略
var result = strats[key] || defaultStrat;
options[key] = result(parent[key], child[key], vm, key);
}
console.log(options)
return options;
}
function initMixin(Vue) {
Vue.prototype._init = function(options) {
var vm = this;
//有多少个Vue的实例对象
vm._uid = uid++;
//Vue.options   传入的options对象合并
mergeOptions(resolveConstructorOptions(vm.constructor), options, vm);
}
}
function Vue(options) {
//安全机制
if (!(this instanceof Vue)) {
warn("Vue是一个构造函数 应该用new关键字调用")
}
this._init(options); //初始化
}
initMixin(Vue); //  初始化选项:  1:规范 2:合并策略
//全局API
Vue.options = {
components: {},
directives: {},
_base: Vue
}
return Vue;
});




 推荐知识

 历史版本

修改日期 修改人 备注
2020-05-02 10:22:30[当前版本] 朱凡 创建版本

  目录
    知识分享平台 -V 4.8.7 -wcp