• 初始化组件实例的关系属性,比如: p a r e n t / parent/ children/ r o o t / root/ 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的双向绑定

    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 = /*#__PURE__*/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+事件对父组件进行传值
  • 组件中可以使用parentparent和children获取到父组件实例和子组件实例,进而获取数据
  • 使用attrsattrs和listeners,在对一些组件进行二次封装式可以方便传值,例如A->B->C
  • 使用$refs获取组件实例,进而获取数据
  • 使用Vuex进行状态管理
  • 使用eventBus进行跨组件触发事件,进而传递数据
  • 使用provide和inject,官方建议我们不要用,elementui中发现大量使用
  • 使用浏览器本地缓存,例如localStorage
  • computed和watch的区别

  • computed是依赖已有的变量来计算一个目标变量,大多数情况都是多个变量凑在一起计算出一个变量;并且computed具有缓存机制,依赖值不变的情况下直接读取缓存进行复用;computed不能进行异步操作。
  • watch是监听某一个变量的变化,并执行响应的回调函数,通常是一个变量的变化决定多个变量的变化。watch可以进行异步操作。
  • Vue异步更新和nextTick实现原理

    说说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 修饰符:
  • //  在“change”时而非“input”时更新
    <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
           
    粉丝