vue面试题总结

runtime-only 和 runtime-compiler

  1. runtime-only:是运行的时候代码不能包含任意一个template标签

    • render(h)- 》 virtual Dom - 》UI真实dom

    • 我们在使用 Runtime Only 版本的 Vue.js 的时候,通常需要借助如 webpack 的 vue-loader 工具把 .vue 文件编译成 JavaScript,因为是在编译阶段做的,所以它只包含运行时的 Vue.js 代码,因此代码体积也会更轻量。 在将 .vue 文件编译成 JavaScript的编译过程中会将组件中的template模板编译为render函数,所以我们得到的是render函数的版本。所以运行的时候是不带编译的,编译是在离线的时候做的。

  1. runtime-compiler:代码中可以有template标签

    • template加载过程:

      template - 》parse - 》ast 抽象语法树 - 》compiler - 》render(h)- 》 virtual Dom - 》UI真实dom

总结对比

最终渲染都是通过 render 函数,如果写 template 属性,则需要编译成 render 函数,那么这个编译过程会发生运行时,所以需要带有编译器的版本。

很显然,这个编译过程对性能会有一定损耗,所以通常我们更推荐使用 Runtime-Only 的 Vue.js。

runtime-only比runtime-compiler性能更高,代码更少(少6kb)

计算属性和监听属性和方法的区别

计算属性

计算属性是依赖的值改变会重新执行函数,当数据没有变化的时候,他会读取缓存。计算属性是取返回值作为最新结果所以里面不能异步的返回结果。不能写异步逻辑

页面初次加载的时候,会运行计算

计算属性是对多个属性进行监听,进一步整合,执行判断逻辑等,返回结果作为一个新的属性,可以绑定在页面中

监听属性

侦听属性是侦听的值改变会重新执行函数,将一个值重新赋值作为最新结果,所以赋值的时候可以进行一些异步操作。

页面初次加载的时候,不会执行操作

监听属性 是对单个已存在的data属性进行监听,获取 oldValue newValue,然后执行一些判断逻辑,比如修改其他值

总结对比

computed是属性调用,而method是函数调用

数据变化时执行异步或者开销比较大的操作的时候,这时候使用watch是合适的

computed一般是一个依赖值衍生新的值,值结果会被缓存,除非依赖值发生变化才会重新计算( eg:购物车结算 )

watch一般监听一个对象键值是需要观察的变量或者表达式,键值对应是回调函数,主要是负责监听某些特定数据的变化,从而进行某些具体的业务逻辑

methods方法表示一个具体的操作,负责书写主要业务逻辑

keep-alive

名词解释和作用

keep-alive是vue内置的组件,自身不会渲染一个DOM元素,Vue在初始化生命周期的时候,为组件实例建立父子关系会根据abstract属性决定是否忽略某个组件。在keep-alive中,设置了abstract:true,那Vue就会跳过该组件实例。最后构建的组件树中就不会包含keep-alive组件,那么由组件树渲染成的DOM树自然也不会有keep-alive相关的节点了。

可以是被包含的组件保留状态,缓存组件实例,不会销毁,避免重新渲染。

避免组件反复创建和渲染,有效提升系统性能。总的来说,keep-alive用于保存组件的渲染状态。

对应的vue组件生命周期 activited和deactivited

属性说明

include:可以是字符串(组件名称)或者正则表达式,只有匹配的组件会被缓存

exclude:可以是字符串(组件名称)或者正则表达式,任何匹配的组件都不会被缓存

max:定义缓存组件上限,超出上限使用LRU的策略置换缓存数据。

内存管理的一种页面置换算法,对于在内存中但又不用的数据块(内存块)叫做LRU,操作系统会根据哪些数据属于LRU而将其移出内存而腾出空间来加载另外的数据。

两个同时使用,若某组件同时被两个属性都匹配, exclude 优先级较高,最终匹配的组件不会被缓存

keep-alive 源码解析

路由传参

路由传参有4种方式

路由配置表中,路径后面串联传入的参数

