初始化组件实例的关系属性,比如:
p
a
re
n
t
/
children/
roo
t
/
refs等
初始化自定义事件
初始化插槽,获取this.$slots,定义this._c即createElement方法
调用beforeCreate钩子函数
初始化组件的inject配置项,得到result[key]=value显示的配置对象,然后将配置对象进行响应式处理,并代理每个key到vm实例上
初始化组件的props、data、methods、computed、watch等配置项,响应式处理,并代理到vm实例上
解析组件配置项上的provide对象,将其挂载到vm._provided属性上
调用created钩子函数
如果发现配置项上有el选项,则自动调用mount方法,也就是说有了el选项,就不需要手动调用mount方法,反之,没提供el选项则必须手动调用mount
编译阶段,将template模版字符串编译成render函数
调用beforeMount钩子函数
执行render函数生成vnode虚拟dom
vnode渲染dom过程(因为是第一次则不需要新旧vnode的diff对比过程)。
new一个render Watcher
调用mount钩子函数
Vue的编译过程(解析-优化-生成)
将一个模版字符串编译(compile)成render函数
parse 解析阶段
正则匹配template模版解析成AST树;
optimize 优化阶段
AST优化阶段标记静态节点和静态根节点
递归遍历AST节点,判断每个节点是否是静态的;
递归遍历父节点中所有子节点是否是静态的,如果所有子节点都为静态,则该父节点为静态根节点;
在生成render函数阶段,判断一个节点是否是一个静态根节点,如果是静态根节点,生成静态render函数。
render函数生成vnode阶段,如果是静态render函数,将其生成的vnode进行缓存,等到下次再执行render函数的时候直接从缓存中取出。
故标记静态根节点是为了缓存vnode,减少render函数生成vnode的时间。
generate 生成阶段
将优化后的AST生成render函数。
Vue -- key 的特性作用
-分析下面一段代码
<template>
<div class="v-for">
<ul class="ul">
<li v-for="(row, index) in list">{{ row }}</li>
<button v-on:click="reverse">反转数组</button>
</div>
</template>
对比新旧vnode的第一个li
vue判断两个节点是否相同的源码
function sameVnode (a, b) {
return (
a.key === b.key && (
a.tag === b.tag &&
a.isComment === b.isComment &&
isDef(a.data) === isDef(b.data) &&
sameInputType(a, b)
) || (
isTrue(a.isAsyncPlaceholder) &&
a.asyncFactory === b.asyncFactory &&
isUndef(b.asyncFactory.error)
function isDef (v) {
return v !== undefined && v !== null
function sameInputType (a, b) {
if (a.tag !== 'input') { return true }
var i;
var typeA = isDef(i = a.data) && isDef(i = i.attrs) && i.type;
var typeB = isDef(i = b.data) && isDef(i = i.attrs) && i.type;
return typeA === typeB || isTextInputType(typeA) && isTextInputType(typeB)
根据1.1源码逻辑分析新旧vnode的第一个li是否是相同的节点,结论是:true
旧的vnode第一个li为a;新的vnode第一个li为b
a.key和b.key都是undefined,顾相等
a.tag和b.tag都是li,顾相等
a.isComment和b.isComment都是false,顾相等
a.data和b.data都是undefined,则isDef(a.data)和isDef(b.data)都是false,顾相等
所有最终判定sameNode(a,b)等于true
执行patchVnode方法
a : {
key : undefined,
tag : 'li',
isComment : false,
data : undefined
b : {
key : undefined,
tag : undefined,
isComment : false,
data : undefined
判断他们的子节点是否是sameVnode,结论是ture
a : {
key : undefined,
tag : undefined,
isComment : false,
data : undefined,
text: 1
b : {
key : undefined,
tag : undefined,
isComment : false,
data : undefined,
text: 5
判断新vnode的text是不是undefined或者null,结论为flase
判断新vnode的text和旧vnode的text是否相等,结论为false
执行nodeOps.setTextContent(elm, vnode.text)
setTextContent的第一个参数elm(var elm = vnode.elm = oldVnode.elm;),即第一个
参数是真实的dom树;
setTextContent的第二个参数是新vnode的text
即将新的值替换到实际dom树上去
function setTextContent (node, text) {
node.textContent = text;
var nodeOps = Object.freeze({
createElement: createElement$1,
createElementNS: createElementNS,
createTextNode: createTextNode,
createComment: createComment,
insertBefore: insertBefore,
removeChild: removeChild,
appendChild: appendChild,
parentNode: parentNode,
nextSibling: nextSibling,
tagName: tagName,
setTextContent: setTextContent,
setStyleScope: setStyleScope
如果v-for不添加key,则直接修改li里面的内容,官网里的表述为就地复用。
为什么data是一个函数并且返回一个对象呢
data之所以是一个函数,是因为一个组件可能会被多处调用,而每一次调用就会执行data函数并返回新的数据对象,这样,可以避免多处调用之间的数据污染。
组件之间的传值方式有哪些?
父组件传值给子组件,子组件使用props进行接收
子组件传值给父组件,子组件使用$emit+事件对父组件进行传值
组件中可以使用parent和children获取到父组件实例和子组件实例,进而获取数据
使用attrs和listeners,在对一些组件进行二次封装式可以方便传值,例如A->B->C
使用$refs获取组件实例,进而获取数据
使用Vuex进行状态管理
使用eventBus进行跨组件触发事件,进而传递数据
使用provide和inject,官方建议我们不要用,elementui中发现大量使用
使用浏览器本地缓存,例如localStorage
computed和watch的区别
computed是依赖已有的变量来计算一个目标变量,大多数情况都是多个变量凑在一起计算出一个变量;并且computed具有缓存机制,依赖值不变的情况下直接读取缓存进行复用;computed不能进行异步操作。
watch是监听某一个变量的变化,并执行响应的回调函数,通常是一个变量的变化决定多个变量的变化。watch可以进行异步操作。
说说nextTick的用处
Vue采用的时异步更新的策略,通俗点说就是,统一事件循环内多次修改,会统一进行视图更新。
Vue是异步更新的,所以数据一更新,视图却还没有更新,此时获取视图数据不是最新的。nextTick可以是
Vue-Router路由有哪些模式呢?
hash模式:通过#号后面的内容的更改,触发hashchange事件,实现路由切换
history模式:通过pushState和replaceState切换url,触发popstate事件,实现路由切换,需要后端配合
Vuex有哪些属性?用处是什么?
vuex.vuejs.org/zh/guide/
Vuex是专门为Vue开发的状态管理模式 + 库。它采用集中式存储管理应用的所有组件的状态,并以响应的规则保证状态以一种可预测的方式发生变化。
State
Vuex使用单一状态树——是的,用一个对象就包含了全部的应用层级状态。
在Vue中获取Vuex状态:this.$store.state.count
2. Getter
从store中的state中派生出一些状态,例如对列表进行过滤并计数:
Mutation
更改Vuex的store中的状态的唯一方法及时提交mutation。他接受state作为第一个参数;
Mutation通过store.commit触发
Mutation必须是同步函数
Action
Action类似于mutation,不同在于:
Action提交的是mutation,而不是直接变更状态
Action通过store.dispatch触发
5.Module
由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store对象有可能变得相当臃肿。
为了解决以上的问题,Vue允许我们将store分割成模块(module)。每个模块拥有自己的state、getter、mutation、action、甚至于嵌套子模块。
<div id="app">
<div>{{ countCopy }}</div>
<div><button @click="add">add</button></div>
<div><button @click="asyncAdd">asyncAdd</button></div>
</div>
<script src="https://unpkg.com/vue@next"></script>
<script src="https://unpkg.com/vuex@4"></script>
<script>
const store = Vuex.createStore({
state(){
return {
count: 0
mutations: {
add(state){
state.count ++
actions: {
add(context){
setTimeout(() => {
context.commit('add')
}, 1000);
const app = Vue.createApp({
computed: {
countCopy(){
return this.$store.state.count
methods: {
add(){
this.$store.commit('add')
asyncAdd(){
this.$store.dispatch('add')
app.use(store)
app.mount('#app')
</script>
</body>
Vuex的实现原理
v-model的实现原理
v3.cn.vuejs.org/guide/forms…
v-model
只是语法糖
v-model
在内部为不同的输入元素使用不同的 property 并抛出不同的事件:
text 和 textarea 元素使用 value
property 和 input
事件;
checkbox 和 radio 使用 checked
property 和 change
事件;
select 字段将 value
作为 prop 并将 change
作为事件;
组件上, 使用 modelValue
作为 prop 和 update:modelValue
作为事件。
.lazy
在默认情况下,v-model
在每次 input
事件触发后将输入框的值与数据进行同步 (除了上述输入法组织文字时)。你可以添加 lazy
修饰符,从而转为在 change
事件之后进行同步:
.number
如果想自动将用户的输入值转为数值类型,可以给 v-model
添加 number
修饰符:
.trim
如果要自动过滤用户输入的首尾空白字符,可以给 v-model
添加 trim
修饰符:
<input v-model.lazy="msg" />
Keep-Alive
当组件在 <keep-alive>
内被切换时,它的 mounted
和 unmounted
生命周期钩子不会被调用,取而代之的是 activated
和 deactivated
。(这会运用在 <keep-alive>
的直接子节点及其所有子孙节点。)
子组件更新props中的属性值的两种方式
vue怎么给绑定的onclick事件传递除event对象之外的参数?
@click="click($event, '1')"
function click(e, index){}
yanessa_yu
44.0k
粉丝