Vue面试题整合

什么是mvvm?

MVVM是Model-View-ViewModel的缩写。mvvm是一种设计思想。Model 层代表数据模型,也可以在Model中定义数据修改和操作的业务逻辑;View 代表UI 组件,它负责将数据模型转化成UI 展现出来,ViewModel 是一个同步View 和 Model的对象。

在MVVM架构下,View 和 Model 之间并没有直接的联系,而是通过ViewModel进行交互,Model 和 ViewModel 之间的交互是双向的, 因此View 数据的变化会同步到Model中,而Model 数据的变化也会立即反应到View 上。

ViewModel 通过双向数据绑定把 View 层和 Model 层连接了起来,而View 和 Model 之间的同步工作完全是自动的,无需人为干涉,因此开发者只需关注业务逻辑,不需要手动操作DOM, 不需要关注数据状态的同步问题,复杂的数据状态维护完全由 MVVM 来统一管理。


mvvm和mvc区别?

mvc和mvvm其实区别并不大。都是一种设计思想。主要就是mvc中Controller演变成mvvm中的viewModel。mvvm主要解决了mvc中大量的DOM 操作使页面渲染性能降低,加载速度变慢,影响用户体验。和当 Model 频繁发生变化,开发者需要主动更新到View 。


计算属性和watch的区别及使用场景

computed计算属性是用来声明式的描述一个值依赖了其它的值。当你在模板里把数据绑定到一个计算属性上时,Vue 会在其依赖的任何值导致该计算属性改变时更新 DOM。这个功能非常强大,它可以让你的代码更加声明式、数据驱动并且易于维护。 // 计算属性computed,计算的是Name依赖的值,它不能计算在data中已经定义过的变量。

watch监听的是你定义的变量,当你定义的变量的值发生变化时,调用对应的方法。// 当num的值发生变化时,就会调用num的方法,方法里面的形参对应的是num的新值和旧值

  • 一个数据属性在它所依赖的属性发生变化时,也要发生变化,这种情况下,我们最好使用计算属性。
  • watch函数适用于,当数据发生变化时,执行异步操作或较大开销操作的情况。

生命周期

Vue 实例从创建到销毁的过程,就是生命周期。从开始创建、初始化数据、编译模板、挂载Dom→渲染、更新→渲染、销毁等一系列过程,称之为 Vue 的生命周期。

  1. 创建前/后: 在beforeCreate阶段,vue实例的挂载元素el和数据对象data都为undefined,还未初始化。在created阶段,vue实例的数据对象data有了,el还没有。

  2. 载入前/后:在beforeMount阶段,vue实例的$el和data都初始化了,但还是挂载之前为虚拟的dom节点,data.message还未替换。在mounted阶段,vue实例挂载完成,data.message成功渲染。

  3. 更新前/后:当data变化时,会触发beforeUpdate和updated方法。

  4. 销毁前/后:在执行destroy方法后,对data的改变不会再触发周期函数,说明此时vue实例已经解除了事件监听以及和dom的绑定,但是dom结构依然存在

作用

它的生命周期中有多个事件钩子,让我们在控制整个Vue实例的过程时更容易形成好的逻辑。

第一次页面加载会触发哪几个钩子?

会触发下面这几个beforeCreate、created、beforeMount、mounted 。

DOM 渲染在哪个周期中就已经完成?

DOM 渲染在 mounted 中就已经完成了


vue的指令

  • v-if指令
  • v-show指令
  • v-else指令
  • v-for指令
  • v-bind指令
  • v-on指令
  • v-model指令
  • v-text读取文本不能读取html标签
  • v-html 能读取html标签

双向绑定 – Object.defineProperty()

vue实现数据双向绑定主要是:
采用数据劫持结合发布者-订阅者模式的方式,通过 Object.defineProperty() 来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应监听回调。当把一个普通 Javascript 对象传给 Vue 实例来作为它的 data 选项时,Vue 将遍历它的属性,用 Object.defineProperty() 将它们转为 getter/setter。用户看不到 getter/setter,但是在内部它们让 Vue追踪依赖,在属性被访问和修改时通知变化。


Proxy 相比于 defineProperty 的优势

  • 数组变化也能监听到
  • 不需要深度遍历监听
let data = { a: 1 }
let reactiveData = new Proxy(data, {
	get: function(target, name){
		// ...
	},
	// ...
})

