广告
返回顶部
首页 > 资讯 > 前端开发 > VUE >vue parseHTML函数源码解析start钩子函数
  • 937
分享到

vue parseHTML函数源码解析start钩子函数

2024-04-02 19:04:59 937人浏览 薄情痞子
摘要

目录正文platfORMGetTagNamespace 源码 isForbiddenTag 函数addIfCondition是什么processIfConditions 源

目录
  • 正文
    • platfORMGetTagNamespace 源码
    •  isForbiddenTag 函数
    • addIfCondition是什么
    • processIfConditions 源码

正文

接上章节:parsehtml 函数源码解析 AST 预备知识

现在我们就可以愉快的进入到Vue start钩子函数源码部分了。

start: function start(tag, attrs, unary) {
	// check namespace.
	// inherit parent ns if there is one
	var ns = (currentParent && currentParent.ns) || platformGetTagNamespace(tag);
	// handle IE svg bug
	
	if (isIE && ns === 'svg') {
		attrs = guardIESVGBug(attrs);
	}
	var element = createASTElement(tag, attrs, currentParent);
	if (ns) {
		element.ns = ns;
	}
	if (isForbiddenTag(element) && !isServerRendering()) {
		element.forbidden = true;
		warn$2(
			'Templates should only be responsible for mapping the state to the ' +
			'UI. Avoid placing tags with side-effects in your templates, such as ' +
			"<" + tag + ">" + ', as they will not be parsed.'
		);
	}
	// apply pre-transforms
	for (var i = 0; i < preTransforms.length; i++) {
		element = preTransforms[i](element, options) || element;
	}
	if (!inVPre) {
		processPre(element);
		if (element.pre) {
			inVPre = true;
		}
	}
	if (platformIsPreTag(element.tag)) {
		inPre = true;
	}
	if (inVPre) {
		processRawAttrs(element);
	} else if (!element.processed) {
		// structural directives
		processFor(element);
		processIf(element);
		processOnce(element);
		// element-scope stuff
		processElement(element, options);
	}
	function checkRootConstraints(el) {
		{
			if (el.tag === 'slot' || el.tag === 'template') {
				warnOnce(
					"Cannot use <" + (el.tag) + "> as component root element because it may " +
					'contain multiple nodes.'
				);
			}
			if (el.attrsMap.hasOwnProperty('v-for')) {
				warnOnce(
					'Cannot use v-for on stateful component root element because ' +
					'it renders multiple elements.'
				);
			}
		}
	}
	// tree management
	if (!root) {
		root = element;
		checkRootConstraints(root);
	} else if (!stack.length) {
		// allow root elements with v-if, v-else-if and v-else
		if (root.if && (element.elseif || element.else)) {
			checkRootConstraints(element);
			addIfCondition(root, {
				exp: element.elseif,
				block: element
			});
		} else {
			warnOnce(
				"Component template should contain exactly one root element. " +
				"If you are using v-if on multiple elements, " +
				"use v-else-if to chain them instead."
			);
		}
	}
	if (currentParent && !element.forbidden) {
		if (element.elseif || element.else) {
			processIfConditions(element, currentParent);
		} else if (element.slotScope) { // scoped slot
			currentParent.plain = false;
			var name = element.slotTarget || '"default"';
			(currentParent.scopedSlots || (currentParent.scopedSlots = {}))[name] = element;
		} else {
			currentParent.children.push(element);
			element.parent = currentParent;
		}
	}
	if (!unary) {
		currentParent = element;
		stack.push(element);
	} else {
		closeElement(element);
	}
}

如上代码start 钩子函数接受三个参数,这三个参数分别是标签名字 tag,该标签的属性数组attrs,以及代表着该标签是否是一元标签的标识 unary。

接下来别害怕看不懂,我们一点点来分析它函数体中的代码。

var ns = (currentParent && currentParent.ns) || platformGetTagNamespace(tag);

开头定义了 ns 变量,它的值为标签的命名空间,如何获取当前元素的命名空间呢?首先检测currentParent 变量是否存在,我们知道 currentParent 变量为当前元素的父级元素描述对象,如果当前元素存在父级并且父级元素存在命名空间,则使用父级的命名空间作为当前元素的命名空间。

