本文主要探讨一下,Vue的beforeCreate和created阶段一个大致运行流程,我们知道,它的生命周期包括,beforeCreate,created,beforeMount,mounted,beforeUpdate,updated,beforeDestroy,destroyed。出于简单起见,这里暂时讨论只讨论beforeCreate,created阶段
本次探究所用的代码如下,vue版本为v2.5.17-beta.0
:
<!--html模板-->
<div id="box">
<ul>
<li v-for="item in data" @click="logChange(item.NAME,item.AGE)">
{
{item.NAME}}
</li>
</ul>
</div>
//js
new Vue({
el: '#box',
data: {
data:[
{
NAME:'SDF',AGE:3},
{
NAME:'JIKU',AGE:6},
{
NAME:'HYF',AGE:3}
]
},
methods: {
logChange: function(name,age) {
console.log(name,age);
}
}
});
一、beforeCreate阶段
这个阶段主要是完成vue中关于生成周期以及事件的一些初始化工作,在这之前它会执行一个mergeOptions
函数,得到$options
选项,并把它设置成Vue实例的一个属性。
1.1、生成$options
选项
//vm为Vue实例
vm.$options = mergeOptions(
resolveConstructorOptions(vm.constructor),
options || {
},
vm
);
这个函数首先是检查我们的一个组件名称是否合法,它会执行如下代码片段:
//name是传入的组件名称
if (!/^[a-zA-Z][\w-]*$/.test(name)) {
warn(
'Invalid component name: "' + name + '". Component names ' +
'can only contain alphanumeric characters and the hyphen, ' +
'and must start with a letter.'
);
}
if (isBuiltInTag(name) || config.isReservedTag(name)) {
warn(
'Do not use built-in or reserved HTML elements as component ' +
'id: ' + name
);
}
从这里我们可以看出,一个合法的组件名应该是必须是以字母开头,并且中间可以加一个或多个横线连接,但vue中内置的一些标签名如'slot,component'
以及常规的html不能用作组件名,这个标签如下;一种是标准的html,还有就是svg标签。
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'
);
// this map is intentionally selective, only covering SVG elements that may
// contain child elements.
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
);
1.2、对传入的选项做合并处理
该过程会执行mergeField
方法。
function mergeField (key) {
var strat = strats[key] || defaultStrat;
options[key] = strat(parent[key], child[key], vm, key);
}
这个方法里面,它是根据我们传入的选项对象的键名来确定一个“策略函数”,然后将相关的键值传入该函数,最后得到$options
对象的一个属性信息(即生成键值对)。其中parent值的信息如下图
以components
键为例,它对应的“策略函数”,mergeAssets
函数
function mergeAssets (
parentVal,
childVal,
vm,
key
) {
var res = Object.create(parentVal || null);
if (childVal) {
"development" !== 'production' && assertObjectType(key, childVal, vm);
return extend(res, childVal)
} else {
return res
}