Starlet 发布的文章

一、事件冒泡和事件捕获

  • 事件冒泡:当一个元素上的事件被触发时,该事件会沿着 DOM 树向上传播,从触发事件的最内层元素开始,依次触发其祖先元素上的相同事件。例如,在一个包含多个嵌套 <div> 的页面中,如果点击最内层的 <div>,那么这个点击事件会先在该 <div> 上触发,然后依次在其父元素、祖父元素等上触发,直到到达文档根节点。
  • 事件捕获:与事件冒泡相反,事件捕获是从文档根节点开始,沿着 DOM 树向下传播,直到到达目标元素。在事件捕获阶段,事件会先在最外层的祖先元素上触发,然后逐渐向内层元素传播。
  • 应用场景与示例:在实际开发中,可以利用事件冒泡和捕获来实现一些复杂的交互逻辑。例如,在一个列表中,点击每个列表项时,既需要在列表项本身触发一个点击事件,又需要在列表容器上统计点击次数。可以通过在列表容器上添加一个捕获阶段的点击事件监听器来统计点击次数,而在列表项上添加冒泡阶段的点击事件监听器来处理列表项的具体点击操作。

二、项目中用flex实现一个左固定,右自适应的布局

  • 使用 flexbox 布局:

    • 父容器设置 display: flex
    • 左固定部分设置固定宽度,例如 width: 200px
    • 右自适应部分设置 flex: 1,表示自动填充剩余空间。

三、flex:1 是什么效果

  • flex: 1flex-grow: 1flex-shrink: 1flex-basis: 0% 的缩写。
  • flex-grow: 1:表示当父容器有剩余空间时,该元素会按照比例分配剩余空间并增长。如果有多个子元素都设置了 flex-grow,则它们会按照各自的 flex-grow 值比例分配剩余空间。例如,一个父容器内有两个子元素,一个设置 flex: 1,另一个设置 flex: 2,那么剩余空间会按照 1:2 的比例分配给这两个子元素。
  • flex-shrink: 1:当父容器空间不足时,该元素会按照比例缩小。如果所有子元素的 flex-shrink 都为 1,它们会平均缩小;如果值不同,则按照比例缩小。
  • flex-basis: 0%:指定了元素在分配剩余空间或收缩之前的初始大小。设置为 0% 表示元素在分配空间之前不占据任何空间,完全依赖于 flex-grow 来分配空间。

四、js 中的原型链

  • 原型链概念:在 JavaScript 中,每个对象都有一个原型(prototype),而原型本身也是一个对象,它又有自己的原型,这样就形成了一个原型链。当访问一个对象的属性或方法时,如果该对象本身没有这个属性或方法,JavaScript 引擎会沿着原型链向上查找,直到找到该属性或方法或者到达原型链的顶端(Object.prototype 的原型为 null)。
  • 示例
function Person() {
  this.name = 'John';
}

Person.prototype.sayHello = function() {
  console.log('Hello, I am'+ this.name);
};

const person = new Person();
person.sayHello(); // 调用原型上的方法,输出 "Hello, I am John"

// 查看原型链
console.log(person.__proto__ === Person.prototype); // true
console.log(Person.prototype.__proto__ === Object.prototype); // true
console.log(Object.prototype.__proto__); // null

五、同源策略

  • 同源策略定义:同源策略是浏览器的一种安全机制,它限制了一个源(协议、域名、端口)的脚本只能与同来源的资源进行交互。例如,一个页面从 http://example.com 加载,那么该页面中的 JavaScript 脚本只能向 http://example.com 发送请求,不能向其他域名或不同协议、端口的资源发送请求,除非有特殊的跨域设置。
  • 目的:主要目的是防止恶意网站通过脚本获取其他网站的敏感信息,保障用户数据的安全和网站的隐私。例如,防止一个恶意网站读取用户在银行网站的账户信息等。
  • 跨域解决方案:虽然同源策略限制了跨域访问,但在实际开发中,有多种方式可以实现跨域,如 JSONP(利用 <script> 标签不受同源策略限制的特性)、CORS(服务器端设置允许跨域的响应头)、代理服务器(在同源的服务器端代理请求其他域的资源)等。

六、Nodejs 代理服务器

  • 作用:Node.js 代理服务器可以在客户端和目标服务器之间起到中转的作用。它可以用于解决跨域问题,通过在同源的 Node.js 服务器上代理客户端的请求到不同源的目标服务器,然后将目标服务器的响应返回给客户端,从而绕过浏览器的同源策略限制。此外,还可以用于请求过滤、缓存、日志记录等功能。