强制刷新页面,参数不会丢失 {path: '/a/:num', name: A, component: A}

 方式1:通过router-link,to属性 路由地址+传递参数
  
  
 方式2:通过path 串联路由地址和传递的参数
 this.$router.push({
        path: `/d/${id}`
      })
  方式3:通过命名路由+params 匹配路由配置好的属性名
  this.$router.push({
        name: 'A',
        params: {
          num: '12'
        }
      })

命名路由+params传递参数

路径后面不需要加传入的参数,再次刷新页面后,参数会丢失 {path: '/b', name: 'B', component: B}

 this.$router.push({
        name: 'B',
        params: {
          sometext: '一只羊出没'
        }
      })
      
   获取参数: {{this.$route.params.sometext}}
   

通过query来传递参数

会显示在地址,以?开头串联在地址末尾,传递多个参数,用“&”隔开,每个参数的名和值用“=”隔开,强制刷新页面,参数不会丢失

 this.$router.push({
        path: '/c',
        query: {
          sometext: '这是小羊同学'
        }
  获取参数:{{this.$route.query.sometext}}

传参注意事项

1.当使用path路径匹配路由时,不能和params不能同时使用,params传递的参数会丢失

2.当使用命名路由时name,params和query可以同时使用传递参数

路由懒加载

为什么要懒加载

当打包构建应用时,JavaScript 包会变得非常大,影响页面加载。

路由中会定义很多不同的页面,默认情况下这些页面会被打包放在一个js文件中,造成这个js文件非常大,请求耗时会比较久,有可能用户的电脑还会出现短暂的空白,影响用户的体验。

怎么实现懒加载

结合 Vue 的异步组件 (opens new window)和 Webpack 的代码分割功能 (opens new window),轻松实现路由组件的懒加载

路由懒加载功能

主要作用就是将路由对应的组件打包成一个个的js代码块,只有在这个路由被访问的时候,才加载对应的组件

路由懒加载的三种方式

方式1 结合vue的异步组件和webpack的代码分析,写法太复杂,基本已经弃用

const home = resolve => {require.ensure(['../views/Home.vue'],()=>{
resolve(require('../views/Home.vue'))
})}

方式2:AMD写法,也基本被弃用了

const home = resolve =>require(['../vuews/Home.vue'],resolve);

方式3:在ES6中 有更加简单的写法来组织vue异步组件和webpack的代码分割,强烈推荐

const home = ()=> import('../views/Home.vue')

路由守卫

路由守卫分为2两种: 全局守卫和局部守卫

全局守卫 :前置守卫 beforeEatch 和后置钩子 afterEatch

局部守卫包括:路由守卫和组件守卫

路由守卫是配置在路由映射表中,beforeEnter,参数和beforeEatch一直,优先级高于全局守卫

组件守卫是定义在组件中的钩子函数 beforeRouterEnter , beforeRouterUpdate, beforeRouterLevel

beforeRouterEnter 中不能使用this,因为还没有创建好组件。

beforeRouterUpdate 是当路由地址没有改变,但是参数改变的时候,才会被调用,比如 /a/1 => /a/2

beforeEatch((to,from,next)={ 

})
beforeEatch是一个函数,里面的参数是一个箭头函数,to和from 都是route对象实例,next和函数,必须要调用,所以不会执行路由不会跳转
通常用全局的守卫来监听路由跳转,执行一些全局的操作,比如标题。

路由导航

所有的组件都继承自vue的原型,在vue原型vue.prototype 上定义的函数和属性,子组件可以通过this. 直接调用,

比如**this.$router 和this.$route**
this.$router 指向的路由映射表,VueRouter实例,可以导航到不同的url,
this.$router.push(),this.$router.replace,对应的history中的pushState和replaceState

this.$route 指向的是路由映射表中的一个路由选项,代表当前跳转的路由,可以获取当前路由的name,path,query,params等

Es6新特性

1.不一样的变量声明:const和let,ES6推荐使用let声明局部变量

let表示声明变量,而const表示声明常量,两者都为块级作用域;const 声明的变量都会被认为是常量,意思就是它的值被设置完成后就不能再修改了

如果const的是一个对象,对象所包含的值是可以被修改的。抽象一点儿说,就是对象所指向的地址没有变就行

let 关键词声明的变量不具备变量提升(hoisting)特性,不能先使用,再声明。var具备变量提升

let 和 const 声明只在最靠近的一个块中(花括号内)有效

当使用常量 const 声明时,请使用大写变量,如:CAPITAL_CASING

const 在声明时必须被赋值

2.模板字符串

在ES6之前,我们往往通过“\”和“+”来构建模板

es6可以将表达式嵌入字符串中进行拼接。用${}来界定

ES6反引号(``)直接搞定;

  1. $("body").html(`This demonstrates the output of HTML content to the page, 
    including student's ${name}, ${seatNumber}, ${sex} and so on.`);
    

3.箭头函数(Arrow Functions)

ES6 中,箭头函数就是函数的一种简写形式,使用括号包裹参数,跟随一个 =>,紧接着是函数体;

箭头函数最直观的三个特点。

  • 不需要 function 关键字来创建函数
  • 省略 return 关键字
  • 继承当前上下文的 this 关键字
  • 当你的函数有且仅有一个参数的时候,是可以省略掉括号的。当你函数返回有且仅有一个表达式的时候可以省略{} 和 return;

4.函数参数默认值

// ES6之前,当未传入参数时,
text = 'default'; 
function printText(text) {
    text = text || 'default';   
   console.log(text);
}
// ES6;
function printText(text = 'default') {    
 console.log(text);
}
printText('hello'); // helloprintText();// default

5.二进制和八进制字面量

ES6 支持二进制和八进制的字面量,通过在数字前面添加 0o 或者0O 即可将其转换为八进制值:

let oValue = 0o10;console.log(oValue); // 8 let bValue = 0b10; // 二进制使用 `0b` 或者 `0B`console.log(bValue); // 2

6.模块化 export 和 import

import 导入模块、export 导出模块

可以直接在任何变量或者函数前面加上一个 export 关键字,就可以将它导出。

let var 和const区别

在javascript中有三种声明变量的方式:var、let、const。

JS中作用域有:全局作用域、函数作用域。没有块作用域的概念。ECMAScript 6(简称ES6)中新增了块级作用域。****块作用域由 { } 包括,if语句和for语句里面的{ }也属于块作用域。

var

var定义的变量可以修改,如果不初始化会输出undefined,不会报错。

var 声明全局变量,换句话理解就是,声明在for循环中的变量,跳出for循环同样可以使用。

let

同一个变量,不可在声明之前调用,必须先定义再使用,否则会报错,循环体中可以用let

let是块级作用域,函数内部使用let定义后,对函数外部无影响。并且let不能定义同名变量,否则会报错。

cosnt

const:用于声明常量,也具有块级作用域 ,也可声明块级。const定义的变量不可以修改,而且必须初始化。

如果const的是一个对象,对象所包含的值是可以被修改的。抽象一点儿说,就是对象所指向的地址没有变就行

它和let一样,也不能重复定义同一个变量,const一旦定义,无法修改.

let和const属于局部变量,不会出现变量提升的情况,

全局定义的let和const变量,不属于顶层变量,不属于window的属性,

浏览器环境中顶层对象是window,Node中是global对象

es5中顶层变量的属性等价于全局变量,定义的var变量是window属性

到了es6中有所改变,es5的var ,function 声明的全局变量 依旧是顶级对象的属性 而es6声明的全局变量不属于顶级对象的属性了

var age = 29;
let ages = 29;
alert(window.age)  ==>29
alert(window.ages ) ==>undefined

axios配置

 //安装axios
 npm install axios 

Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。可以执行get请求,执行post请求,执行多个并发请求,支持promise ,拦截请求和响应,转换请求数据和响应数据,取消请求 ,自动转换json数据。

1.支持node端和浏览器端

同样的API,node和浏览器全支持,平台切换无压力

2.支持 Promise

使用Promise管理异步,告别传统callback方式

3.丰富的配置项

支持拦截器等高级配置

常用的请求配置

method:请求方法 post get delete put等
baseUrl:请求基本路径地址,将自动加在 `url` 前面
url:请求地址
headers:自定义请求头参数,可以包含token,content-type等
timeout:配置请求超时
params: 是即将与请求一起发送的 URL 参数

添加拦截器

// 添加请求拦截器
axios.interceptors.request.use(
   function (response) {    // 对请求数据做点什么    return response;  },
 function (error) {    // 对请求错误做点什么    return Promise.reject(error);  }
);
// 添加响应拦截器
axios.interceptors.response.use(
 function (response) {    // 对响应数据做点什么    return response;  },
 function (error) {    // 对响应错误做点什么    return Promise.reject(error);  }
);

创建axios实例

function createAxios(type){
    let timeout = 20000; //统一的超时时间
    var token = null;
    if (userInfo.token()) {
        token = userInfo.token();
    }
    let applicationHeaderPayload = {
        'Content-Type': 'application/json; charset=utf-8',
        'token':token,
        'platform': "H5",
        'Accept': '*/*'
    }
    let applicationHeader = {
        'Content-Type': 'application/x-www-form-urlencoded', 
        'token':token,
        'platform': "H5",
        'Accept': '*/*'
    }; 
    let args = {}; //配置参数
    let axiosInstance; //axios 实例
    switch(type){
        case "payload" :
            args = {
                timeout,
                "headers": applicationHeaderPayload
            };
            break;
        case "formData" :
            args = {
                timeout,
                "headers" : applicationHeader
            };
            break;
        default :
            break;
    }
    axiosInstance = axios.create(args);
    axiosInstance.interceptors.request.use (function (config) { //请求拦截器
        var token = null;
        if (userInfo.token()) {
            token = userInfo.token();
        }
        config.url = baseUrl+config.url;
        config.headers = {
            'Content-Type': 'application/json; charset=utf-8',
            'token':token,
            'platform': "H5",
            'Accept': '*/*'
        }
        if(config && config.data && ['formData'].indexOf(type) != -1){
            config.data = qs.stringify(config.data);
            config.headers = {
                'Content-Type': 'application/x-www-form-urlencoded', 
                'token':token,
                'platform': "H5",
                'Accept': '*/*'
            }
        }
        return config;
    }, function (error) {
        return Promise.reject(error);
    });
    axiosInstance.interceptors.response.use(function (response) { //返回拦截器
        return handleSuccess(response);
    }, function (data) {
        return handleError(data);
    });
    return axiosInstance;
}

vue-router两种加载模式

1. Hash (对应HashHistory)

hash(“#”)符号的本来作用是加在URL中指示网页中的位置:

http://www.example.com/index.html#print

符号本身以及它后面的字符称之为hash(也就是我之前为什么地址栏都会有一个‘#’),可通过window.location.hash属性读取。它具有如下特点:

  1. hash虽然出现在URL中,但不会被包括在HTTP请求中。它是用来指导浏览器动作的,对服务器端完全无用,因此,改变hash不会重新加载页面

2.可以为hash的改变添加监听事件:

window.addEventListener("hashchange", funcRef, false)
  1. 每一次改变hash(window.location.hash),都会在浏览器的访问历史中增加一个记录

利用hash的以上特点,就可以来实现前端路由“更新视图但不重新请求页面”的功能了。

2. History (对应HTML5History)

History接口是浏览器历史记录栈提供的接口,通过back(), forward(), go()等方法,我们可以读取浏览器历史记录栈的信息,进行各种跳转操作。

从HTML5开始,History interface提供了两个新的方法:pushState(), replaceState()使得我们可以对浏览器历史记录栈进行修改:

window.history.pushState(stateObject, title, URL)
window.history.replaceState(stateObject, title, URL)

stateObject: 当浏览器跳转到新的状态时,将触发popState事件,该事件将携带这个stateObject参数的副本
title: 所添加记录的标题
URL: 所添加记录的URL

这两个方法有个共同的特点:当调用他们修改浏览器历史记录栈后,虽然当前URL改变了,但浏览器不会刷新页面,这就为单页应用前端路由“更新视图但不重新请求页面”提供了基础。
浏览器历史记录可以看作一个「栈」。栈是一种后进先出的结构,可以把它想象成一摞盘子,用户每点开一个新网页,都会在上面加一个新盘子,叫「入栈」。
用户每次点击「后退」按钮都会取走最上面的那个盘子,叫做「出栈」。而每次浏览器显示的自然是最顶端的盘子的内容。

vue-router 的作用

vue-router的作用就是通过改变URL,在不重新请求页面的情况下,更新页面视图。简单的说就是,虽然地址栏的地址改变了,但是并不是一个全新的页面,而是之前的页面某些部分进行了修改。

export default new Router({ 
  mode: 'history', //后端支持可开
  routes: constantRouterMap})

这是Vue项目中常见的一段初始化vue-router的代码,mode属性用来指定vue-router使用哪一种模式。在没有指定mode的值,则使用hash模式。

vue-router路由模式有几种?请谈谈你对它们的理解?

常用的路由模式有hash和history;
最直观的区别是hash模式url上会携带有一个#,而history不携带;

hash:

即地址栏URL中的#符号,它的特点在于hash值虽然出现在URL中,但不会被包括在HTTP请求中,对服务端完全没影响,因此改变hash值不会重新加载页面。

history:

利用了HTML5 History interface 中新增的pushState() 和 replaceState()方法。
这两个方法应用于浏览器历史记录栈,提供了修改历史记录的功能,执行修改时虽然改变了URL但是不会立即的向服务端发起请求。

hash和history模式都属于浏览器自身的特性,vue-router只是利用了这两个特性来实现前端路由
但是在history模式下会出现刷新404的问题,对于这个问题,我们只需要在服务器配置nginx如果URL匹配不到任何静态资源,就跳转到默认的index.html

history.pushState()相比于直接修改hash主要有以下优势:

  1. pushState设置的新URL可以是与当前URL同源的任意URL;而hash只可修改#后面的部分,故只可设置与当前同文档的URL
  2. pushState设置的新URL可以与当前URL一模一样,这样也会把记录添加到栈中;而hash设置的新值必须与原来不一样才会触发记录添加到栈中
  3. pushState通过stateObject可以添加任意类型的数据到记录中;而hash只可添加短字符串
  4. pushState可额外设置title属性供后续使用

v-if 和 show的区别

相同点:v-if与v-show都可以动态控制dom元素显示隐藏
不同点:v-if显示隐藏是将dom元素整个添加或删除,而v-show隐藏则是为该元素添加css--display:none,dom元素还在。

组件通信的方法

父子组件通信

1.props 父组件向子组件传递数据 ,$emit 子组件触发父组件事件响应

2.$children 和 $refs 获取子组件实例对象,$parent或者$root 获取父组件或者根组件实例对象。拿到实例对象可以直接操作data数据或者调用函数,但是一般不推荐,耦合度太高

$children 和 $refs 获取子组件实例对象 这两个的区别:
 ref可以指定任意的dom元素节点,包括原生HTML元素,children 获取的是包含自定义子组件实例列表,并且是无序的

3.通过vuex 或者localStorage 保存数据,进行数据传递

4.多级组件嵌套需要传递数据时, Vue2.4 版本提供了另一种方法----$attrs/$listeners

5.  provide/inject,以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在起上下游关系成立的时间里始终生效。
祖先组件中通过 provider 来提供变量,然后在子孙组件中通过 inject 来注入变量。

provide / inject API 主要解决了跨级组件间的通信问题,不过它的使用场景,主要是子组件获取上级组件的状态,跨级组件间建立了一种主动提供与依赖注入的关系。

需要注意的是:**provide 和 inject 绑定并不是可响应的**。这是刻意为之的。然而,如果你传入了一个可监听的对象,那么其对象的属性还是可响应的----vue 官方文档

所以,上面 A.vue 的 name 如果改变了,B.vue 的 this.name 是不会改变的,为了解决这种问题,可以把祖先组件的this实例传递provide过去,然后子组件通过this 获取需要的参数。耦合度太高

组件通信常见使用场景可以分为三类:

**父子通信:**
  父向子传递数据是通过 props,子向父是通过 events($emit);
  通过父链 / 子链也可以通信($parent / $children);ref 也可以访问组件实例;
  provide / inject API;$attrs/$listeners

 ** 兄弟通信:**
  Bus;Vuex;localStorage

  **跨级通信:**
  Bus;Vuex;localStorage;provide / inject API;$attrs/$listeners

详细解析

vue 自定义指令

自定义指令
Vue 内置了一些非常有用的指令(比如v-html 和 v-once等),每个指令都有自身的用途
Vue 也允许注册自定义指令。它的作用价值在于当开发人员在某些场景下需要对普通 DOM 元素进行操作。
Vue 自定义指令有全局注册和局部注册两种方式。先来看看注册全局指令的方式,
通过 Vue.directive( id, [definition] ) 方式注册全局指令。然后在入口文件中进行 Vue.use() 调用。

当页面加载时,该元素将获得焦点 (注意:autofocus 在移动版 Safari 上不工作)。事实上,只要你在打开这个页面后还没点击过任何内容,这个输入框就应当还是处于聚焦状态。现在让我们用指令来实现这个功能:

注册一个全局自定义指令 v-focus

Vue.directive('focus', {
  // 当被绑定的元素插入到 DOM 中时……
  inserted: function (el) {
    // 聚焦元素
    el.focus()
  }
})

如果想注册局部指令,组件中也接受一个 directives 的选项:

directives: {
  focus: {
    // 指令的定义
    inserted: function (el) {
      el.focus()
    }
  }
}

然后你可以在模板中任何元素上使用新的 v-focus property,如下:

vue常用内置指令

v-model
v-for
v-text
v-html
v-on
v-bind
v-if/v-else
v-show

1.vuex是什么?怎么使用?哪种功能场景使用它

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。简单来说就是:应用遇到多个组件共享状态时,使用vuex。
场景:多个组件共享数据或者是跨组件传递数据时

vuex的流程

页面通过mapAction异步提交事件到action。action通过commit把对应参数同步提交到mutation,mutation会修改state中对应的值。最后通过getter把对应值跑出去,在页面的计算属性中,通过,mapGetter来动态获取state中的值
在vue组件中可以直接通过this.$store 来操作

vuex有哪几种属性

有五种,分别是State , Getter , Mutation , Action , Module (就是mapAction)

  1. state:vuex的基本数据,用来存储变量
  2. geeter:从基本数据(state)派生的数据,相当于state的计算属性,对state数据进行封装转换之后再输出
  3. mutation:提交更新数据的方法,必须是同步的(如果需要异步使用action)。每个mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数,提交载荷作为第二个参数。
  4. action:和mutation的功能大致相同,不同之处在于 ==》1. Action 提交的是 mutation,而不是直接变更状态。 2. Action 可以包含任意异步操作。
  5. modules:模块化vuex,可以让每一个模块拥有自己的state、mutation、action、getters,使得结构非常清晰,方便管理。
  6. actions与mutations作用类似,都是可以对状态进行修改。不同的是actions是异步操作的。actions是可以调用Mutations里的方法的。
    dispatch:异步操作,写法: this.store.commit('mutations方法名',值)

Vuex中actions和mutations的区别

Mutation 更改 Vuex 的 store 中的状态的唯一方法是提交 mutation
Vuex 中的 mutation 非常类似于事件:每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数
Action Action 类似于 mutation,不同在于:

  • Action 提交的是 mutation,而不是直接变更状态。
  • Action 可以包含任意异步操作。 .

什么是mvvm模式,谈谈你的理解?

MVVM - Model View ViewModel,数据,视图,视图模型
view 可以通过 事件绑定 的方式影响 model
model 可以通过 数据绑定 的形式影响到view,
viewModel是把 model 和 view 连起来的桥梁,这样就实现了数据的双向绑定。

请谈谈你对vue.js 生命周期的理解?

1.什么是vue.js的生命周期:Vue 实例有一个完整的生命周期,也就是从开始创建、初始化数据、编译模版、挂载 Dom -> 渲染、更新 -> 渲染、卸载等一系列过程,我们称这是 Vue 的生命周期。

2.各个生命周期的作用


1111.jpg

为什么vue中组件里面的data是一个函数而不是一个对象呢?

因为组件可能被用来创建多个实例,如果data仍然是一个纯粹的对象,则所有的实例将共享引用一个数据对象,通过提供data函数,每次创建一个新的实例之后,我们能够调用data函数从而返回一个全新的副本数据对象,这样每一个实例都有自己私有的数据空间不会互相影响

vue事件修饰符以及各个的作用?

.stop:阻止事件冒泡
.native:绑定原生事件
.once:事件只执行一次
.self 将事件绑定在自身身上,相当于阻止事件冒泡
.prevent:阻止默认事件
.passive: 2.3.0 新增,滚动事件的默认行为 (即滚动行为) 将会立即触发,不能和.prevent 一起使用

vue如何优化页面加载?

1.UI组件库尽量使用cdn的方式引入,或者下载本地通过js文件引入;
2.配置路由懒加载的方式;
3.增加loading图,提升用户体验

父组件和子组件生命周期执行的顺序?

1.加载渲染过程:

父 beforeCreate -> 父 created -> 父 beforeMount -> 子 beforeCreate
-> 子 created -> 子 beforeMount -> 子 mounted -> 父 mounted

2.子组件更新过程:

父 beforeUpdate -> 子 beforeUpdate -> 子 updated -> 父 updated

3.父组件更新过程:

父 beforeUpdate -> 父 updated

4.销毁过程:

父 beforeDestroy -> 子 beforeDestroy -> 子 destroyed -> 父 destroyed

获取dom节点的方式

案例解析
DOM 是一个树形结构,操作一个DOM节点,实际上就是这几个操作:更新、删除、添加、遍历
在操作DOM节点之前,需要通过各种方式先拿到这个DOM节点,常用的方法有:

一、通过元素类型的方法来操作:

  1. document.getElementById();//id名,在实际开发中较少使用,选择器中多用class id一般只用在顶级层存在 不能太过依赖id
  2. document.getElementsByTagName();//标签名
  3. document.getElementsByClassName();//类名
  4. document.getElementsByName();//name属性值,一般不用
  5. document.querySelector();//css选择符模式,返回与该模式匹配的第一个元素,结果为一个元素;如果没找到匹配的元素,则返回null
  6. document.querySelectorAll()//css选择符模式,返回与该模式匹配的所有元素,结果为一个类数组

二、根据关系树来选择(遍历节点树):

【先简单介绍一下节点:
DOM(文档对象模型)可以将任何HTML、XML文档描绘成一个多层次的节点树。所有的页面都表现为以一个特定节点为根节点的树形结构。html文档中根节点为document节点。

所有节点都有nodeType属性,代表节点的不同类型,通过nodeType属性可以来判断节点的类型。经常使用的节点主要有以下几种类型:

Element类型(元素节点):nodeType值为 1
Text类型(文本节点):nodeType值为 3
Comment类型(注释节点):nodeType值为 8
Document类型(document节点):nodeType值为 9;其规定的一些常用的属性有
document.body    document.head  分别为HTML中的 
document.documentElement为标签

所有的节点都有 hasChildNodes()方法 判断有无子节点 有一个或多个子节点时返回true】

通过一些属性可以来遍历节点树:
parentNode//获取所选节点的父节点,最顶层的节点为#document
childNodes //获取所选节点的子节点们
firstChild //获取所选节点的第一个子节点
lastChild //获取所选节点的最后一个子节点
nextSibling //获取所选节点的后一个兄弟节点 列表中最后一个节点的nextSibling属性值为null
previousSibling //获取所选节点的前一兄弟节点 列表中第一个节点的previousSibling属性值为null
由于文档中的节点类型较多,遍历子节点的结果很多时候并不能得到我们想要的结果,使用遍历元素节点则很方便

三、基于元素节点树的遍历(遍历元素节点树):

parentElement //返回当前元素的父元素节点(IE9以下不兼容)
children  // 返回当前元素的元素子节点
firstElementChild //返回的是第一个元素子节点(IE9以下不兼容)
lastElementChild  //返回的是最后一个元素子节点(IE9以下不兼容)
nextElementSibling  //返回的是后一个兄弟元素节点(IE9以下不兼容)
previousElementSibling  //返回的是前一个兄弟元素节点(IE9以下不兼容)

vue获取dom节点

在vue项目中,获取dom节点可以用ref属性,这个属性就是来获取dom对象的。




你可能感兴趣的:(vue面试题总结)