VUE面试题系列02,前端面试题

16、动态路由传参2种方式params与query

一、格式的区别

1)、params

声明式:
<router-link :to="{ name: 'user', params: { id: 123 }}">User</router-link>
编程式:
$router.push({ name: 'user', params: { id: '123' }})

 //模板里的写法:
 $route.params.参数名
 
 //脚本里的写法:
 this.$route.params.参数名

动态路由匹配也行。

1)、路由配置:{ path: '/user/:id', component: User }

2)、传参:

//声明式 <router-link to="/user/01001">用户01001的信息</router-link> //编程式 $router.push("/user/01001");

3)、接值:

//模板里的写法: $route.params.参数名

//脚本里的写法: this.$route.params.参数名

2)、query

传:

// 带查询参数,变成 /register?plan=private
$router.push({ path: '/register', query: { plan: 'private' }})
注意:如果提供了 path,那么params 会被忽略

接:

 //模板里的写法:
 $route.query.参数名 
 //脚本里的写法:
 this.$route.query.参数名

二、使用场景的区别:

1、params:在传递一个参数时使用,如果参数多的话,地址栏上不利于阅读

2、query:在传递多个参数时使用,地址栏比params好阅读

17、vue实例和vue组件写法的区别

1、 data是个函数(面试题) 一个组件的 data 选项必须是一个函数,且要有返回object,只有这样,每个实例(vue组件对象)就可以维护一份被返回对象的独立的拷贝,否则组件复用时,数据相互影响,也就是说,组件的作用域是独立的。

2、组件模板(html代码)只能有一个根标签

3、组件名不可和html官方的标签名同名

4、组件没有el选项,只有根实例存在el

5、书写:组件名如果驼峰,那么使用时,用短横线(羊肉串的写法)

18、谈谈你对vueX的理解

1、vueX是干什么的

vuex能够保存全局数据,供整个应用使用,可以在组件之间传递数据。

vuex保存的数据是响应式的

vuex保存的数据可以跟踪状态的变化

2、vueX的核心概念

state : 数据仓库 ,存储所有的 共享数据 ,相当于vue组件里的data

getter : 在state的基础上 派生的数据, 相当于vue组件里 computed

mutation:修改state的数据时,用mutation,这与跟踪状态 有关系

action:解决mutation里只能有同步代码的问题,action里可以有异步代码

3、vueX的数据流

组件里 dispatch(派发)vueX中的 action,action里commit(提交)mutation,mutation里修改state。state被修改后,会响应式到组件上。

4、辅助函数

现在的面试,都会问的比较多。而且在项目中大部分都会使用辅助函数来简化项目中的代码。

有了这些辅助函数后,在组件里,不用再写$store了。

mapState:把vuex中state(状态)映射(合并)到组件对象的computed上。直接使用计算属性就可以拿到vuex的状态

mapGetters:把vueX的getters映射到组件的computed上。

mapMutations:把vueX的mutations映射到组件的methods上。

mapActions: 把vueX的actions映射到组件的methods上。

示例代码

//1、vueX
export default new vueX.Store({
   state:{
       count:10
   }
})

//2、组件里
import { mapState } from "vuex";

export default {
  name: "Store01",
  data() {
    return {};
  },
  computed:{        
        ...mapState(['count']), //把vuex的state映射到组件的计算属性上
        a:function(){
            return 250;
        },
    }
};

5、modules

       当项目比较大时,所有的全局数据存放在state里,会非常混乱,怎么办?使用module,把数据分门别类的进行处理,即:模块化。 每个模块是一个独立的store。然后由总体的store引入所有的分模块store。

示例代码:

//1、moduleA.js  此模块里管理的数据是 count。

export default {
    namespaced:true, //这个命名空间是区分不同模块的
    state:{
        count:1
    },
    mutations:{
       ……………………
    },
    actions:{        
        incCount(context){
            console.log("moduleA的action");
            setTimeout(()=>{
                context.commit("incCount");
            },2000);
        }
    }
}

2、创建vueX.store对象


import moduleA from "./moduleA";

export default new vueX.Store({
    modules:{
        moduleA:moduleA
    }
    //简写:
    modules:{
        moduleA,moduleB
    }
});


//2、组件里派发action时,加上namespaced,用来区分不同的模块

