2023高频前端面试题-vue

news2025/1/13 8:07:16

1. 什么是 M V VM

Model-View-ViewModel 模式
在这里插入图片描述

Model 层: 数据模型层

通过 Ajaxfetch 等 API 完成客户端和服务端业务模型的同步。

View 层: 视图层

作为视图模板存在,其实 View 就是⼀个动态模板。

ViewModel 层: 视图模型层

负责暴露数据给 View 层,并对 View 层中的数据绑定声明、 指令声明、 事件绑定声明, 进行实际的业务逻辑实现。

数据变化了, 视图自动更新 => ViewModel 底层会做好监听 Object.defineProperty,当数据变化时,View 层会自动更新

视图变化了, 绑定的数据自动更新 => 会监听双向绑定的表单元素的变化,⼀旦变化,绑定的数据也会得到⾃动更新。

2. MVVM 的优缺点有哪些?

优点

  1. 实现了视图(View)和模型(Model)的分离,降低代码耦合、提⾼视图或逻辑的复⽤性

  2. 提⾼了可测试性:ViewModel 的存在可以帮助开发者更好地编写测试代码

  3. 能⾃动更新 DOM:利⽤双向绑定,数据更新后视图⾃动更新,让开发者从繁琐的⼿动操作 DOM 中解放出来

缺点

  1. Bug 难被调试:因为使⽤了双向绑定的模式,当我们看到界⾯发生异常了,有可能是 View 的代码产生的 Bug,

    也有可能是 Model 代码的问题。数据绑定使得⼀个位置的 Bug 被快速传递到别的位置,

    要定位原始出问题的地⽅就变得不那么容易了

    可采用的调试方案:

    (1) 注释掉一段代码, 确定代码的位置

    (2) debugger 打断点 或者 console 进行调试

  2. 在⼀个⼤的模块中 Model 也会很⼤,虽然使⽤上来说⽅便了,但如果⻓期持有不释放内存,就会造成更多的内存消耗

    占用的是 浏览器的 内存

3. 谈谈对 Vue 生命周期的理解?

生命周期的概念

每个 Vue 实例(每个组件也都是一个 vue 实例)都有⼀个完整的⽣命周期:

  1. 开始创建 (空实例)
  2. 初始化数据
  3. 编译模版
  4. 挂载 DOM
  5. 渲染、更新数据 => 重新渲染
  6. 卸载

这⼀系列过程我们称之为 Vue 的⽣命周期。

各个生命周期的作用

生命周期执行时机
beforeCreate在组件实例被创建之初、组件的属性⽣效之前被调用
created在组件实例已创建完毕。此时属性也已绑定,但真实 DOM 还未⽣成,$el 还不可⽤
beforeMount在组件挂载开始之前被调⽤。相关的 render 函数⾸次被调⽤
mounted在 el 被新建的 vm.$el 替换并挂载到实例上之后被调用
beforeUpdate在组件数据修改了, 视图更新之前调⽤。发⽣在虚拟 DOM 打补丁之前
updated在组件数据修改了, 视图更新之后被调用
activited在组件被激活时调⽤(使用了 <keep-alive> 的情况下)
deactivated在组件被停用时调⽤(使用了 <keep-alive> 的情况下)
beforeDestory在组件销毁前调⽤ (销毁: vue 默认会进行释放掉实例所有的监听, 释放掉所有的组件…)
destoryed在组件销毁后调⽤ (像定时器, webscoket 连接, … 跟 vue 没有太大关联的资源, 需要手动释放!)

生命周期示意图
在这里插入图片描述

4. 在 Vue 中网络请求应该放在哪个生命周期中发起?

至少在 created 之后, 因为数据才基本初始化完毕, 当然 mounted 中也可以 (比 created 稍晚一些)

5. Vue 组件之间如何进行通信?

父传子, 子传父, 非父子, Vuex

5.1 props 和 $emit

(1) 通过 props 将数据在组件树中进行⾃上⽽下的传递;

<jack :money="count" :obj="myobj"></jack>
export default {
  // props: ['money']
  props: {
    money: {
      type: Number,
      default: 1,
    },
    obj: {
      type: Object,
      default: () => {
        return {
          name: "zs",
          age: 18,
        };
      },
    },
  },
};

附件: props 验证

(2) 通过 $emit@ 来作信息的向上传递。

this.$emit('add-action', 参数1, 参数2, ...)
<jack @add-action="fatherFn"></jack>

5.2 eventBus 事件总线