七、echarts 传值方式、及多个echarts更新单个

  • 数据更新:可以直接通过修改 echarts 实例的 option 对象中的数据来更新图表。例如,如果有一个柱状图,要更新柱子的高度数据,可以这样操作:
  • 事件传值:echarts 提供了丰富的事件,如 clicklegendselectchanged 等。在事件回调函数中,可以获取到相关的数据信息并进行传值操作。
  • 单独更新:在子组件中使用watch监听进行数值更新操作。

八、微信小程序提高响应速度

  • 优化代码结构:合理划分页面和组件,避免代码过于臃肿。将公共的逻辑提取到独立的模块或组件中,减少页面加载时的代码量。
  • 数据请求优化:减少不必要的数据请求,对数据进行缓存。例如,可以使用 wx.getStoragewx.setStorage 对经常使用的数据进行本地缓存,减少重复请求服务器的次数。同时,优化数据请求的时机,避免在页面加载时同时发起过多请求,可以采用延迟加载或合并请求的方式。
  • 图片和资源优化:对图片进行压缩处理,选择合适的图片格式(如 webp 格式在某些情况下比 jpg、png 更具优势)。对于一些较大的资源文件,可以考虑使用分包加载,将不常用的资源放在分包中,在需要时再加载。
  • 使用骨架屏或加载提示:在页面数据加载过程中,显示骨架屏或加载提示,让用户有等待的预期,避免页面长时间空白或无响应给用户带来的不良体验。

九、前端身份验证

  • 基于 Token 的身份验证:

    • 流程:用户登录成功后,服务器生成一个包含用户身份信息的 Token(通常是一个加密的字符串)并返回给前端。前端将 Token 存储起来,通常存储在 localStoragesessionStorage 中。在后续的请求中,前端将 Token 添加到请求头(如 Authorization 字段)中发送给服务器。服务器收到请求后,验证 Token 的有效性,如果有效则允许访问相应资源,否则返回错误信息。
  • 基于 Cookie 的身份验证:

    • 流程:用户登录成功后,服务器在响应中设置一个包含用户身份信息的 Cookie。浏览器会自动在后续的同源请求中携带该 Cookie。服务器根据 Cookie 中的信息进行身份验证。不过,由于 Cookie 存在一些安全风险(如跨站请求伪造 CSRF),需要采取相应的防范措施,如设置 SameSite 属性等。
继续阅读->

一、你目前在长春吗?预计多久可以实习?

我目前在长春,预计拿到offer后可以开始实习。

二、描述一下你的项目,你最得意的页面

三、八股问答

(一)前端路由导航激活(切换按钮的激活状态 css)

在实现前端路由导航激活时,通过监听路由的变化,利用 Vue Router 提供的导航守卫或者在组件内使用 watch 监听 $route 对象的变化。当路由发生改变时,根据当前路由路径与导航菜单的对应关系,动态地为相应的菜单项添加或移除激活状态的 CSS 类名。

(二)vue 中 histroy 为什么变化后会显示元素

在 Vue 中使用 vue-routerhistory 模式时,当 URL 的 history 发生变化,vue-router 会根据新的 URL 匹配对应的路由组件,并将该组件渲染到指定的视图区域,从而显示对应的元素。这是因为 vue-router 对浏览器的 history API 进行了封装,监听了 popstate 事件以及在路由跳转时手动更新 history 状态,然后根据内部的路由映射表来决定显示哪个组件。

(三)页面之间传参的方式

  • 路由传参:

    • 动态路由参数:在路由配置中定义动态参数,例如 { path: '/user/:id', component: User },在组件内通过 this.$route.params.id 获取参数。
    • 查询参数:通过 this.$router.push({ path: '/search', query: { keyword: 'vue' } }) 传递参数,在接收页面通过 this.$route.query.keyword 获取。
  • 父子组件传参:

    • 父传子:在父组件的模板中,通过属性绑定将数据传递给子组件,例如 <child-component :message="parentMessage"></child-component>,在子组件中通过 props 接收,props: ['message']
    • 子传父:子组件通过 $emit 事件触发一个自定义事件,并传递数据,例如 this.$emit('sendData', data),在父组件中监听该事件并接收数据,<child-component @sendData="receiveData"></child-component>methods: { receiveData(data) { console.log(data); } }

(四)vue 父传子子传父

如上述页面传参方式中所描述,父传子通过属性绑定和 props 实现,子传父通过 $emit 触发自定义事件实现,这种方式使得父子组件之间的数据传递和交互更加灵活和可控,方便构建复杂的组件结构和应用逻辑。

(五)vue3 生命周期函数

Vue 3 中的生命周期函数有了一些变化,主要的生命周期钩子包括:

  • setup:在组件创建之前执行,用于初始化组件的一些数据和逻辑,是 Vue 3 中新增的组合式 API 的入口函数。
  • onBeforeMount:在组件挂载之前被调用。
  • onMounted:在组件挂载完成后被调用。
  • onBeforeUpdate:在组件数据更新之前被调用。
  • onUpdated:在组件数据更新完成后被调用。
  • onBeforeUnmount:在组件卸载之前被调用。
  • onUnmounted:在组件卸载完成后被调用。