如果父级元素不存在或父级元素没有命名空间那么会调用platformGetTagNamespace函数,platformGetTagNamespace 函数只会获取 svg 和 math 这两个标签的命名空间,但这两个标签的所有子标签都会继承它们两个的命名空间。

platformGetTagNamespace 源码

function getTagNamespace(tag) {
	if (isSVG(tag)) {
		return "svg"
	}
	if (tag === "math") {
		return "math"
	}
}

接下来源码:

if (isIE && ns === "svg") {
	attrs = guardIESVGBug(attrs);
}

这里通过isIE来判断宿主环境是不是IE浏览器,并且前元素的命名空间为svg, 如果是通过guardIESVGBug处理当前元素的属性数组attrs,并使用处理后的结果重新赋值给attrs变量,该问题是svg标签中渲染多余的属性,如下svg标签:

<svg xmlns:feature="Http://www.openplans.org/topp"></svg>

被渲染为:

<svg xmlns:NS1="" NS1:xmlns:feature="http://www.openplans.org/topp"></svg>

标签中多了 'xmlns:NS1="" NS1:' 这段字符串,解决办法也很简单,将整个多余的字符串去掉即可。而 guardIESVGBug 函数就是用来修改NS1:xmlns:feature属性并移除xmlns:NS1="" 属性的。

接下来源码:

var element = createASTElement(tag, attrs, currentParent);
if (ns) {
	element.ns = ns;
}

在上章节聊过,createASTElement 它将生成当前标签的元素描述对象并且赋值给 element 变量。紧接着检查当前元素是否存在命名空间 ns ,如果存在则在元素对象上添加 ns 属性,其值为命名空间的值。

接下来源码:

if (isForbiddenTag(element) && !isServerRendering()) {
	element.forbidden = true;
	warn$2(
		'Templates should only be responsible for mapping the state to the ' +
		'UI. Avoid placing tags with side-effects in your templates, such as ' +
		"<" + tag + ">" + ', as they will not be parsed.'
	);
}

这里的作用就是判断在非服务端渲染情况下,当前解析的开始标签是否是禁止在模板中使用的标签。哪些是禁止的呢?

 isForbiddenTag 函数

function isForbiddenTag(el) {
	return (
		el.tag === 'style' ||
		(el.tag === 'script' &amp;&amp; (
			!el.attrsMap.type ||
			el.attrsMap.type === 'text/javascript'
		))
	)
}

可以看到,style,script 都是在禁止名单中,但通过isForbiddenTag 也发现一个彩蛋。

<script type="text/x-template" id="hello-world-template">
  <p>Hello hello hello</p>
</script>

当定义模板的方式如上,在 <script> 元素上添加 type="text/x-template" 属性。 此时的script不会被禁止。

最后还会在当前元素的描述对象上添加 element.forbidden 属性,并将其值设置为true。

接下来源码:

for (var i = 0; i < preTransforms.length; i++) {
	element = preTransforms[i](element, options) || element;
}

如上代码中使用 for 循环遍历了preTransforms 数组,preTransforms 是通过pluckModuleFunction 函数从options.modules 选项中筛选出名字为preTransformNode 函数所组成的数组。实际上 preTransforms 数组中只有一个 preTransformNode 函数该函数只用来处理 input 标签我们在后面章节会来讲它。

接下来源码:

if (!inVPre) {
	processPre(element);
	if (element.pre) {
		inVPre = true;
	}
}
if (platformIsPreTag(element.tag)) {
	inPre = true;
}
if (inVPre) {
	processRawAttrs(element);
} else if (!element.processed) {
	// structural directives
	processFor(element);
	processIf(element);
	processOnce(element);
	// element-scope stuff
	processElement(element, options);
}

可以看到这里会有大量的process*的函数,这些函数是做什么用的呢?实际上process* 系列函数的作用就是对元素描述对象做进一步处理,比如其中一个函数叫做 processPre,这个函数的作用就是用来检测元素是否拥有v-pre 属性,如果有v-pre 属性则会在 element 描述对象上添加一个 pre 属性,如下:

