vue面试知识点

vue基本使用

1. 文本插值

  • JS表达式 yes(只能是表达式,不能是 js 语句)
  • 动态属性 id

2. watch

watch如何深度监听

watch监听引用类型,拿不到oldVal

<template>
    <div>
        <input v-model="name"/>
        <input v-model="info.city"/>
    </div>
</template>

<script>
export default {
    data() {
        return {
            name: '哈哈',
            info: {
                city: '北京'
            }
        }
    },
    watch: {
        name(oldVal, val) {
            // eslint-disable-next-line
            console.log('watch name', oldVal, val) // 值类型,可正常拿到 oldVal 和 val
        },
        info: {
            handler(oldVal, val) {
                // eslint-disable-next-line
                console.log('watch info', oldVal, val) // 引用类型,拿不到 oldVal 。因为指针相同,此时已经指向了新的 val
            },
            deep: true // 深度监听
        }
    }
}
</script>

3. computed

computed有缓存,data不变则不会重新计算

<template>
    <div>
        <p>num {{num}}</p>
        <p>double1 {{double1}}</p>
        <input v-model="double2"/>
    </div>
</template>

<script>
export default {
    data() {
        return {
            num: 20
        }
    },
    computed: {
        double1() {
            return this.num * 2
        },
        double2: { // 双向绑定必须有get和set方法
            get() {
                return this.num * 2
            },
            set(val) {
                this.num = val/2
            }
        }
    }
}
</script>

4. class和style

<template>
    <div>
        <p :class="{ black: isBlack, yellow: isYellow }">使用 class</p>
        <p :class="[black, yellow]">使用 class (数组)</p>
        <p :style="styleData">使用 style</p>
    </div>
</template>

<script>
export default {
    data() {
        return {
            isBlack: true,
            isYellow: true,

            black: 'black',
            yellow: 'yellow',

            styleData: {
                fontSize: '40px', // 转换为驼峰式
                color: 'red',
                backgroundColor: '#ccc' // 转换为驼峰式
            }
        }
    }
}
</script>

<style scoped>
    .black {
        background-color: #999;
    }
    .yellow {
        color: yellow;
    }
</style>

4. 条件渲染

  • v-if v-else 的用法,可使用变量,也可使用 === 表达式
  • v-if 和 v-show的区别?

​ v-if是通过控制dom节点的存在与否来控制元素的显隐;v-show是通过设置DOM元素的display样式,block为显示,none为隐藏。

  • 使用场景

​ 如果需要非常频繁地切换,则使用 v-show 较好;如果在运行时条件很少改变,则使用 v-if 较好。

5. 循环(列表)渲染

  • 可以用v-for遍历对象和数组

  • key的重要性 (尽量和业务相关)

  • v-for 和v-if 不能一起使用

6. 事件

自定义传参

事件修饰符:


image.png

7. 表单

常见表单项 textarea checkbox radio select

修饰符 lazy number trim

8. vue组件使用

  1. 父子组件间通讯 props 和 $emit
  2. 兄弟之间通讯: 自定义事件

​ 在外面新建一个名字叫 event.js 的文件,里面写

import Vue from 'vue'

export default new Vue()

创建一个vue的实例 就可以调用 event.emit和event.on 最后卸载时执行event.$off销毁

  1. 生命周期(单个组件)
    1422175-20190125154237190-1916558490.png

    created是vue实例已经初始化完成了,但是还没有渲染 mounted是页面已经渲染完毕
  2. 生命周期(父子组件)


    image.png

9. vue高级特性

  • 自定义v-model
// 父组件

<p>{{name}}</p>
<CustomVModel v-model="name"/>


// 子组件
<template>
    <!-- 例如:vue 颜色选择 -->
    <input type="text"
        :value="text1"
        @input="$emit('change1', $event.target.value)"
    >
    <!--
        1. 上面的 input 使用了 :value 而不是 v-model
        2. 上面的 change1 和 model.event1 要对应起来
        3. text1 属性对应起来
    -->
</template>

<script>
export default {
    model: {
        prop: 'text1', // 对应 props text1
        event: 'change1'
    },
    props: {
        text1: String,
        default() {
            return ''
        }
    }
}
</script>
  • $nextTick

vue是异步渲染,data改变后dom不会立刻渲染,$nextTick会在DOM渲染后在回调,以获取最新的dom节点。页面渲染时会将data的修改做整合,多次data修改只能渲染一次

  • slot 基本使用

​ 作用域插槽

// 父组件使用名字叫ScopedSlotDemo的子组件 在父组件里展示子组件的website的title

<ScopedSlotDemo :url="website.url">
    <template v-slot="slotProps">
        {{slotProps.slotData.title}}
    </template>
</ScopedSlotDemo>

<template>
    <a :href="url">
        <slot :slotData="website">
            {{website.subTitle}} <!-- 默认值显示 subTitle ,即父组件不传内容时 -->
        </slot>
    </a>
</template>

​ 具名插槽