可通过 EventBus 进⾏信息的发布与订阅。 (创建一个都能访问到的事件总线)

Vue.prototype.$eventBus = new Vue(); // this.$eventBus
// A组件中, 监听 bus的事件
this.$eventBus.$on('事件名', function(参数1, 参数2, ...) {
	...
})

// B组件中, 触发 bus的事件
this.$eventBus.$emit('事件名', 参数1, 参数2, ...)

5.3 $children $parent $refs

(1) $children

父组件中, $children 返回的是一个组件集合,如果你能清楚的知道子组件的顺序,你也可以使用下标来操作

// 父组件中
<template>
  <div class="hello_world">
    <com-a></com-a>
    <com-b></com-b>
  </div>
</template>

this.$children[0] => <com-a></com-a>

this.$children[1] => <com-b></com-b>

(2) $parent

子组件中, this.$parent 指向父组件

this.$parent.xxx = 200

this.$parent.fn()

(3) $refs

通过添加 ref 和 $refs 配合, 也可以很方便的获取子组件, 访问调用子组件的属性或方法

// 父组件中
<template>
  <div class="hello_world">
    <com-a ref="coma"></com-a> // this.$refs.coma.count = 200
    <com-b ref="comb"></com-b> // this.$refs.comb.addFn()
  </div>
</template>

this.$refs.coma => <com-a></com-a>

this.$refs.comb => <com-b></com-b>

5.4 provide inject

**成对出现:**provide 和 inject 是成对出现的

作用:用于父组件向子孙组件传递数据

使用方法:

  • provide 在父组件中, 返回要传给下级的数据
  • inject 在需要使用这个数据的子孙组件中注入数据。(不论组件层次有多深)

父组件

export default {
  provide() {
    return {
      value: this.value, // 共享给子孙组件的数据
    };
  },
  data() {
    return {
      value: "父组件的数据",
      money: 100,
    };
  },
};

子孙组件

export default {
    inject: ['value'],
    props: {
        ...
    }
}

5.5 $attrs $listeners

在 Vue 2.4 版本中加⼊的 $attrs$listeners 可以用来作为跨级组件之间的通信机制。 (父传孙)

父组件

<template>
  <div>
    <my-child1 :money="100" desc='你好哇' @test1="fn1" @test2="fn2"></my-child1>
  </div>
</template>

子组件

<template>
  <div class="my-child1">
    <!-- $attrs => { "money": 100, "desc": "你好哇" } -->
    <div>{{ $attrs }}</div>
    <my-child2 v-bind="$attrs" v-on="$listeners"></my-child2>
  </div>
</template>

<script>
import MyChild2 from "./my-child2";
export default {
  created() {
    console.log(this.$listeners);
  },
  components: {
    MyChild2,
  },
};
</script>

在这里插入图片描述

孙组件

<template>
  <div>
    我是child2 - {{ money }} - {{ desc }}
    <button @click="clickFn">按钮</button>
  </div>
</template>

<script>
export default {
  props: ['money', 'desc'],
  methods: {
    clickFn () {
      this.$emit('test1', '嘎嘎')
      this.$emit('test2', '嘿嘿')
    }
  }
}
</script>

在这里插入图片描述

5.6 Vuex

全局状态管理库。可通过它来进行全局数据流的管理。

state: 存放数据

mutations: 存放操作数据的方法

actions: 存放一些异步操作 (也可以进行一些同步处理) 注意: actions 是不能直接修改 state 数据的, 需要提交 mutation

getters: 存放基于 state 计算出来的一些值 (计算属性)

modules: 分模块, 项目大了, 也推荐分模块管理 (同模块的 vuex 操作, 就会在一起)

注意点: 分模块了, 默认 muations, actions, getters 注册到全局的, 一般会开启命名空间

语法: namespaced: true

6. computed 和 watch 的区别是什么?

computed

  1. 它是计算属性。主要用于值的计算并一般会返回一个值。所以它更多⽤于计算值的场景
  2. 它具有缓存性。当访问它来获取值时,它的 getter 函数所计算出来的值会进行缓存
  3. 只有当它依赖的属性值发生了改变,那下⼀次再访问时才会重新调⽤ getter 函数来计算
  4. 它适⽤于计算⽐较消耗性能的计算场景
  5. 必须要有一个返回值

watch

  1. 它更多的是起到 “观察” 的作⽤,类似于对数据进行变化的监听并执行回调。

    主要⽤于观察 props 或 本组件 data 的值,当这些值发生变化时,执⾏处理操作

  2. 不一定要返回某个值