{
  type: 1,
  tag,
  attrsList: attrs,
  attrsMap: makeAttrsMap(attrs),
  parent,
  children: [],
  pre: true
}

总结:所有process* 系列函数的作用都是为了让一个元素的描述对象更加充实,使这个对象能更加详细地描述一个元素, 不过我们本节主要总结解析一个开始标签需要做的事情,所以稍后去看这些代码的实现。

接下来源码:

function checkRootConstraints(el) {
	{
		if (el.tag === 'slot' || el.tag === 'template') {
			warnOnce(
				"Cannot use <" + (el.tag) + "> as component root element because it may " +
				'contain multiple nodes.'
			);
		}
		if (el.attrsMap.hasOwnProperty('v-for')) {
			warnOnce(
				'Cannot use v-for on stateful component root element because ' +
				'it renders multiple elements.'
			);
		}
	}
}

我们知道在编写 Vue 模板的时候会受到两种约束,首先模板必须有且仅有一个被渲染的根元素,第二不能使用 slot 标签和 template 标签作为模板的根元素。

checkRootConstraints 函数内部首先通过判断 el.tag === 'slot' || el.tag === 'template' 来判断根元素是否是slot 标签或 template 标签,如果是则打印警告信息。接着又判断当前元素是否使用了 v-for 指令,因为v-for 指令会渲染多个节点所以根元素是不允许使用 v-for 指令的。

接下来源码:

if (!root) {
	root = element;
	checkRootConstraints(root);
} else if (!stack.length) {
	// allow root elements with v-if, v-else-if and v-else
	if (root.if &amp;&amp; (element.elseif || element.else)) {
		checkRootConstraints(element);
		addIfCondition(root, {
			exp: element.elseif,
			block: element
		});
	} else {
		warnOnce(
			"Component template should contain exactly one root element. " +
			"If you are using v-if on multiple elements, " +
			"use v-else-if to chain them instead."
		);
	}
}

这个 if 语句先检测 root 是否存在!我们知道 root 变量在一开始是不存在的,如果 root 不存在那说明当前元素应该就是根元素,所以在 if 语句块内直接把当前元素的描述对象 element 赋值给 root 变量,同时会调用 checkRootConstraints函数检查根元素是否符合要求。

再来看 else if 语句的条件,当 stack 为空的情况下会执行 else if 语句块内的代码, 那stack 什么情况下才为空呢?前面已经多次提到每当遇到一个非一元标签时就会将该标签的描述对象放进数组,并且每当遇到一个结束标签时都会将该标签的描述对象从 stack 数组中拿掉,那也就是说在只有一个根元素的情况下,正常解析完成一段 html 代码后 stack 数组应该为空,或者换个说法,即当 stack 数组被清空后则说明整个模板字符串已经解析完毕了,但此时 start 钩子函数仍然被调用了,这说明模板中存在多个根元素,这时 else if 语句块内的代码将被执行:

接下来源码:

if (root.if &amp;&amp; (element.elseif || element.else)) {
	checkRootConstraints(element);
	addIfCondition(root, {
		exp: element.elseif,
		block: element
	});
} else {
	warnOnce(
		"Component template should contain exactly one root element. " +
		"If you are using v-if on multiple elements, " +
		"use v-else-if to chain them instead."
	);
}

想要能看懂这个代码,你需要懂一些前置知识。