this.$store.dispatch('moduleA/incCount');//moduleA就是模块名。保证派发的是moduleA里的incCount。

19、vue路由懒加载

vue的SPA(Single Page Application)应用里,当(webpack)打包构建时,会把所有的js打在一起,JavaScript 包会变得非常大,并在第一次请求时全部下载完毕,影响页面加载(性能)。如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就更加高效了。

目前有三种方式实现路由组件的懒加载,分别是:

  • vue异步组件

  • es 的 import()

  • webpack的require.ensure()

1)、 vue异步组件

把路由配置,进行修改

{
​
    path: '/shopcar',
​
    name: 'shopcar',
​
    component: resolve => require(['@/pages/ShopCar'],resolve)
​
},

1)、运行是打开chrome的network,就会看到进入路由 /shopcar 时,会多出另外 一个js文件。一般是0.js或者1.js

2)、用npm run build打包时,wepback就会多打了一个 js文件(如:0.b5a82d6947b2e30edcc8.js),这个js文件就是把ShopCar文件进行了单独打包。同样的在network里,就会看到进入路由 /shopcar 时,多出一个单独的js文件的请求

注:这种方式,webpack会把每个异步组件单独打成一个js文件。

2)、es的import()

主要是把原来的引入方式进行修改 ,路由配置就不用改了:

1、不指定webpackChunkName,每个组件单独打一个js文件

原来是:import ShopCar from '@/pages/ShopCar'

修改后:const ShopCar = () => import('@/pages/ShopCar');

修改后的做法是定义了一个函数,由于函数不调用不执行,所有,一开始时,并不会引入该组件,只有路由跳转时才会调用该函数。

2、指定webpackChunkName,相同的webpackChunkName就会打在同一个js文件里

1)、以下两个组件的webpackChunkName相同,所以,打在一个js文件里

const ShopCar = () => import(/* webpackChunkName: 'demot' */ '@/pages/ShopCar');
​
const GoodsDetailPage = () => import(/* webpackChunkName: 'demot' */ '@/pages/GoodsDetailPage');

2)、下面这个组件的webpackChunkName和上面两个不一样,所以,单独打在一个js文件里

const Login = () => import(/* webpackChunkName: 'demoty' */ '@/pages/Login');

3)、webpack的require.ensure()

这种方式,只改路由配置即可。

如:

{
​
    path: '/GoodsDetailPage',
​
    name: 'GoodsDetailPage',
​
    component: r => require.ensure([], () => r(require('@/pages/GoodsDetailPage')), 'demot')
​
},
​
{
​
    path: '/Login',
​
    name: 'Login',
​
    component: r => require.ensure([], () => r(require('@/pages/Login')), 'demot')
​
},
​
{
​
    path: '/shopcar',
​
    name: 'shopcar',
    
    component: r => require.ensure([], () => r(require('@/pages/ShopCar')), 'demoty')
​
},

以上代码中,我把Login和GoodsDetailPage使用了相同的chunkName

20、MV*(MVC,MVP,MVVM)

答:

这是项目的架构模式。优点:耦合度低、重用性高、生命周期成本低、部署快、可维护性高、有利软件工程化管理。

1、MVC是从后端演变后的项目架构模式。

M:model,模型,主要完成业务功能,在数据库相关的项目中,数据库的增删改查属于模型(重点)。 V:view,视图,主要负责数据的显示 C:controller,控制器,主要负责每个业务的核心流程,在项目中体现在路由以及中间件上。

2、MVP

MVP是由MVC演变过来的。

P:Presenter 代替里C。

在MVP中View并不直接使用Model,而在MVC中View可以绕过Controller从直接Model中读取数据。

3、MVVM

MVVM是Model-View-ViewModel的缩写,MVVM模式把Presenter改名为ViewModel,基本与MVP模式相似。 唯一区别是:MVVM采用数据双向绑定的方式

在做vue的开发时,程序员写的代码和vue框架本身合起来是属于MVVM模式。

21、你了解Vue.js吗?

这种题,一般是比较难以回答的,问得很模糊,

如果不想多说,那就直接回答:了解并做过五个项目。

如果想回答详细的话,参考思路如下:

1)、vueJS是基于MVVM的JS框架

2)、有(常见的)13个指令:

3)、有(常见的)8个配置项:el,data,computed,watch,components,filter,directives,mixins