(六)vue2 和 vue3 生命周期区别

  • Vue 2 中的 beforeCreatecreated 在 Vue 3 中被整合到了 setup 函数中,setup 函数在组件实例化之前执行,可以访问到 propscontext,但不能访问到组件实例 this
  • Vue 3 中移除了 beforeDestroydestroyed,取而代之的是 onBeforeUnmountonUnmounted,使得生命周期函数的命名更加语义化,符合组件挂载和卸载的概念。
  • Vue 3 的生命周期函数采用了基于函数的注册方式,而不是 Vue 2 中的选项式注册,例如在 Vue 3 中使用 import { onMounted } from 'vue'; onMounted(() => { console.log('mounted'); });,这种方式使得代码更加灵活和可复用。

(七)前后端是怎么实现交互的

前后端交互通常基于 HTTP 协议。前端通过发送 HTTP 请求(如 GETPOSTPUTDELETE 等请求方法)到后端服务器的特定接口地址,后端服务器接收到请求后,根据请求的内容进行相应的业务逻辑处理,如查询数据库、执行业务算法等,然后将处理结果以 HTTP 响应的形式返回给前端。前端在收到响应后,根据响应的数据进行页面的更新和展示。在 Vue 项目中,常使用 axios 等库来发送 HTTP 请求

(八)表单元素用户名,性别,右边按钮查询,后台请求列表,姓名,性别,职业;设计数据结构并描述整套流程

  • 数据结构设计:

    • 前端表单数据结构
{
  username: '', // 用户名
  gender: '', // 性别
}
  • 后端返回数据结构
[
  {
    name: '', // 姓名
    gender: '', // 性别
    profession: '' // 职业
  },
...
]
  • 流程描述:

    • 前端页面展示包含用户名输入框、性别选择框(如男、女)和查询按钮的表单。当用户输入用户名并选择性别后,点击查询按钮,前端会将表单数据(usernamegender)封装成一个对象,使用 axios 发送一个 POST 请求到后端的查询接口(如 /api/search)。后端接收到请求后,根据传入的用户名和性别参数在数据库中进行查询操作,查询符合条件的用户信息,将查询结果(包含姓名、性别、职业)封装成一个数组形式的 JSON 数据,然后将该数据作为 HTTP 响应返回给前端。前端在收到响应后,解析响应数据,将用户信息展示在页面的列表中,例如使用 v-for 指令循环渲染列表项。

(九)水平居中元素的方法

  • 行内元素或文本:可以使用 text-align: center 样式属性将父元素内的行内元素或文本水平居中
  • 定宽块级元素:可以使用 margin: 0 auto 样式,将块级元素的左右外边距设置为自动,使其在父元素内水平居中
  • 不定宽块级元素:对于不定宽的块级元素,可以使用 display: flexjustify-content: center 实现水平居中。

(十)js 中的数组操作有哪些

JavaScript 中的数组操作非常丰富,常见的有:

  • 创建数组:

    • 使用字面量方式 const arr = [1, 2, 3];
    • 使用 Array 构造函数 const arr = new Array(1, 2, 3);
  • 访问数组元素:通过索引访问,例如 arr[0] 获取数组的第一个元素。
  • 修改数组元素:直接通过索引赋值,例如 arr[1] = 5;
  • 数组长度:使用 length 属性获取或修改数组长度,例如 arr.length 返回数组的长度,arr.length = 5 可以改变数组的长度。
  • 添加元素:

    • push:在数组末尾添加一个或多个元素,例如 arr.push(4, 5),返回修改后的数组长度。
    • unshift:在数组开头添加一个或多个元素,例如 arr.unshift(0),返回修改后的数组长度。
  • 删除元素:

    • pop:删除数组末尾的元素,返回被删除的元素。
    • shift:删除数组开头的元素,返回被删除的元素。
    • splice:可以删除、插入或替换数组中的元素,例如 arr.splice(1, 2) 删除从索引 1 开始的 2 个元素,arr.splice(2, 0, 'new') 在索引 2 处插入元素 'new'
  • 数组遍历:

    • for 循环for (let i = 0; i < arr.length; i++) { console.log(arr[i]); }
    • forEach 方法arr.forEach(item => console.log(item));
    • map 方法:创建一个新数组,其结果是该数组中的每个元素都调用一个提供的函数后的返回值,例如 const newArr = arr.map(item => item * 2);
    • filter 方法:创建一个新数组,其包含通过所提供函数实现的测试的所有元素,例如 const filteredArr = arr.filter(item => item > 2);
    • reduce 方法:对数组中的每个元素执行一个由您提供的 reducer 函数 (升序执行),将其结果汇总为单个返回值,例如 const sum = arr.reduce((acc, item) => acc + item, 0);