​ 在slot上绑定一个name=“名字”,在父组件里在template里写v-slot:名字

  • 动态、异步组件

    1. 动态组件:需要根据数据,动态渲染的场景。即组件类型不确定
    <component :is= "子组件的名字" />
    
    1. 异步组件:用法
    <demo v-if="showDemo"/>
    <button @click=" showDemo = true "></button>
    当点击按钮时,显示demo组件时,加载demo组件
    
    components: {
      demo: () => import('组件路径')
    }
    
  • keep-alive (缓存组件): 需要频繁切换且不需要重复渲染的时候

    将需要缓存的组件用<keep-alive>标签包裹起来

  • mixin 可以将多个组件的相同的逻辑抽离出来

    将共同的逻辑抽离出来放在一个JS文件里,在需要的页面通过import引用,在和data同级的位置写

    mixins: [引用的js文件的名字]   可以添加多个,会自动合并起来
    
    这样就可以在当前页面用引入来的js文件里的data、方法
    

    缺点:

    1. 变量来源不明确,不利用阅读

      1. 多 mixin 可能会造成命名冲突
      2. mixin 和组件可能出现多对多的关系,复杂度较高

10. vuex

  • state
  • getters
  • mutation
  • action

api

  • dispatch
  • commit
  • mapState
  • mapGetters
  • mapActions
  • mapMutations

11. vue-router

  • 路由模式(hash、history)
  • 路由配置(动态路由、懒加载)

vue原理

1. 如何理解MVVM模型

数据驱动视图,不用我们操作DOM,只需要关注数据,数据变了,视图就会变

MVVM分为三个部分:分别是M(Model,模型层 ),V(View,视图层),VM(ViewModel,V与M连接的桥梁,也可以看作为控制器)
1、 M:模型层,主要负责业务数据相关;
2、 V:视图层,顾名思义,负责视图相关,细分下来就是html+css层;
3、 VM:V与M沟通的桥梁,负责监听M或者V的修改,是实现MVVM双向绑定的要点;

MVVM支持双向绑定,意思就是当M层数据进行修改时,VM层会监测到变化,并且通知V层进行相应的修改,反之修改V层则会通知M层数据进行修改,以此也实现了视图与模型层的相互解耦;


mvvm.png

2. vue响应式

核心API - Object.defineProperty

image.png

深度监听对象的时候需要用到 for in 定义一个方法 ,遍历对象,通过判断遍历出来的属性是一个值还是对象,如果是对象的话,就需要再次调用这个方法,再次遍历,直到遍历到底。

Object.defineProperty 的缺点

  • 深度监听,需要递归到底,一次性计算量大
  • 无法监听新增属性/删除属性(vue.set vue.delete)
  • 无法监听数组,需要特殊处理

3. 虚拟DOM(vdom)和 diff

vodm:用js模拟DOM结构,计算出最小的变更,操作DOM
用js模拟DOM结构

image.png

vdom核心概念: h vnode patch diff key 等

  • patch:path(elem, vnode) 和 patch(vnode, newvnode)

vdom存在的价值:数据驱动试图,控制DOM操作

你知道Vue中key的作用和工作原理吗?说说你对它的理解。

  1. key的主要作用是为了高效的更新虚拟DOM,其原理是vue在patch过程中通过key可以精准判断两个节点是否是同一个,从而避免频繁更新不同元素,使得整个patch过程更加高效,减少DOM操作量,提高性能。
  2. 另外,若不设置key还可能在列表更新时引发一些隐藏的bug
  3. vue中在使用相同标签名元素的过渡切换时,也会使用到key属性,其目的也是为了让vue可以区分它们,否则vue只会替换其内部属性而不会触发过渡效果。

4. 模板编译

  • 会将template编译成一个 render函数,里面是with语法的函数体(类似于h函数),最后返回vnode。
  • 基于vnode在执行patch和diff。
  • 使用webpack-vue-loader,会在开发环境编译模板
const template = `
    <div id="div1" class="container">
        <img :src="imgUrl"/>
    </div>`
    
    
with(this){return _c('div', // 标签
     {staticClass:"container",attrs:{"id":"div1"}}, // 属性
     [
         _c('img',{attrs:{"src":imgUrl}})])}  // 子元素

5. 组件渲染/更新过程

  • 初次渲染过程
    1. 解析模板为render函数(或在开发环境已完成, vue-loader)
    2. 触发响应式,监听data属性getter,setter
    3. 执行render函数,生成vnode,path(elem, vnode)
  • 更新过程
    1. 修改data,触发setter(此前在getter中已被监听)
    2. 重新执行render函数,生成newVnode
    3. patch(vnode, newvnode)


      image.png

6. 异步渲染

  • $nextTick
  • 汇总data的修改,一次性更新视图
  • 减少DOM操作次数,提高性能
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,816评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,729评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,300评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,780评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,890评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,084评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,151评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,912评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,355评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,666评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,809评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,504评论 4 334
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,150评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,882评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,121评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,628评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,724评论 2 351

推荐阅读更多精彩内容