4)、vue实例生命周期分为四个阶段,八个生命周期函数

5)、vue做项目时会用到的全家桶技术:vueJS框架,vueX,vue-router,aixos,vant组件库等等

6)、我用vue框架一共做过五个项目。

………………………………

22、vue-router的两种路由模式的区别

路由模式分为两种:hash和history;通过设置vueRouter对象的mode属性来完成修改。

区别:

1)、外观上

hash模式时,路径上有#。

history模式时,路径上没有#。

2)、原理上

hash模式通过修改location.href来完成

使用锚点连接的思路,使用hash模式不会给后端发请求。当然,在hash值变化时,会同时触发window对象的onhashchange事件,并可以通过事件对象的oldURL属性和newURL属性 得到新旧URL。

<body>
    <div>
        <a href="#p01" >p01</a><br/>
        <a href="#p02" >p02</a><br/>
        <a href="#p03" >p03</a>
    </div>
    <br/><br/><br/><br/><br/><br/>
    <a name="p01">我是第一个p</a>
    <br/><br/><br/><br/><br/><br/>
    <a name="p02">我是第二个p</a>
    <br/><br/><br/><br/><br/><br/>
    <a name="p03">我是第三个p</a>
    <br/><br/><br/><br/><br/><br/>
</body>
</html>
<script>
window.onhashchange = function(event){
    console.log("旧url",event.oldURL);
    console.log("新的url",event.newURL);
}
</script>

2)、通过修改history.pushState来完成

如:

window.history.pushState(null,null,"p01.html");
window.location.reload();//想测试的话,尽量加上这句话,要不然,地址变了,但是页面并没有出现。

history模式会给后端发请求(如果刷新当前页面的话),一旦,后端和前端提供了同样的路径,那么,浏览器的请求结果就会有问题,到底是后端的资源还是前端的资源(不同的后端处理思路不停),还好,我们一般在后端apiserver的请求路径的前面习惯性的有个 /api。

所以,由于不同服务端的处理思路不同。所以,需要在服务端增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面(单页面),这个页面就是你 app 依赖的页面。否则,就会返回404。

你可以改成history的模式,测试一下,如果刷新当前页面,那么,浏览器会朝后端发送请求(给当前路径)。

23、Vue路由守卫的三种方式,及其钩子函数和参数

1)、全局守卫

全局守卫有前置守卫和后置守卫,是vueRouter对象的两个钩子函数,分别是 beforeEach和afterEach。

前置守卫:

router.beforeEach((to, from, next) => {
    //  to: 目标路由
    //  from: 当前路由
​
    // next() 跳转  一定要调用
    next(false);//不让走
    next(true);//继续前行
    next('/login')//走哪
    next({path:'/detail/2',params:{},query:{}})//带点货
 }

后置守卫:

router.afterEach((to,from)=>{
  //全局后置守卫业务
})

如果能够回答上过程,肯定有加分:

//过程: 1、请求一个路径:如:/Index 2、经历前置守卫 决定了能去哪个路径 3、根据去的路径,找对应component(路由配置) 4、经过后置守卫 5、创建组件

2)、路由独享守卫

写在路由配置里。钩子函数名:beforeEnter,只有前置守卫

如:

// src/router/index.js
{
  path: '/user',
  component: User,
  beforeEnter: (to,from,next)=>{ //路由独享守卫 前置 
    console.log('路由独享守卫');
    if(Math.random()<.5){
      next()
    }else{
      next('/login')
    }
  }
 }

3)、组件内部守卫

写在组件对象里。分别有前置守卫,后置守卫,路由改变守卫(当前组件被复用的情况,不是路径改变)三个钩子函数。

export default{
    data(){return {}}
  ……………………  
​
    //组件内部钩子
    beforeRouteEnter (to, from, next) {//前置
      // 不!能!获取组件实例 `this`
      // 因为当守卫执行前,组件实例还没被创建
    },
    beforeRouteUpdate (to, from, next) {
      // 在当前路由改变,但是该组件被复用时调用
      // 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
      // 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
      // 可以访问组件实例 `this`
    },
    beforeRouteLeave (to, from, next) {//后置
      // 导航离开该组件的对应路由时调用
      // 可以访问组件实例 `this`
    }
}
  • 19
    点赞
  • 81
    收藏
    觉得还不错? 一键收藏
  • 9
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值