这里记录面试及工作中遇到的知识点及问题,问题没有顺序,想到哪写到哪,每周五发布。
封面图
面试只是起点,能力才是终局。
上周的周报生成器
暂时就告一段落吧,最近也没时间去整理它。后续会修复相应的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)
- 响应式原理
- 异步更新队列
然后你会发现,面试常问的问题都在里面。
- computed 和 watch 的区别?
- v-if 和 v-show 的区别?
- key的作用?
- 父子组价传参的方式?
- 响应式原理?
- 异步消息队列?
知道了这些,我们继续思考一个问题。文档里讲的这些内容里,哪些才是核心呢
? 或者说你理解的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的使用方法。大致有以下内容:
- 动态路由
- 嵌套路由
- 命名视图
- 路由参数
- 编程导航
- 路由模式
- 路由守卫
其中动态路由
,嵌套路由
,编程导航
等都是我们在项目里经常使用的内容。路由守卫
大部分的时候用不用其实无关紧要。
我想说的是:命名视图
这个内容大家用的应该非常少。但是这个内容我觉得应该会有很多场景以后会用到。
一个我们没有注意过的问题是
:
Link
和Router-View
这连个组件其实是Vue-Router
给我们封装的两个全局组件。
有兴趣的话可以去查看源码。其实就是用Vue.component()
注册了两个全局组件。
这两个组件我觉的是Vue-Router的核心之一。
另外一个比较核心的技术点是:如何捕获参数
。
通过this.route.params或this.route.query?
这只是表象。如果想真正弄明白这个问题,我觉我们至少需要搞明白下面这几个概念:
- router
- route
- matcher
- history
这些概念也需要我们自己去源码中寻找答案。
暂且我们只需要知道,我们项目里使用的路由,其实是VueRouter的一个实例对象,并且我们可以用这个对象的提供的api对这个路由进行扩展就可以了。
动态扩展路由,意为着我们可以做更多的事儿。比如我么可以整个微服务
之类的,如果业务上需要的话。
接下来就到了Vuex
。
Vuex
Vuex致力于解决两个问题:
- 多个视图依赖统一状态
- 不同视图需要改变同一状态
当然,解决这两个问题的方案有很多。比如:
- 全局变量
- 本地缓存
但是基于Vue的话,vuex还是最好的选择。
简单说下对几个概念的理解:
state
和module
可以把state
理解为一个全局的对象,module
可以将state拆分成不同的模块儿,模块儿通过module收集器(ModuleCollection)
进行重组,module收集器是一个类,可以获取命名空间,注册和更新module。
mapState
mapState的写法通常如下:
代码语言:javascript复制// mapState
computed: mapState({
products: state => state.products.all
}),
从这个写法中,我们可以看出来,mapStated的主要作用是将state中的属性映射称为vue实例的属性,确切的说是computed属性。
mapActions
,mapMutations
,mapGetters
和mapState
的作用类似,mapActions将store中的actions中定义的action行为,映射为vue的方法,示例如下:
// 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...