建议

  1. 当目的是进⾏数值计算,且依赖于其他数据,那么推荐使用 computed

  2. 当需要在某个数据发生变化的, 同时做⼀些稍复杂的逻辑操作,那么推荐使⽤ watch

7. Vue 双向绑定原理?

7.1 基本认知

在 Vue 2.x 中,利⽤的是 Object.defineProperty 去劫持对象的访问器(Getter、Setter),

当对象属性值发⽣变化时可获取变化,然后根据变化来作后续响应;(一个一个的劫持)

在 Vue 3.0 中,则是通过 Proxy 代理对象进⾏类似的操作。劫持的是整个对象, 只要对象中的属性变化了, 都能劫持到

7.2 Object.defineProperty 和 Proxy 的优缺点?

Proxy

  • 可以直接监听整个对象,⽽⾮是对象的某个属性

  • 可以直接监听数组的变化

  • 拦截⽅法丰富:多达 13 种,不限于get set deletePropertyhas 等。

    Object.defineProperty 强大很多

Object.defineProperty

  • 兼容性较好(可⽀持到 IE9)

8. 如何理解 Vue 的响应式系统?

(考察 MVVM) M: model 数据模型, V:view 视图模型, VM: viewModel 视图数据模型

双向:

  1. 视图变化了, 数据自动更新 => 监听原生的事件即可, 输入框变了, 监听输入框 input 事件
  2. 数据变化了, 视图要自动更新 => vue2 和 vue3

8.1 基本原理

vue2.0 数据劫持: Object.defineProperty (es5)

vue3.0 数据劫持: Proxy (es6)

分析 :此题考查 Vue 的 MVVM 原理

解答: Vue 的双向绑定原理其实就是 MVVM 的基本原理, Vuejs 官网已经说明, 实际就是通过 Object.defineProperty 方法 完成了对于 Vue 实例中数据的 劫持 , 通过对于 data 中数据 进行 set 的劫持监听, 然后通过 观察者模式 , 通知 对应的绑定节点 进行节点数据更新, 完成数据驱动视图的更新

简单概述 : 通过 Object.defineProperty 完成对于数据的劫持, 通过观察者模式, 完成对于节点的数据更新

8.2 观察者模式

观察者模式: 当对象间存在 一对多 关系时,则使用观察者模式(Observer Pattern)。

比如,当一个对象或者数据被修改时,则会自动通知依赖它的对象。

意图: 定义对象间的一种 一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

拍卖会的时候,大家相互叫价,拍卖师(Dep) 会观察 最高标价(利用 Object.defineProperty 监听),

一旦最高价变化了, 然后通知给其它竞价者(watcher 观察者 - 订阅者, 订阅了价格的变化),这就是一个观察者模式

下图为 Vue 框架在数据初始化中使用观察者模式的示意图:
在这里插入图片描述
在这里插入图片描述

Dep 要进行 依赖收集,并通过一个 subs 数组, 记录观察者 Watcher,

Watcher 分为 渲染 watcher、计算属性 watcher、侦听器 watcher 三种

收集依赖: 简单点说就是谁借了我的钱,我就把那个人 记下来 ,以后我的钱少了 我就通知他们说我没钱了

<div>
  <p>{{ msg }}</p>   // Watcher1(渲染), 依赖于msg
</div>

<div>
  <h1>{{ car }}</h1>   // Watcher2(渲染),  依赖于car
</div>

<div>
  <h1>{{ myMsg }}</h1>   // Watcher3(渲染), 依赖于myMsg
</div>

computed: {
  myMsg () {
    console.log('计算属性重新计算了')
    return this.msg + '20'  // Watcher4(计算属性中), 依赖于msg, msg变了重新计算
  }
}

watch: {
  msg (newValue) {
    console.log('新的msg', newValue) // Watcher5(侦听器), 将来msg变化, 这边要执行这个函数
  }
}

------------------------------------------------------------------

// 收集依赖 (dep结构有点类似于二维数组, (Map结构))   arr.type="msgDep"
dep: [
  msgDep: [Watcher5(侦听器), Watcher4(计算属性中), Watcher1(渲染)],
  carDep: [Watcher2(渲染)],
  myMsgDep: [Watcher3(渲染)]
]