vue路由hash模式与history模式的区别

  • hash模式
    • 路由的哈希模式其实是利用了window可以监听onhashchange事件,也就是说你的url中的哈希值(#后面的值)如果有变化,前端是可以做到监听并做一些响应(搞点事情),这么一来,即使前端并没有发起http请求他也能够找到对应页面的代码块进行按需加载。
      后来人们给他起了一个霸气的名字叫前端路由,成为了单页应用标配。
  • history模式
    • 我们先介绍一下H5新推出的两个神器:pushState与replaceState
      具体自行百度,简而言之,这两个神器的作用就是可以将url替换并且不刷新页面,好比挂羊头卖狗肉,http并没有去请求服务器该路径下的资源,一旦刷新就会暴露这个实际不存在的“羊头”,显示404。

那么如何去解决history模式下刷新报404的弊端呢,这就需要服务器端做点手脚,将不存在的路径请求重定向到入口文件(index.html),前后端联手,齐心协力做好“挂羊头卖狗肉”的完美特效。

总之,pushState方法不会触发页面刷新,只是导致history对象发生变化,地址栏会有反应。

history模式下,build之后本地 index.html 打开是无效的。

hash模式下,build之后本地 index.html 打开正常!

大牛回答:hash模式url里面永远带着#号,我们在开发当中默认使用这个模式。那么什么时候要用history模式呢?如果用户考虑url的规范那么就需要使用history模式,因为history模式没有#号,是个正常的url适合推广宣传。当然其功能也有区别,比如我们在开发app的时候有分享页面,那么这个分享出去的页面就是用vue或是react做的,咱们把这个页面分享到第三方的app里,有的app里面url是不允许带有#号的,所以要将#号去除那么就要使用history模式,但是使用history模式还有一个问题就是,在访问二级页面的时候,做刷新操作,会出现404错误,那么就需要和后端人员配合让他配置一下apache或是nginx的url重定向,重定向到你的首页路由上就ok啦。


$route 和 $router的区别

  • $route是“路由信息对象”,包括path,params,hash,query,fullPath,matched,name等路由信息参数。
  • 而$router是“路由实例”对象包括了路由的跳转方法,钩子函数等

路由跳转

  • 编程式( js跳转)this.$router.push()
  • 声明式(标签跳转)<router-link to=""></router-link>

路由的懒加载

import Vue from 'vue'
import Router from 'vue-router'

Vue.use(Router)

const routes = [ 
  {
  path:'/',
  component:resolve => require(['@/components/First'],resolve)
  }, 
  {
  path:'/first', 
  component:resolve => require(['@/components/First'],resolve)
  },
  {
  path:'/second',
  component: resolve => require(['@/components/Second'],resolve)
  }
 ] 
 //最后创建router 对路由进行管理,它是由构造函数 new vueRouter() 创建,接受routes 参数。 
  const router = new VueRouter({ 
  routes 
 }) 
   
 export default router;

按需加载会在页面第一次请求的时候,把相关路由组件块的js添加上;非按需加载则会把所有的路由组件块的js包打在一起。当业务包很大的时候建议用路由的按需加载(懒加载)。


路由的传参


<template>
  <div>
    <el-button type="primary" @click="pushTo1">按钮1</el-button>
    <el-button type="primary" @click="pushTo2">按钮2</el-button>
    <el-button type="primary" @click="pushTo3">按钮3</el-button>
  </div>
</template>
// query 传参
<script>
export default {
  name: 'officeHome',
  data () {
    return {};
  },
  methods: {
    pushTo1 () {
      this.$router.push({path: '/view/home', query: { username: 'liu', userId: 12 }});
    },
    pushTo2 () {
      this.$router.push({name: 'home', query: { username: 'liu', userId: 12 }});
    },
    pushTo3 () {
      // name 和 path 都有的情况下,以name为准
      this.$router.push({name: 'home', path: '/view/home', query: { username: 'liu', userId: 12 }});
    }
  }
};
</script>
// params 传参
<script>
export default {
  name: 'officeHome',
  data () {
    return {};
  },
  methods: {
    pushTo1 () {
      // 这种指定了路由的path,没有指定路由的name,会导致params失效
      this.$router.push({path: '/view/home', params: { username: 'liu', userId: 12 }});
    },
    // 使用params传递参数,必须指定Vue组件路由的name属性
    pushTo2 () {
      this.$router.push({name: 'home', params: { username: 'liu', userId: 12 }});
    },
    pushTo3 () {
      // name 和 path 都有的情况下,以name为准
      this.$router.push({name: 'home', path: '/view/home', params: { username: 'liu', userId: 12 }});
    }
  }
};
</script>

vue-router解决的问题

  • 监听URL的变化,并在变化前后执行相应的逻辑
  • 不同的URL对应不同的组件
  • 提供多种方式改变URL的API(URL的改变不能导致浏览器刷新)

v-if 和 v-show 的区别

  • v-if按照条件是否渲染,v-show是display的block或none;
  • v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用 v-show 较好;如果在运行时条件很少改变,则使用 v-if 较好。

在Vue中使用插件的步骤

  • 采用ES6的import … from …语法或CommonJS的require()方法引入插件
  • 使用全局方法Vue.use( plugin )使用插件,可以传入一个选项对象Vue.use(MyPlugin, { someOption: true })

vue-cli 工程技术集合介绍
使用技术

  • vue.js:vue-cli工程的核心,主要特点是 双向数据绑定 和 组件系统。
  • vue-router:vue官方推荐使用的路由框架。
  • vuex:专为 Vue.js 应用项目开发的状态管理器,主要用于维护vue组件间共用的一些 变量 和 方法。
  • axios( 或者 fetch 、ajax ):用于发起 GET 、或 POST 等 http请求,基于 Promise 设计。
  • vuex等:一个专为vue设计的移动端UI组件库。
  • 创建一个emit.js文件,用于vue事件机制的管理。
  • webpack:模块加载和vue-cli工程打包器。

vuex

  • state: 状态中心
  • mutations: 更改状态
  • actions: 异步更改状态
  • getters: 获取状态
  • modules: 将state分成多个modules,便于管理

vue-cli配置反向代理

vue-cli提供了配置反向代理的接口,即设置config/index.js中的proxyTable。配置如下:

dev: {
	......
	
	proxyTable: {
      '/api':{     //将www.exaple.com印射为/apis
        target:'https://www.exaple.com',     //跨域地址
        changeOrigin:true,       //是否跨域
        secure:false,        //是否使用https
        pathRewrite: {
          '^/api': '/api'       //匹配以/api为开头的请求地址,并使用/api替换
        }
      }
    }
}

在这里插入图片描述
在组件中调用接口示例(axios):

import axios from 'axios'

axios({
	method:'post',
	url:'/api/login',
	data:{
		username:'qwe',
		password:123456
	}
}).then();

上述示例请求的地址会被解析为https://www.exaple.com/api/login。如果proxyTable中pathRewrite配置为空,则请求的地址被解析为https://www.exaple.com/login

以上配置只是在开发环境(dev)中解决跨域。要解决生产环境的跨域问题,则在config/dev.env.js和config/prod.env.js里也就是开发/生产环境下分别配置一下请求的地址API_HOST,开发环境中我们用上面配置的代理地址api,生产环境下用正常的接口地址。配置代码如下:

module.exports = merge(prodEnv, {
  NODE_ENV: '"development"',     //开发环境
  API_HOST:"/api/"
})
module.exports = {
  NODE_ENV: '"production"',      //生产环境
  API_HOST:'"http://40.00.100.100:3002/"'
}

对反向代理解决跨域过程的理解

通过伪造请求使得http请求为同源的,然后将同源的请求发送到反向代理服务器上,由反向代理服务器去请求真正的url,这样就绕过直接请求真正的url导致跨域问题。


Vue 组件 data 为什么必须是函数

  • 每个组件都是 Vue 的实例。
  • 组件共享 data 属性,当 data 的值是同一个引用类型的值时,改变其中一个会影响其他

axios

get

 this.$axios.get("http://www.wwtliu.com/sxtstu/blueberrypai/getIndexBanner.php",{
      params:{
        type:'参数'
      }
 })
 .then(res=>{
   consoe.log(res)
 })
 .catch(error=>{
   console.log(error)
 })

post

this.$axios.post("http://www.wwtliu.com/sxtstu/blueberrypai/getIndexBanner.php",{
    typs:'参数'
  }  
)
.then(res=>{
console.log(res)
})
.catch(error=>{
console.log(error)
})

post请求注意:如果后台接收的数据格式是 form-data格式 : ?name=a&age=20 你需要进行转换

默认是 x-www-form-urlencoded格式: {name:‘a’,age:‘20’} 这种格式的

怎样转换 :node给我们提供了一个库 qs 我们先将qs引进来

import Qs from 'qs'

然后:Qs.stringify({转换参数})

 this.$axios.post("http://www.wwtliu.com/sxtstu/blueberrypai/getIndexBanner.php",Qs.stringify(
    {
      typs:'参数'
    }
  ))
  .then(res=>{
    this.msg=res.data.banner
  })
  .catch(error=>{
    console.log(error)
  });

axios封装

import axios from "axios";
 
export default {
    ajaxGet (api, cb) {
        axios.get(api)
            .then(cb)
            .catch(err => {
                console.log(err);
            })
    },
    ajaxPost (api, post, cb) {
        axios.post(api, post)
            .then(cb)
            .catch(err => {
                console.log(err);
            })
    },
}
// get请求
http.ajaxGet(url, res => {
     console.log(res)               
});
// post请求
http.ajaxPost(url, obj, res => {
     console.log(res)               
});

vue的SEO优化问题

常用解决方案有3种

  1. 页面预渲染
  2. 服务端渲染
  3. 路由采用h5 history模式

keep-alive

vue的内置组件。通过<keep-alive> 包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。

使用场景

一般用于缓存路由组件


// 方式一:vue文件中
<keep-alive>
    <router-view></router-view>
</keep-alive>
 
// 方式二:router.js中
{
   path: '/as',
    icon: 'earth',
    title: '赠品管理',
    name: 'as',
    component: Main,
    children: [{
        path: 'a',
        title: '赠品管理',
        name: 'a',
        component: () =>
            import ('@/views/a/index.vue'),
        meta:{
            keepAlive:true
        }
    }]
}
// 可以使用v-if通过路由元信息判断缓存哪些路由
 <keep-alive>
     <router-view v-if="$route.meta.keepAlive">
         <!--这里是会被缓存的路由-->
     </router-view>
 </keep-alive>
 <router-view v-if="!$route.meta.keepAlive">
     <!--因为用的是v-if 所以下面还要创建一个未缓存的路由视图出口-->
 </router-view>
 //router配置
 new Router({
   routes: [
     {
       path: '/',
       name: 'home',
       component: Home,
       meta: {
         keepAlive: true // 需要被缓存
       }
     },
     {
       path: '/edit',
       name: 'edit',
       component: Edit,
       meta: {
         keepAlive: false // 不需要被缓存
       }
     }
   ]
 });

属性

  • include - 字符串或正则表达式。只有名称匹配的组件会被缓存。
  • exclude - 字符串或正则表达式。任何名称匹配的组件都不会被缓存。
  • max - 数字。最多可以缓存多少组件实例。一旦这个数字达到了,在新实例被创建之前,已缓存组件中最久没有被访问的实例会被销毁掉。
<!-- 逗号分隔字符串 -->
<keep-alive include="a,b">
  <component :is="view"></component>
</keep-alive>

<!-- 正则表达式 (使用 `v-bind`) -->
<keep-alive :include="/a|b/">
  <component :is="view"></component>
</keep-alive>

<!-- 数组 (使用 `v-bind`) -->
<keep-alive :include="['a', 'b']">
  <component :is="view"></component>
</keep-alive>

生命周期

  • activated在组件第一次渲染时会被调用,之后在每次缓存组件被激活时调用
  • deactivated:组件被停用(离开路由)时调用

注意:使用了keep-alive就不会调用beforeDestroy(组件销毁前钩子)和destroyed(组件销毁),因为组件没被销毁,被缓存起来了。


  • 2
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue面试题下载指的是在面试前准备过程中下载一些相关的Vue面试题目。以下是对于Vue面试题2023下载的回答: 在进行Vue面试时,希望能够提前了解到一些常见的Vue面试题,以便更好地准备自己的面试策略和回答技巧。对于Vue面试题2023的下载,可以通过以下途径来获取相关的题目和答案: 1. 在网上搜索:通过搜索引擎,输入关键词"Vue面试题2023下载",可以找到一些相关的网站和资源,可以下载一些Vue面试题的PDF或者文档,在准备面试的过程中参考学习。 2. 在技术论坛和社区:一些技术论坛和社区会有一些Vue的讨论区,里面会有一些人分享一些自己准备面试的经验和资料,可以在这些地方提问,查找相关资源。 3. 参考优秀的面试指南:有一些优秀的面试指南会提供一些常见的面试题目,以及对应的答案和解析,可以在这些指南中找到一些Vue面试题目。 4. 提问老师和同学:如果你正在参加培训课程或者有老师和同学在学习Vue,可以向他们请教一些往年的Vue面试题目,或者是通过共享资料的方式获取相关题目。 总之,下载Vue面试题目是为了更好地准备面试,提前了解可能会被面试官问到的问题,从而提高回答的质量和准确性。但是在复习过程中,不仅要关注理论知识,还要编写代码来巩固和运用所学内容。平时需要多写一些Vue的项目和案例,提高自己的实际操作能力。希望以上回答对您有帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值