四、你未来是打算怎么发展的

想在大城市发展

五、我看你简历上主修课程都是后端课程,为什么想到要做前端呢?(问了两次)

继续阅读->

1、浏览器渲染过程

  • HTML 解析:浏览器首先解析 HTML 文档,构建 DOM 树。在解析过程中,如果遇到外部资源(如 CSS 文件、JavaScript 文件、图片等),会发起相应的请求去获取这些资源。
  • CSS 解析:同时,浏览器会解析 CSS 文件,构建 CSSOM(CSS Object Model)树。CSSOM 描述了文档的样式信息,包括每个元素的样式规则。
  • 构建渲染树:结合 DOM 树和 CSSOM 树,浏览器构建渲染树。渲染树只包含需要显示的节点和这些节点的样式信息。
  • 布局(Layout):确定每个节点在屏幕上的位置和大小。布局过程会考虑元素的盒模型、定位方式、尺寸等因素。
  • 绘制(Painting):根据渲染树,浏览器将每个节点绘制到屏幕上。绘制过程包括填充颜色、绘制边框、绘制文本等操作。
继续阅读->

1. 介绍 flex,适用什么场景,三个核心属性是什么

  • Flex 是 CSS 的一种布局方式,全称为 Flexible Box Layout,即弹性盒布局。它提供了一种更加灵活和高效的方式来布局网页元素。

适用场景:

  • 自适应布局:可以轻松实现不同屏幕尺寸下的自适应布局,适用于响应式设计。
  • 对齐和分布:方便地实现元素的水平和垂直对齐,以及均匀分布。
  • 复杂布局:对于复杂的布局需求,如导航栏、表单、卡片布局等,Flex 可以提供简洁的解决方案。

三个核心属性:

  • flex-direction:决定主轴的方向,即项目在弹性容器中的排列方向。可以是row(水平从左到右)、row-reverse(水平从右到左)、column(垂直从上到下)、column-reverse(垂直从下到上)。
  • flex-wrap:决定当项目在主轴方向上超出弹性容器的尺寸时,是否换行。可以是nowrap(不换行)、wrap(换行)、wrap-reverse(反向换行)。
  • justify-content:决定项目在主轴上的对齐方式。可以是flex-start(左对齐或上对齐)、flex-end(右对齐或下对齐)、center(居中对齐)、space-between(两端对齐,项目之间的间隔相等)、space-around(每个项目两侧的间隔相等)。
继续阅读->

1.Electron 底层原理

Electron 是一个使用 JavaScript、HTML 和 CSS 构建跨平台桌面应用程序的框架。它的底层原理主要包括以下几个方面:

  • 基于 Chromium 和 Node.js:Electron 结合了 Chromium 浏览器引擎和 Node.js 运行时环境。Chromium 提供了强大的网页渲染能力,而 Node.js 允许在应用程序中使用 JavaScript 进行服务器端编程和访问操作系统的底层功能。
  • 主进程和渲染进程:Electron 应用程序分为主进程和渲染进程。主进程负责管理应用程序的生命周期、窗口管理、与操作系统的交互等。渲染进程则负责渲染用户界面,每个窗口都有一个独立的渲染进程。
  • 进程间通信:主进程和渲染进程之间可以通过进程间通信(IPC)进行通信。这使得它们可以共享数据、调用对方的功能,并实现复杂的应用程序逻辑。

2.Electron 缺点

  • 体积较大:由于包含了 Chromium 和 Node.js 等组件,Electron 应用程序的体积通常比较大。这可能会导致下载和安装时间较长,占用较多的磁盘空间。
  • 性能问题:虽然 Electron 提供了强大的功能,但与原生应用程序相比,它可能在性能方面存在一些不足。特别是在处理大量图形渲染、复杂计算或高频率的 I/O 操作时,可能会出现性能瓶颈。
  • 安全风险:由于 Electron 应用程序可以访问操作系统的底层功能,存在一定的安全风险。如果应用程序存在漏洞,可能会被攻击者利用来获取系统权限或执行恶意代码。

3. 为什么 Electron 能渲染 DOM

Electron 能渲染 DOM 是因为它结合了 Chromium 浏览器引擎。Chromium 是一个开源的浏览器项目,它具有强大的网页渲染能力,可以解析 HTML、CSS 和 JavaScript,并将其渲染为可视化的用户界面。

Electron 利用 Chromium 的渲染引擎,在应用程序中创建一个或多个窗口,并在这些窗口中加载网页内容。网页内容可以是本地的 HTML 文件、远程服务器上的网页或通过 JavaScript 动态生成的内容。通过这种方式,Electron 可以像浏览器一样渲染 DOM,并提供丰富的用户界面交互功能。

继续阅读->