// Watcher
{
  callback: Function, (数据变化后, 需要执行的回调)
  isRenderWatcher: Boolean, (是否是render的watcher, 是否要触发视图的更新, 往后放, 最后统一虚拟dom对比, 统一更新)
  ...
}

比如: 假定数据 money 变了, 那么没有任何与 money 相关的观察者, 就不需要进行任何更新操作, 也不需要执行任何的监视函数

然而: 假定数据 msg 变了, 就会通知到相关的 Watcher, 且优先通知侦听器 Watcher 和计算属性 Watcher, 后进行统一的渲染更新

  1. 通知侦听器 Watcher, 立刻执行配置的函数, console.log(‘新的 msg’, newValue)
  2. 通知计算属性 Watcher, 计算属性依赖的值变了, 需要重新计算
    且更新后, myMsg 变化了, 需要进行进行视图的渲染 (render) (— 要更新, 等着—)
  3. 通过到 watcher1, 渲染 Watcher (—要更新—)
  4. 最后统一进行, 新旧虚拟 dom 的对比, 完成视图的更新

当数据状态发生改变时,会被 Object.defineProperty 监听劫持到, 会通知到 Dep, 并根据收集的依赖关系,

让订阅者 Watcher 进行数据更新(update)操作 , 派发更新

总结概述: vue 采用的是观察者模式, 是一种一对多的关系, 一上来 vue 在解析渲染时, 会进行依赖收集, 会将渲染 watcher、计算属性 watcher、侦听器 watcher, 都收集到对应的 dep 中, 将来 Object.defineProperty 监听到数据变化, 就根据依赖关系, 派发更新

9. Vue 中的 key 到底有什么用?

key 是为 Vue 中的虚拟 DOM 节点(vNode)标记唯⼀性的 id。

9.1 key 的作用

作用: 给虚拟 dom 添加标识, (优化复用对比策略, 优化渲染性能)

主要考察:

  1. vue 的更新机制 (差异化更新) 对比新旧虚拟 dom, 找出不同的部分, 进行更新视图

    为什么对比虚拟 dom, 而不对比真实的 dom ? 真实的 dom 太复杂, 对比起来性能太差

  2. 虚拟 dom: 使用 js 对象的方式, 模拟真实的 dom 结构 { type: ‘div’, className: ‘box’ , children: [] }

    属性的量大大的减少了, 没有真实 dom 的那么多无效的属性, 对比起来性能高很多

  3. diff 算法: 默认的对比(diff) 机制, 同层兄弟元素, 是按照下标进行对比的, 但是加了 key, 就相当于给虚拟 dom 加了个标识

    对比策略, 就是对相同 key 的元素进行对比了, 在列表 v-for 中, key 的使用尤为常见, 可以用于优化渲染性能

在这里插入图片描述

9.2 key 的常见应用场景

key 的常见应用场景 => v-for, v-for 遍历的列表中的项的顺序, 非常的容易改变

1 往后面加, 默认的对比策略, 按照下标, 没有任何问题

// 旧
<ul>
  <li>张三</li>
  <li>李四</li>
</ul>

// 新
<ul>
  <li>张三</li>
  <li>李四</li>
  <li>王五</li>
</ul>

2 往前面加, 由于下标变了, 如果按照之前的下标对比, 元素是混乱的, 策略: 加上 key

一旦加上了 key, 就是按照 key 进行新旧 dom 的对比了

// 旧
<ul>
  <li key="17">张三</li>
  <li key="31">李四</li>
</ul>

// 新  [ { id: 17, name: '张三' }, ... ]
<ul>
  <li key="52">王五</li>
  <li key="17">张三</li>
  <li key="31">李四</li>
</ul>

总结: key 就是给 虚拟 dom 添加了一个 标识, 优化了对比策略!!!

10. Vue 跳转路由时的传参方式 (query 和 params 的区别)

  1. 通过 query 传参
this.$router.push("/login?username=pp&age=18&desc=xx");

this.$router.push({
  path: "/login",
  query: {
    username: "pp",
    age: 18,
    desc: "xxx",
  },
});

this.$router.push({
  name: "login",
  query: {
    username: "pp",
    age: 18,
    desc: "xxx",
  },
});

获取: this.$route.query.username

  1. 通过 params 传参, 必须通过命名路由的方式传递!
this.$router.push({
  name: "login",
  params: {
    username: "pp",
    age: 18,
  },
});

获取: this.$route.params.username