[ Vue条件渲染 ] (https://cn.vuejs.org/v2/guide/conditional.html)

我们知道在编写 Vue 模板时的约束是必须有且仅有一个被渲染的根元素,但你可以定义多个根元素,只要能够保证最终只渲染其中一个元素即可,能够达到这个目的的方式只有一种,那就是在多个根元素之间使用 v-if 或 v-else-if 或 v-else 。

示例代码:

<div v-if="type === 'A'">
  A
</div>
<div v-else-if="type === 'B'">
  B
</div>
<div v-else-if="type === 'C'">
  C
</div>
<div v-else>
  Not A/B/C
</div>

在回归到代码部分。

if (root.if && (element.elseif || element.else))

root 对象中的 .if 属性、.elseif 属性以及 .else 属性都是哪里来的,它们是在通过 processIf 函数处理元素描述对象时,如果发现元素的属性中有 v-if 或 v-else-if 或 v-else ,则会在元素描述对象上添加相应的属性作为标识。

上面代码如果第一个根元素上有 .if 的属性,而非第一个根元素 element 有 .elseif 属性或者 .else 属性,这说明根元素都是由 v-if、v-else-if、v-else 指令控制的,同时也保证了被渲染的根元素只有一个。

接下来继续看:

if (root.if && (element.elseif || element.else)) {
	checkRootConstraints(element);
	addIfCondition(root, {
		exp: element.elseif,
		block: element
	});
} else {
	warnOnce(
		"Component template should contain exactly one root element. " +
		"If you are using v-if on multiple elements, " +
		"use v-else-if to chain them instead."
	);
}

checkRootConstraints 函数检查当前元素是否符合作为根元素的要求,这都能理解。

addIfCondition是什么

看下它的源代码。

function addIfCondition(el, condition) {
	if (!el.ifConditions) {
		el.ifConditions = [];
	}
	el.ifConditions.push(condition);
}

代码很简单,调用addIfCondition 传递的参数 root 对象,在函数体中扩展一个属性addIfCondition, root.addIfCondition 属性值是一个对象。 此对象中有两个属性exp、block。实际上该函数是一个通用的函数,不仅仅用在根元素中,它用在任何由 v-if、v-else-if 以及 v-else 组成的条件渲染的模板中。

通过如上分析我们可以发现,具有 v-else-if 或 v-else 属性的元素的描述对象会被添加到具有 v-if 属性的元素描述对象的 .ifConnditions 数组中。

举个例子,如下模板:

<div v-if="A"></div>
<div v-else-if="B"></div>
<div v-else-if="C"></div>
<div v-else></div>

解析后生成的 AST 如下(简化版):

{
  type: 1,
  tag: 'div',
  ifConditions: [
    {
      exp: 'A',
      block: { type: 1, tag: 'div'  }
    },
    {
      exp: 'B',
      block: { type: 1, tag: 'div'  }
    },
    {
      exp: 'C',
      block: { type: 1, tag: 'div'  }
    },
    {
      exp: 'undefined',
      block: { type: 1, tag: 'div'  }
    }
  ]
  // 省略其他属性...
}

假如当前元素不满足条件:root.if && (element.elseif || element.else) ,那么在非生产环境下会打印了警告信息。

接下来源码:

if (currentParent && !element.forbidden) {
	if (element.elseif || element.else) {
		processIfConditions(element, currentParent);
	} else if (element.slotScope) { // scoped slot
		currentParent.plain = false;
		var name = element.slotTarget || '"default"';
		(currentParent.scopedSlots || (currentParent.scopedSlots = {}))[name] = element;
	} else {
		currentParent.children.push(element);
		element.parent = currentParent;
	}
}
if (!unary) {
	currentParent = element;
	stack.push(element);
} else {
	closeElement(element);
}

我们先从下往上讲, 为什么呢?原因是在解析根元素的时候currentParent并没有赋值。

!unary 表示解析的是非一元标签,此时把该元素的描述对象添加到stack 栈中,并且将 currentParent 变量的值更新为当前元素的描述对象。如果一个元素是一元标签,那么应该调用 closeElement 函数闭合该元素。

老生常谈的总结:每当遇到一个非一元标签都会将该元素的描述对象添加到stack数组,并且currentParent 始终存储的是 stack 栈顶的元素,即当前解析元素的父级。

if (currentParent && !element.forbidden) {
	if (element.elseif || element.else) {
		processIfConditions(element, currentParent);
	} else if (element.slotScope) { // scoped slot
		currentParent.plain = false;
		var name = element.slotTarget || '"default"';
		(currentParent.scopedSlots || (currentParent.scopedSlots = {}))[name] = element;
	} else {
		currentParent.children.push(element);
		element.parent = currentParent;
	}
}

这里的条件要成立,则说明当前元素存在父级( currentParent ),并且当前元素不是被禁止的元素。

常见的情况如下:

if (currentParent && !element.forbidden) {
        if (element.elseif || element.else) {
         //...
	} else if (element.slotScope) { // scoped slot
	 //...
	} else {
		currentParent.children.push(element);
		element.parent = currentParent;
	}
}

在 else 语句块内,会把当前元素描述对象添加到父级元素描述对象 ( currentParent ) 的children 数组中,同时将当前元素对象的 parent 属性指向父级元素对象,这样就建立了元素描述对象间的父子级关系。

如果一个标签使用 v-else-if 或 v-else 指令,那么该元素的描述对象实际上会被添加到对应的v-if 元素描述对象的 ifConditions 数组中,而非作为一个独立的子节点,这个工作就是由如下代码完成:

if (currentParent && !element.forbidden) {
	if (element.elseif || element.else) {
		processIfConditions(element, currentParent);
	} else if (element.slotScope) { // scoped slot
		currentParent.plain = false;
		var name = element.slotTarget || '"default"';
		(currentParent.scopedSlots || (currentParent.scopedSlots = {}))[name] = element;
	} else {
	  //...
	}
}

如当前解析的元素使用了 v-else-if 或 v-else 指令,则会调用 processIfConditions 函数,同时将当前元素描述对象 element 和父级元素的描述对象 currentParent 作为参数传递:

processIfConditions 源码

function processIfConditions(el, parent) {
	var prev = findPrevElement(parent.children);
	if (prev && prev.if) {
		addIfCondition(prev, {
			exp: el.elseif,
			block: el
		});
	} else {
		warn$2(
			"v-" + (el.elseif ? ('else-if="' + el.elseif + '"') : 'else') + " " +
			"used on element <" + (el.tag) + "> without corresponding v-if."
		);
	}
}

findPrevElement 函数是去查找到当前元素的前一个元素描述对象,并将其赋值给 prev 常量,addIfCondition 不用多说如果prev 、prev.if 存在,调用 addIfCondition 函数在当前元素描述对象添加 ifConditions 属性,传入的对象存储相关信息。

如果当前元素没有使用 v-else-if 或 v-else 指令,那么还会判断当前元素是否使用了 slot-scope 特性,如下:

if (currentParent && !element.forbidden) {
	if (element.elseif || element.else) {
          //...
	} else if (element.slotScope) { // scoped slot
		currentParent.plain = false;
		var name = element.slotTarget || '"default"';
		(currentParent.scopedSlots || (currentParent.scopedSlots = {}))[name] = element;
	} else {
	  //...
	}
}

如果一个元素使用了 slot-scope 特性,那么该元素的描述对象会被添加到父级元素的scopedSlots 对象下,也就是说使用了 slot-scope 特性的元素与使用了v-else-if 或 v-else 指令的元素一样,他们都不会作为父级元素的子节点,对于使用了 slot-scope 特性的元素来讲它们将被添加到父级元素描述对象的 scopedSlots 对象下。

自 2.6.0 起有所更新。已废弃的使用slot-scope 特性的语法在这里。所以此块内容就不铺开来讲了,有兴趣的同学可以去了解下,更多关于vue parseHTML start钩子函数的资料请关注编程网其它相关文章!

--结束END--

本文标题: vue parseHTML函数源码解析start钩子函数

本文链接: https://www.lsjlt.com/news/34273.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • vue parseHTML函数源码解析start钩子函数
    目录正文platformGetTagNamespace 源码 isForbiddenTag 函数addIfCondition是什么processIfConditions 源...
    99+
    2022-09-27
  • vue parseHTML函数源码分析start钩子函数
    这篇文章主要讲解了“vue parseHTML函数源码分析start钩子函数”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“vue parseHTML函数源码分析start...
    99+
    2023-07-02
  • vue parseHTML源码解析hars end comment钩子函数
    目录引言chars源码:parseTextend 源码closeElement 源码comment 注释节点描述对象引言 接上文  parseHTML 函数源码解析&nbs...
    99+
    2022-11-13
  • vue parseHTML 函数源码解析
    目录正文函数开头定义的一些常量和变量while 循环textEnd ===0parseStartTag 函数解析开始标签总结:正文 接上篇: Vue编译器源码分析AST 抽象语法树 ...
    99+
    2022-09-27
  • vue parseHTML函数源码分析
    本文小编为大家详细介绍“vue parseHTML函数源码分析”,内容详细,步骤清晰,细节处理妥当,希望这篇“vue parseHTML函数源码分析”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧...
    99+
    2023-07-02
  • vue parseHTML函数源码分析AST
    这篇“vue parseHTML函数源码分析AST”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“vue ...
    99+
    2023-07-02
  • vue parseHTML 函数源码解析AST基本形成
    目录AST(抽象语法树)?子节点Vue中是如何把html(template)字符串编译解析成AST解析html代码重新改造接着解析 html (template)字符串解析divAS...
    99+
    2022-09-27
  • Vue八大生命周期钩子函数源码分析
    本篇内容主要讲解“Vue八大生命周期钩子函数源码分析”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Vue八大生命周期钩子函数源码分析”吧!一.速识概念:我们把一个对象从生成(new)到被销毁(d...
    99+
    2023-07-05
  • vue parseHTML 函数拿到返回值后的处理源码解析
    目录引言parseStartTag函数返回值handleStartTag源码tagName 及unarySlash调用parser钩子函数引言 继上篇文章: parseHTML 函数...
    99+
    2022-09-27
  • Vue中钩子函数的示例分析
    这篇文章主要介绍了Vue中钩子函数的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。Vue-Router导航守卫:有的时候,我们需要通...
    99+
    2022-10-19
  • python 钩子函数详解
    1.with 与 __enter__ ,__exit__ with obj: expressment #进入with块时调用 obj.__enter__() #退出with块时调用 obj....
    99+
    2023-01-31
    钩子 详解 函数
  • vue parseHTML函数解析器遇到结束标签
    目录引言match函数匹配正则endTag关键 parseEndTag 函数代码总结parseEndTag 函数作用handleStartTag函数后续最后更新 stack 栈以及 ...
    99+
    2022-09-27
  • drupal之hook_link和hook_link_alter钩子函数解析
    本文实例讲述了drupal中hook_link和hook_link_alter钩子函数的用法。分享给大家供大家参考。具体如下: 在Drupal中有个钩子,叫做hook_link,参数如下:复制代码代码如下:hook_li...
    99+
    2022-06-12
    drupal hook_link hook_link_alter 钩子函数
  • 浅析pytest 钩子函数 之初始钩子和引导钩子
    目录1. F( arg1, arg2, …)2. F( arg1, arg2=value2, …)3. F( *arg1 )1. F( arg1, arg...
    99+
    2022-11-11
  • Vue中钩子函数怎么用
    小编给大家分享一下Vue中钩子函数怎么用,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!在Vue 中可以把一系列复杂的操作包装为一...
    99+
    2022-10-19
  • Vue中钩子函数有什么用
    这篇文章给大家分享的是有关Vue中钩子函数有什么用的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。Vue-Router导航守卫有的时候,我们需要通过路由来进行一些操作,比如最常见的...
    99+
    2022-10-19
  • 怎么自定义Vue钩子函数
    这篇文章主要讲解了“怎么自定义Vue钩子函数”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么自定义Vue钩子函数”吧!useWindowResize这是一个基本的钩子,因为它被用在很多项目...
    99+
    2023-06-29
  • Vue中callHook钩子函数怎么调用
    这篇“Vue中callHook钩子函数怎么调用”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Vue中callHook钩子函数...
    99+
    2023-07-04
  • vue路由钩子函数是哪几种
    这篇文章主要介绍“vue路由钩子函数是哪几种”,在日常操作中,相信很多人在vue路由钩子函数是哪几种问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”vue路由钩子函数是哪几种”...
    99+
    2022-10-19
  • vue钩子函数的作用是什么
    Vue钩子函数的作用是在组件生命周期的不同阶段执行特定的代码逻辑。它们使开发者能够在组件的不同生命周期阶段进行自定义操作,以满足不同...
    99+
    2023-08-08
    vue
软考高级职称资格查询
推荐阅读
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作