此题属于实践题,考察大家对vue常用api使用熟练度,答题时不仅要列出这些解决方案,同时最好说出他们异同
答题思路:
mixins
、extends
、composition api
slots
;vue3
中新引入的composition api
带来的变化回答范例:
mixins
,slots
,extends
等mixins
是分发 Vue
组件中可复用功能的非常灵活的方式。混入对象可以包含任意组件选项。当组件使用混入对象时,所有混入对象的选项将被混入该组件本身的选项// 复用代码:它是一个配置对象,选项和组件里面一样
const mymixin = {
methods: {
dosomething(){
}
}
}
// 全局混入:将混入对象传入
Vue.mixin(mymixin)
// 局部混入:做数组项设置到mixins选项,仅作用于当前组件
const Comp = {
mixins: [mymixin]
}
vue
组件中的内容分发,也可以用于组件扩展子组件Child
<div>
<slot>这个内容会被父组件传递的内容替换slot>
div>
父组件Parent
<div>
<Child>来自父组件内容Child>
div>
如果要精确分发到不同位置可以使用具名插槽
,如果要使用子组件中的数据可以使用作用域插槽
extends
,也可以起到扩展组件的目的// 扩展对象
const myextends = {
methods: {
dosomething(){
}
}
}
// 组件扩展:做数组项设置到extends选项,仅作用于当前组件
// 跟混入的不同是它只能扩展单个对象
// 另外如果和混入发生冲突,该选项优先级较高,优先起作用
const Comp = {
extends: myextends
}
vue3
中引入的composition api
,可以很好解决这些问题,利用独立出来的响应式模块可以很方便的编写独立逻辑并提供响应式的数据,然后在setup
选项中组合使用,增强代码的可读性和维护性。例如// 复用逻辑1
function useXX() {
}
// 复用逻辑2
function useYY() {
}
// 逻辑组合
const Comp = {
setup() {
const {
xx} = useXX()
const {
yy} = useYY()
return {
xx, yy}
}
}
题目分析
mutations
和actions
是vuex
带来的两个独特的概念。新手程序员容易混淆,所以面试官喜欢问。mutations
,actions
只能通过提交mutation
修改状态即可回答范例
Vuex
的 store
中的状态的唯一方法是提交 mutation
,mutation
非常类似于事件:每个 mutation
都有一个字符串的类型 (type
)和一个 回调函数 (handler
) 。Action
类似于 mutation
,不同在于:Action
可以包含任意异步操作,但它不能修改状态, 需要提交mutation
才能变更状态action
;需要直接修改状态则提交mutation
。但由于dispatch
和commit
是两个API
,容易引起混淆,实践中也会采用统一使用dispatch action
的方式。调用dispatch
和commit
两个API
时几乎完全一样,但是定义两者时却不甚相同,mutation
的回调函数接收参数是state
对象。action
则是与Store
实例具有相同方法和属性的上下文context
对象,因此一般会解构它为{commit, dispatch, state}
,从而方便编码。另外dispatch
会返回Promise
实例便于处理内部异步结果commit(type)
方法相当于调用options.mutations[type](state)
;dispatch(type)
方法相当于调用options.actions[type](store)
,这样就很容易理解两者使用上的不同了实现
我们可以像下面这样简单实现commit
和dispatch
,从而辨别两者不同
class Store {
constructor(options) {
this.state = reactive(options.state)
this.options = options
}
commit(type, payload) {
// 传入上下文和参数1都是state对象
this.options.mutations[type].call(this.state, this.state, payload)
}
dispatch(type, payload) {
// 传入上下文和参数1都是store本身
this.options.actions[type].call(this, this, payload)
}
}
前端vue面试题详细解答
分析
递归组件我们用的比较少,但是在Tree
、Menu
这类组件中会被用到。
体验
组件通过组件名称引用它自己,这种情况就是递归组件
<template>
<li>
<div> {
{ model.name }}div>
<ul v-show="isOpen" v-if="isFolder">
<TreeItem
class="item"
v-for="model in model.children"
:model="model">
TreeItem>
ul>
li>
<script>
export default {
name: 'TreeItem',
// ...
}
script>
回答范例
Tree
、Menu
这类组件,它们的节点往往包含子节点,子节点结构和父节点往往是相同的。这类组件的数据往往也是树形结构,这种都是使用递归组件的典型场景。name
属性,用来查找组件定义,如果使用SFC
,则可以通过SFC
文件名推断。组件内部通常也要有递归结束条件,比如model.children
这样的判断。resolveComponent
,这样实际获取的组件就是当前组件本身原理
递归组件编译结果中,获取组件时会传递一个标识符 _resolveComponent("Comp", true)
const _component_Comp = _resolveComponent("Comp", true)
就是在传递maybeSelfReference
export function resolveComponent(
name: string,
maybeSelfReference?: boolean
): ConcreteComponent | string {
return resolveAsset(COMPONENTS, name, true, maybeSelfReference) || name
}
resolveAsset
中最终返回的是组件自身:
if (!res && maybeSelfReference) {
// fallback to implicit self-reference
return Component
}
解决跨域的方法有很多,下面列举了三种:
而在vue
项目中,我们主要针对CORS
或Proxy
这两种方案进行展开
CORS
CORS (Cross-Origin Resource Sharing,跨域资源共享)是一个系统,它由一系列传输的HTTP头组成,这些HTTP头决定浏览器是否阻止前端 JavaScript 代码获取跨域请求的响应
CORS
实现起来非常方便,只需要增加一些 HTTP
头,让服务器能声明允许的访问来源
只要后端实现了 CORS
,就实现了跨域
以koa
框架举例
添加中间件,直接设置Access-Control-Allow-Origin
响应头
app.use(async (ctx, next)=> {
ctx.set('Access-Control-Allow-Origin', '*');
ctx.set('Access-Control-Allow-Headers', 'Content-Type, Content-Length, Authorization, Accept, X-Requested-With , yourHeaderFeild');
ctx.set('Access-Control-Allow-Methods', 'PUT, POST, GET, DELETE, OPTIONS');
if (ctx.method == 'OPTIONS') {
ctx.body =