区别:

  1. params 传参, 必须要用命名路由的方式传值

  2. params 传参, 不会显示在地址栏中, 刷新会丢失

    可以配合 localStorage 使用

    (1) A 跳转路由到 B, 通过 params 传值

    (2) B 页面中, 立刻通过 this.$route.params 获取参数

    (获取参数的逻辑, 优先从$route 中拿, 如果拿不到(说明刷新了), 从本地取即可)

    (3) 拿到参数后, 立刻存到本地 (保证刷新丢失后, 还能从本地拿)

    (4) 实现功能…

B 页面的逻辑

created () {
    let username = this.$route.params.username
    if (username) {
        // 刚跳过来, 有参数, 立刻存起来
        localStorage.setItem('myParams', JSON.stringify(this.$route.params))
    } else {
        // 没有, 说明用户刷新了, 丢失了params, username参数, 本地拿
        username = JSON.parse(localStorage.getItem('myParams')).username
    }
}

11. Vue 项目进行 SEO 优化

Vue SPA 单页面应用对 SEO 不太友好,当然也有相应的解决方案,下面列出几种 SEO 方案

  1. SSR 服务器渲染

    服务端渲染, 在服务端 html 页面节点, 已经解析创建完了, 浏览器直接拿到的是解析完成的页面解构

    关于服务器渲染:Vue 官网介绍 ,对 Vue 版本有要求,对服务器也有一定要求,需要支持 nodejs 环境。

    优势: 更好的 SEO,由于搜索引擎爬虫抓取工具可以直接查看完全渲染的页面

    缺点: 服务器 nodejs 环境的要求, 且对原代码的改造成本高! nuxt.js (坑比较多, 做好踩坑的准备)

  2. 静态化 (博客, 介绍性官网)

    Nuxt.js 可以进行 generate 静态化打包, 缺点: 动态路由会被忽略。 /users/:id

    优势:

    • 编译打包时, 就会帮你处理, 纯静态文件,访问速度超快;
    • 对比 SSR,不涉及到服务器负载方面问题;
    • 静态网页不宜遭到黑客攻击,安全性更高。

    不足:

    • 如果动态路由参数多的话不适用。
  3. 预渲染 prerender-spa-plugin (插件)

    如果你只是对少数页面需要做 SEO 处理(例如 / 首页, /about 关于等页面)

    预渲染是一个非常好的方式, 预渲染会在构建时, 简单的针对特定路由, 生成静态 HTML 文件 (打包时可以帮你解析静态化)

    优势: 设置预渲染简单, 对代码的改动小

    缺点: 只适合于做少数页面进行 SEO 的情况, 如果页面几百上千, 就不推荐了 (会打包很慢)

  4. 使用 Phantomjs 针对爬虫 做处理

    Phantomjs 是一个基于 webkit 内核的无头浏览器,没有 UI 界面,就是一个浏览器,

    其内的点击、翻页等人为相关操作需要程序设计实现。

    这种解决方案其实是一种旁路机制,原理就是通过 Nginx 配置, 判断访问的来源 UA 是否是爬虫访问,

    如果是则将搜索引擎的爬虫请求转发到一个 node server,再通过 PhantomJS 来解析完整的 HTML,返回给爬虫

在这里插入图片描述

  1. 优势:

    • 完全不用改动项目代码,按原本的 SPA 开发即可,对比开发 SSR 成本小太多了;
    • 对已用 SPA 开发完成的项目,这是不二之选。

    不足:

    • 部署需要 node 服务器支持;

    • 爬虫访问比网页访问要慢一些,因为定时要定时资源加载完成才返回给爬虫;(不影响用户的访问)

    • 如果被恶意模拟百度爬虫大量循环爬取,会造成服务器负载方面问题,

      解决方法是判断访问的 IP,是否是百度官方爬虫的 IP。

小结:

  • 如果构建大型网站,如商城类 => SSR 服务器渲染

  • 如果只是正常公司官网, 博客网站等 => 预渲染/静态化/Phantomjs 都比较方便

  • 如果是已用 SPA 开发完成的项目进行 SEO 优化,而且部署环境支持 node 服务器,使用 Phantomjs

博客参考: SEO 优化方案

12. Vue 项目权限处理

现在权限相关管理系统用的框架都是 element 提供的vue-element-admin模板框架比较常见。

权限控制常见分为三大块

  • 菜单权限控制
  • 按钮权限控制
  • 请求 url 权限控制。

