前端面试锦集第四期:讲好自己的故事

2022-07-15 10:01:16 浏览数 (1)

这里记录面试及工作中遇到的知识点及问题,问题没有顺序,想到哪写到哪,每周五发布。

封面图

面试只是起点,能力才是终局。

上周的周报生成器暂时就告一段落吧,最近也没时间去整理它。后续会修复相应的Bug,因为有很多想好的功能我还没加上去。

这几天一直在思考一个问题:我们应该具备一种能讲故事的能力,这种能力会在面试的时候起到很好的作用。

讲故事的能力

会讲故事,能讲故事,并不代表能把故事讲好。所以最近我一直在看《宰相刘罗锅》这部电视剧。

看一集,然后思考这一集都讲了哪些内容,然后试着回忆一下。然后试着讲给身边的人听。以此来锻炼自己讲故事的能力。

之所以提到这个讲故事的能力。是因为,从某些方面来讲,我们每次面试的时候,也可以理解为在给面试官讲我们自己的故事。

我做了哪些事儿,这些事儿是基于怎么样的背景,我通过某种途径的努力,最后得出了一个什么样的结果。

仔细想想,确实是在讲一个关于自己的故事。

除了自己的故事,当然还有技术上的故事。技术上的故事,就需要看看我们对某些技术的理解程度了。

单纯的面试题,我们可以死记硬背。但是基于这项技术我们可以做哪些事儿?能如何扩展?就真的需要我们去花时间更加深刻的理解这些技术点。

比如我们接下来试着聊一下vue相关的内容,谈到Vue,我们能够想到哪些内容呢?我们不应该只想到那些博客文章里提到的零散的面试题,而是应该逐渐的将其系统化,深刻的理解到我们的脑子里。

Vue相关的内容

下面这些内容,大概聊一下Vue相关的知识,不涉及大量代码,只谈理论,想到哪写到哪。

一图胜千言:

如果简单罗列Vue相关的技术点,那么我觉的上面的图足以覆盖绝大部分技术点了,当然了,我们不考虑特别细的技术点。

说白了就是四个文档。Vue官方文档,Vue-Router官方文档,Vuex官方文档和Vue-cli的文档。

Vue官方文档

先说Vue的官方文档。这个文档里都讲了哪些内容呢?简单罗列如下:

  • 计算属性和侦听器
  • class和Style绑定
  • 条件渲染 v-if 和 v-show
  • 列表渲染 v-for
    • key
    • 数组方法 push pop shift unshift splice sort reverse
  • 事件处理 v-on
  • 表单绑定 双向绑定 v-modal
  • 组件
    • 定义组件 Vue.cmponent()
    • 数据传递 props
    • 监听子组件事件 $emit,v-modal
    • 内容插槽 slot
    • 动态组件
  • 自定义事件 $(emit)
  • 响应式原理
  • 异步更新队列

然后你会发现,面试常问的问题都在里面。

  1. computed 和 watch 的区别?
  2. v-if 和 v-show 的区别?
  3. key的作用?
  4. 父子组价传参的方式?
  5. 响应式原理?
  6. 异步消息队列?

知道了这些,我们继续思考一个问题。文档里讲的这些内容里,哪些才是核心呢? 或者说你理解的Vue的核心是什么呢?

在我看来,如果把整个项目看成是一个Vue的实例,那么我们可以理解它是一个大的组件。组件中嵌套了很多个子组件。

组件是由元素组成的,元素是虚拟Dom创建的。所以Vue核心还是虚拟Dom

从另外一方面考虑,大部分人平时写的基于Vue的项目,都是基于模板文件创建的。如下:

代码语言:javascript复制
<template>
  <div>this is content to be render</div>
</template>
<script>
export default {
  data(){
    return {

    }
  },
  created(){

  },
  methods:{

  }
}
</script>
<style>
.demo{
  background:#ddd;
}
</style>

Vue会对这个模板进行三个操作:

  • 解析并渲染html模板
  • 解析并执行js
  • 解析并渲染css