权限管理在后端中主要体现在对接口访问权限的控制,在前端中主要体现在对菜单访问权限的控制。

  1. 按钮权限控制比较容易,主要采取的方式是从后端返回按钮的权限标识,然后在前端进行显隐操作 v-if / disabled。

  2. url 权限控制,主要是后端代码来控制,前端只需要规范好格式即可。

  3. 剩下的菜单权限控制,是相对复杂一些的

    (1) 需要在路由设计时, 就拆分成静态路由和动态路由

    静态路由: 所有用户都能访问到的路由, 不会动态变化的 (登录页, 首页, 404, …)

    动态路由: 动态控制的路由, 只有用户有这个权限, 才将这个路由添加给你 (审批页, 社保页, 权限管理页…)

    (2) 用户登录进入首页时, 需要立刻发送请求, 获取个人信息 (包含权限的标识)

在这里插入图片描述

  1. (3) 利用权限信息的标识, 筛选出合适的动态路由, 通过路由的 addRoutes 方法, 动态添加路由即可!

    (4) router.options.routes (拿的是默认配置的项, 拿不到动态新增的) 不是响应式的!

    为了能正确的显示菜单, 为了能够将来正确的获取到用户路由, 我们需要用vuex 管理 routes 路由数组

    (5) 利用 vuex 中的 routes, 动态渲染菜单

13. Vue 项目支付功能

支付宝方式:点击支付宝支付, 调用后台接口(携带订单号),后台返回一个 form 表单(HTML 字符串结构),

提交 form 就可以调用支付宝支付

代码:

//  alipayWap: 后台接口返回的form 片段
<div v-html="alipayWap" ref="alipayWap"></div>

methods: {
	toAlipay () {
		this.$axios.get('xxx').then (res = > {
			this.alipayWap = res;
             // 等待dom更新, 等页面中有这个form表单了
			this.$nextTick(() => {
            	this.$refs.alipayWap.children[0].submit()
          	})
		})
	}
}

在这里插入图片描述

微信支付:需要自己根据后台返回的 url 生成二维码页面,如图所示

在这里插入图片描述

博客参考 1: https://blog.csdn.net/qq_36710522/article/details/90480914

博客参考 2: https://blog.csdn.net/zyg1515330502/article/details/94737044

14. 如何处理 打包出来的项目(首屏)加载过慢的问题

SPA 应用: 单页应用程序, 所有的功能, 都在一个页面中, 如果第一次将所有的路由资源, 组件都加载了, 就会很慢!

加载过慢 => 一次性加载了过多的资源, 一次性加载了过大的资源

  • 加载过多 => 路由懒加载, 访问到路由, 再加载该路由相关的组件内容
  • 加载过大 => 图片压缩, 文件压缩合并处理, 开启 gzip 压缩等

比如:

  1. 配置异步组件, 路由懒加载

    const login = () => import("../pages/login.vue");
    
  2. 图片压缩: 使用 webp 格式的图片, 提升首页加载的速度

  3. CDN 加速: 配置 CDN 加速, 加快资源的加载效率 (花钱)

  4. 开启 gzip 压缩 (一般默认服务器开启的, 如果没开, 确实可能会很慢, 可以让后台开一下)

    在这里插入图片描述
    博客: https://www.cnblogs.com/xidian-Jingbin/p/10643391.html

15. 你在项目中遇到过什么技术难题

问题: 考察解决问题的能力!

话术: 前端要学的东西确实很多,但是并不夸张, 肯多花点时间沉淀一般都会有解决方案

一般遇到难题 (这些前端所谓的难题, 一般都是一些没有做过, 没有尝试过得一些业务), 我们要时刻保持独立思考,

知道自己要做什么业务由此决定要学什么知识, 然后实现业务, 举一反三,总结归纳!

比如 1: 如果之前没有做过国际化, 换肤, 没有做过支付, 权限控制, 没有做过即时通信 websocket, excel 导入导出, 就会觉得很难,

但其实真正上手花时间去学着做了, 也都能逐步思考解决相关页面, 这些其实也都还 ok

比如 2: 有时候, 复杂的或者困难的, 并不是技术层面的, 而是业务需求方面的, 需要进行大量树形结构的处理

展示列表式数据时, 展示图表数据时, 筛选条件关联条件多了, 组件与组件的联动关系的控制也比较麻烦,

将联动的条件, 存 vuex, 然后 => 进行分模块管理也是比较合适的选择

16. 请简单介绍一下你的项目

一定要做准备工作:

项目的介绍, 因人而异, 可以找不同的网站, 先从网站的功能业务角度出发, 去介绍