而这三个操作其实也是对虚拟dom的解析。并且双向绑定,props,computed,watcher等一系列的概念都是对虚拟Dom的解析中产生的。

而全局api如:el,emit ,remove,watch等,其实就是在vue的原型对象上挂载的一系列的方法而已。

再说Vue-Router

Vue-Router官方文档

Vue-Router的文档非常简单,介绍了Vue-Router的使用方法。大致有以下内容:

  • 动态路由
  • 嵌套路由
  • 命名视图
  • 路由参数
  • 编程导航
  • 路由模式
  • 路由守卫

其中动态路由,嵌套路由,编程导航等都是我们在项目里经常使用的内容。路由守卫大部分的时候用不用其实无关紧要。

我想说的是:命名视图这个内容大家用的应该非常少。但是这个内容我觉得应该会有很多场景以后会用到。

一个我们没有注意过的问题是:

LinkRouter-View 这连个组件其实是Vue-Router给我们封装的两个全局组件。

有兴趣的话可以去查看源码。其实就是用Vue.component()注册了两个全局组件。

这两个组件我觉的是Vue-Router的核心之一。

另外一个比较核心的技术点是:如何捕获参数

通过this.route.params或this.route.query?

这只是表象。如果想真正弄明白这个问题,我觉我们至少需要搞明白下面这几个概念:

  • router
  • route
  • matcher
  • history

这些概念也需要我们自己去源码中寻找答案。

暂且我们只需要知道,我们项目里使用的路由,其实是VueRouter的一个实例对象,并且我们可以用这个对象的提供的api对这个路由进行扩展就可以了。

动态扩展路由,意为着我们可以做更多的事儿。比如我么可以整个微服务之类的,如果业务上需要的话。

接下来就到了Vuex

Vuex

Vuex致力于解决两个问题:

  • 多个视图依赖统一状态
  • 不同视图需要改变同一状态

当然,解决这两个问题的方案有很多。比如:

  • 全局变量
  • 本地缓存

但是基于Vue的话,vuex还是最好的选择。

简单说下对几个概念的理解:

  • statemodule

可以把state理解为一个全局的对象,module可以将state拆分成不同的模块儿,模块儿通过module收集器(ModuleCollection)进行重组,module收集器是一个类,可以获取命名空间,注册和更新module。

  • mapState

mapState的写法通常如下:

代码语言:javascript复制
// mapState
  computed: mapState({
    products: state => state.products.all
  }),

从这个写法中,我们可以看出来,mapStated的主要作用是将state中的属性映射称为vue实例的属性,确切的说是computed属性。

mapActions,mapMutations,mapGettersmapState的作用类似,mapActions将store中的actions中定义的action行为,映射为vue的方法,示例如下:

代码语言:javascript复制
// store 的action
const actions = {
// addProductToCart
   addProductToCart ({ state, commit }, product) {
    commit('setCheckoutStatus', null)
    if (product.inventory > 0) {
      const cartItem = state.items.find(item => item.id === product.id)
      if (!cartItem) {
        commit('pushProductToCart', { id: product.id })
      } else {
        commit('incrementItemQuantity', cartItem)
      }
      // remove 1 item from stock
      commit('products/decrementProductInventory', { id: product.id }, { root: true })
    }
  }

}
// 组件中写法
  methods: mapActions('cart', [
    'addProductToCart'
  ]),
  • mapGetters

个人对mapGetters的理解是,它的应用场景是将复杂的逻辑运算提到了store或者叫vuex中,从而避免了在页面组件中写过多的运算逻辑。

而事实上也确实如此:

代码语言:javascript复制
// store中的getter
// getters
const getters = {
  cartProducts: (state, getters, rootState) => {
    return state.items.map(({ id, quantity }) => {
      const product = rootState.products.all.find(product => product.id === id)
      return {
        title: product.title,
        price: product.price,
        quantity
      }
    })
  },
}
// 组件中
 computed: {
    ...mapGetters('cart', {
      products: 'cartProducts',
    })
  },

下周接着聊吧,还有个cli...

0 人点赞