然后思考: 如果是现在让你写这样的功能页面, 你会如何实现! 然后手写记录下来, 推算合理性 (遇到什么问题, 怎么解决的!),

逐步完善对于项目的介绍

以饿了么为例: https://github.com/bailicangdu/vue2-elm

1 基本业务介绍: 给用户提供外卖服务的

2 技术栈: vue2 + vuex + vue-router + webpack + ES6/7 + axios+ sass + flex + svg

3 功能需求介绍:

  • 定位功能
  • 选择城市
  • 搜索地址
  • 展示所选地址附近商家列表
  • 搜索美食,餐馆
  • 根据距离、销量、评分、特色菜、配送方式等进行排序和筛选
  • 餐馆食品列表页
  • 购物车功能
  • 店铺评价页面
  • 单个食品详情页面
  • 商家详情页
  • 登录、注册
  • 修改密码
  • 个人中心
  • 发送短信、语音验证
  • 下单功能
  • 订单列表
  • 订单详情
  • 下载 App
  • 添加、删除、修改收货地址
  • 帐户信息
  • 服务中心
  • 红包
  • 上传头像
  • 付款

4 哪些模块你是会的, 就可以着重介绍, 哪些模块不太会做, 就查资料, 对比方案, 构思思路

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1127760.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

解决oracle12c安装失败【INS-30131】执行安装程序验证所需要的初始设置失败问题

最近看到很多公司都要求会使用Oracle数据库,所以我就在网上找了Oracle教程,打算学习一下,可人生就是喜欢捉弄我,Oracle安装竟然都出了问题,别提学习了,可真让我很难受,那么安装出现了什么问题呢? 看下图: 原因 - 无法访问临时位置。 操作 - 请确保当前用户具有访问临时位置所…

muduo源码学习base——Atomic(原子操作与原子整数)

Atomic(原子操作与原子整数&#xff09; 前置知识AtomicIntegerTget()getAndAdd()getAndSet() 关于原子操作实现无锁队列(lock-free-queue) 前置知识 happens-before&#xff1a; 用来描述两个操作的内存可见性 如果操作 X happens-before 操作 Y&#xff0c;那么 X 的结果对于…

极智AI | 有趣的羊驼系列大模型

欢迎关注我的公众号 [极智视界],获取我的更多经验分享 大家好,我是极智视界,本文来介绍一下 有趣的羊驼系列大模型。 邀您加入我的知识星球「极智视界」,星球内有超多好玩的项目实战源码下载,链接:https://t.zsxq.com/0aiNxERDq "羊驼模型" 在大模型的介绍中应…

CodeWhisperer proxy代理连不上(解决)

报错&#xff1a; 2023-10-24 14:15:50 [INFO]: selected AWS ID sign in 2023-10-24 14:15:50 [ERROR]: API response (oidc.us-east-1.amazonaws.com /device_authorization): {} 2023-10-24 14:15:50 [ERROR]: webviewId"authWebview": Error: Webview error->…

【外汇天眼】很多交易高手都容易忽视的问题:“路径依赖”!

一、“路径依赖”与“均值回归” 在过去五到十年内&#xff0c;如果你一直通过采用某一策略取得持续的超额收益&#xff0c;那么你很难认识到这种策略可能出现错误。 即使经历了一两年的失效&#xff0c;大多数人都会继续相信并采用这一策略。这受到沉没成本、个人声誉以及多种…

Android Apk一键打包上传至蒲公英平台的gradle脚本

一、背景 项目中每次手动打包后&#xff0c;生成的测试包&#xff0c;都需要手动打开蒲公英平台的网址&#xff0c;登录账号&#xff0c;手动上传apk。之前写过一键上传至fir平台的脚本&#xff0c;想着这次可以搞一下一键打包上传至蒲公英的gradle脚本&#xff0c;提高下工作…

Linux下QT打开文件选择对话框时,程序报错退出

系统&#xff1a;Ubuntu QString fileName QFileDialog::getOpenFileName(this, "open", "./", "document Files (*.pdf)"); 调用该语句弹出文件对话框时&#xff0c;程序崩溃退出 错误提示&#xff1a; (Widget:5272): Gtk-WARNING **: 14…

73 应急响应-WEB分析phpjavaweb自动化工具

目录 应急响应&#xff1a;必备知识点&#xff1a;准备工作&#xff1a;有明确信息网站被入侵&#xff1a;无明确信息网站被入侵&#xff1a;常见分析方法&#xff1a; 演示案例&#xff1a;WindowsIISSql-日志&#xff0c;搜索LinuxBT_Nginxtp5-日志,后门360星图日志自动分析工…

Spring Cloud之服务注册与发现(Eureka)

目录 Eureka 介绍 角色 实现流程 单机构建 注册中心 服务提供者 服务消费者 集群搭建 注册中心 服务提供者 自我保护机制 原理分析 Eureka 介绍 Eureka是spring cloud中的一个负责服务注册与发现的组件&#xff0c;本身是基于REST的服务&#xff0c;同时还提供了…

虚拟化 vs. 裸金属:K8s 部署环境架构与特性对比

伴随着 IT 云化转型的逐步推进&#xff0c;越来越多的用户加入应用容器化改造的行列&#xff0c;并使用 Kubernetes&#xff08;K8s&#xff09;进行容器部署管理。然而&#xff0c;令不少用户感到困惑的是&#xff0c;由于大部分应用此前都部署在虚拟化或超融合环境&#xff0…

批量处理图片,轻松转换JPG到TIFF,让你的图片管理更优化!

作为图片处理的专业人士&#xff0c;您可能经常需要处理大量的图片文件&#xff0c;其中包括各种不同的格式&#xff0c;如JPG、PNG、GIF等。然而&#xff0c;不同的格式有着不同的优缺点&#xff0c;有时候为了更好地保存和传输图片&#xff0c;您可能需要将其转换为其他格式。…

NEFU系统分析与设计

系统分析与设计概述 用户故事 用来描述用户希望得到的功能 三要素&#xff1a;角色、活动、商业价值 举例&#xff1a;作为一个“网站管理员”&#xff0c;我想要“统计每天有多少人访问了我的网站”&#xff0c;以便于“我的赞助商了解我的网站会给他们带来什么收益。 系统…

Jmeter(十二):线程组元件第三方插件的线程组压力和负载线程详解

线程组(thread group) 线程组元件是任何一个测试计划的开始点。在一个测试计划中的所有元件 都必须在某个线程下。所有的任务都是基于线程组。 一个线程组可以看做一个虚拟用户组&#xff0c;线程组中的每个线程都可以理解为一 个虚拟用户。多个用户同时去执行相同的一批次任…

升讯威在线客服系统的并发高性能数据处理技术:为多线程处理同步数据

我在业余时间开发维护了一款免费开源的升讯威在线客服系统&#xff0c;也收获了许多用户。对我来说&#xff0c;只要能获得用户的认可&#xff0c;就是我最大的动力。 最近客服系统成功经受住了客户现场组织的压力测试&#xff0c;获得了客户的认可。 客户组织多名客服上线后&a…

uniapp跨域

配置 /manifest.json "devServer" : { "https" : false, "port" : 7101, "proxy": { "/api": { "target": "https://域名", "changeOrigin": t…

3D模型如何添加表面贴图?

1、模型表面贴图介绍 模型表面贴图&#xff08;Texture Mapping&#xff09;是一种将纹理映射到三维模型表面的技术&#xff0c;用于增加模型的细节和真实感。它通过在模型的每个表面点上应用纹理坐标&#xff0c;并将纹理像素与模型的对应点进行匹配&#xff0c;使得模型表面…

elasticSearch put全局更新和单个字段更新语法

1、如下&#xff1a;更新改类型未doc(文档)的全局字段数据 注意&#xff1a;如果你使用的是上面的语句&#xff0c;但是只写了id和title并赋值&#xff0c;图片上其他字段没有填写&#xff0c;执行命令后&#xff0c;则会把原文档中的其他字段都给删除了&#xff0c;你会发现查…

prosemirror 学习记录(二)创建 apple 节点

apple type 向 schema 中添加 apple type const nodes {apple: {inline: true,attrs: {name: { default: "unknown" },},group: "inline",draggable: true,parseDOM: [{tag: "span[custom-node-typeapple]",getAttrs(dom) {return {name: dom…

【高效开发工具系列】Apifox

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kuan 的首页,持续学…

Vue单页面应用(SPA)怎么做SEO

在Vue单页面应用(SPA)中,由于内容的动态加载和路由切换,搜索引擎可能无法直接获取和索引页面的内容。不过,你可以采取一些策略来优化SEO,使你的Vue单页面应用在搜索引擎中更好地被索引和展示: 1:使用预渲染(Prerendering)或服务器端渲染(Server-Side Rendering,SS…