Starting again company 03

1.vue单向数据流

1.1单向数据流核心

确保数据在组件间传递是单向的,从父组件流向子组件。vue中的单向数据流主要通过props实现,Vue2 的单向数据流核心是 "props 只读,修改需通过事件通知父组件"。

1.2单向数据流存在的意义

数据流向清晰:所有数据变更都能追溯到源头(通常是父组件或更上层的状态管理),便于调试和维护。

避免数据混乱:若允许子组件直接修改父组件数据,当多个子组件同时修改时,会导致数据状态不可预测。

1.3具体实现展示
1.3.1父传子单向数据流

父组件属性绑定传入数据

javascript 复制代码
<!-- 父组件 Parent.vue -->
<template>
  <Child :message="parentMsg" />
</template>
<script>
import Child from './Child.vue'
export default {
  components: { Child },
  data() {
    return { parentMsg: 'Hello from parent' }
  }
}
</script>

子组件props接收数据并使用

javascript 复制代码
<!-- 子组件 Child.vue -->
<template>
  <div>{{ message }}</div> <!-- 显示父组件传递的数据 -->
</template>
<script>
export default {
  props: ['message'] // 声明接收的 props
}
</script>
1.3.2子组件修改数据:通过事件通知父组件

子组件通过 $emit 触发一个自定义事件,并传递需要修改的值

javascript 复制代码
<!-- 子组件 Child.vue -->
<template>
  <button @click="changeMsg">修改数据</button>
</template>
<script>
export default {
  props: ['message'],
  methods: {
    changeMsg() {
      // 触发自定义事件,传递新值
      this.$emit('update-message', 'New message from child')
    }
  }
}
</script>

父组件监听该事件,在事件处理函数中修改自身数据,通过 props 自动同步到子组件。

javascript 复制代码
<!-- 父组件 Parent.vue -->
<template>
  <!-- 监听子组件的自定义事件,执行修改逻辑 -->
  <Child :message="parentMsg" @update-message="handleUpdate" />
</template>
<script>
export default {
  data() { return { parentMsg: 'Hello' } },
  methods: {
    handleUpdate(newVal) {
      this.parentMsg = newVal // 父组件自行修改数据
    }
  }
}
</script>

2.vue2项目打包发布后项目刷新无变化

主要原因是打包后静态资源文件名未变,服务器返回304缓存,需通过「文件名加哈希」让更新后的资源文件名不同,确保 JS、CSS、图片等资源通过「哈希值」区分版本

强制刷新浏览器 ,排除本地缓存--->检查 dist 目录是否更新 ,服务器文件是否为最新--->配置 vue.config.js 确保 JS/CSS 带哈希- -->服务器配置 index.html 不缓存,静态资源长缓存;

2.1JS配置 webpack.config.jsoutput
javascript 复制代码
const path = require('path');

module.exports = {
  output: {
    // 入口 JS 文件(如 main.js)的输出路径和命名
    filename: 'js/[name].[contenthash:8].js', 
    // 异步加载的 chunk(如路由懒加载的组件)的命名
    chunkFilename: 'js/[name].[contenthash:8].chunk.js', 
    // 输出目录(通常为 dist)
    path: path.resolve(__dirname, 'dist'),
    // 每次打包前清空 dist 目录(避免旧文件残留)
    clean: true 
  }
};
2.2CSS 提取带内容哈希

如果用 mini-css-extract-plugin 提取 CSS 为单独文件,需同步配置 CSS 的文件名.

javascript 复制代码
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [MiniCssExtractPlugin.loader, 'css-loader'] // 提取 CSS 到文件
      }
    ]
  },
  plugins: [
    new MiniCssExtractPlugin({
      // CSS 文件命名(同样使用 contenthash)
      filename: 'css/[name].[contenthash:8].css',
      chunkFilename: 'css/[name].[contenthash:8].chunk.css'
    })
  ]
};
2.3确保 HTML 不缓存

即使 JS/CSS 带哈希,若 index.html 被缓存,浏览器仍会加载旧 HTML 中引用的旧资源路径

javascript 复制代码
server {
  location / {
    root /path/to/your/dist; # 指向打包后的 dist 目录
    try_files $uri $uri/ /index.html; # 支持 Vue 路由 history 模式
    # 对 HTML 禁用缓存
    add_header Cache-Control "no-cache, no-store, must-revalidate";
    add_header Pragma "no-cache"; # 兼容 HTTP/1.0
    add_header Expires "0"; # 过期时间设为 0
  }

  # 带哈希的静态资源可长期缓存(1年)
  location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff2?|eot|ttf)$ {
    add_header Cache-Control "max-age=31536000, immutable";
  }
}

3.CDN(内容分发网络)

核心目标通过分布式节点网络,将静态资源缓存到离用户最近的节点,从而降低延迟,提升访问速度,并减轻服务器的压力。

3.1核心架构
  1. 源站(Origin Server)

    • 存放原始资源的服务器(即你的业务服务器,如部署前端代码的 Nginx 服务器)。

    • CDN 节点会定期从源站同步资源(首次请求未命中时也会主动拉取)。

  2. CDN 节点(Edge Node)

    • 分布在全球 / 全国各地区的缓存服务器(如一线城市、二三线城市、海外地区),直接向用户提供资源。

    • 节点数量越多、覆盖越广,用户访问延迟越低(例如北京用户从北京节点获取资源,无需访问千里之外的源站)。

  3. 中心控制系统(DNS + 调度系统)

    • DNS 解析:通过自定义 DNS 服务器,将用户的域名解析到「最优 CDN 节点」(而非源站 IP)。

    • 调度策略:根据用户 IP 地理位置、节点负载、网络质量等,选择延迟最低的节点(例如上海用户优先分配到上海节点)。

3.2 CDN的完整工作流程
  1. 用户发起请求 :用户在浏览器输入 https://cdn.example.com/index.html,请求访问前端页面。

  2. DNS 解析导向 CDN 节点

    • 本地 DNS 向 CDN 的 DNS 服务器查询 cdn.example.com 的 IP。

    • CDN DNS 根据用户 IP 定位到最近的节点(如杭州节点),返回该节点 IP。

  3. CDN 节点处理请求

    用户向杭州节点请求 index.html,节点检查本地缓存:

    • 若已缓存且有效,直接返回缓存的 index.html

    • 若未缓存或已过期,节点向源站(如 origin.example.com)请求 index.html,缓存后返回给用户。

  4. 加载关联资源index.html 中引用的 app.456.js style.789.css 等资源,同样通过上述流程从 CDN 节点获取(若命中缓存,加载速度极快)。

  5. 资源更新与同步 :当前端代码更新并重新打包后(如 app.678.js),由于文件名哈希变化,CDN 节点会将其视为新资源,自动从源站拉取并缓存,用户下次访问时即可获取最新版本。

4.const声明对象是否能被修改

const声明的对象能被修改 ,与js的堆内存的存储机制有关。

  • 基本类型的值存储在栈内存中,变量指向的是具体的值。
  • 引用类型的值是存储在堆内存 中,变量在栈内存中存储的是指向堆内存中该对象的引用地址(类似指针)。

基本类型(值直接存储在栈内存中,变量与值直接绑定)

javascript 复制代码
const num = 10;
num = 20; // 报错:Assignment to constant variable(不能给常量重新赋值)

const str = 'hello';
str = 'world'; // 同样报错

const bool = true;
bool = false; // 报错

引用类型(堆内存指向引用地址,类似指针)

javascript 复制代码
const obj = { name: 'foo' };
obj = { age: 18 }; // 报错:堆内存中创建新对象引用地址发生改变
obj.name = 'bar'; // 允许,修改属性值
obj.age = 18;     // 允许,新增属性
delete obj.name;  // 允许,删除属性

const 与堆内存的联系在于 ------ 它保护的是栈内存中指向堆内存的引用地址不变,但不限制堆内存中对象本身的修改。

5.EventBus(全局事件总线)

适合解决非父子组件间的通信问题,核心思路通过全局的Vue实例作为"事件总线"实现事件的发布于订阅。

5.1.创建EventBus实例

创建独立的事件总线文件,作为全局的 "中介",管理所有组件的事件订阅与发布。

javascript 复制代码
// src/utils/eventBus.js
import Vue from 'vue'
// 实例化一个Vue对象作为事件总线
export default new Vue()
5.2$on订阅事件--接收数据

接收数据的组件中,通过 $on 订阅事件,并在组件销毁前用 $off 取消订阅(避免内存泄漏)。

javascript 复制代码
<!-- 组件A:src/components/ComponentA.vue -->
<template>
  <div>
    <h3>组件A(接收方)</h3>
    <p>收到的消息:{{ receivedMsg }}</p>
  </div>
</template>

<script>
import bus from '@/utils/eventBus' // 导入事件总线

export default {
  data() {
    return {
      receivedMsg: ''
    }
  },
  mounted() {
    // 订阅名为 "sendToA" 的事件,回调函数接收参数
    bus.$on('sendToA', (msg) => {
      this.receivedMsg = msg // 处理收到的数据
    })
  },
  beforeDestroy() {
    // 组件销毁前取消订阅,防止事件重复触发
    bus.$off('sendToA')
  }
}
</script>
5.3$emit发布事件--传递数据
javascript 复制代码
<!-- 组件B:src/components/ComponentB.vue -->
<template>
  <div>
    <h3>组件B(发送方)</h3>
    <button @click="sendMessage">向组件A发送消息</button>
  </div>
</template>

<script>
import bus from '@/utils/eventBus' // 导入事件总线

export default {
  methods: {
    sendMessage() {
      // 发布名为 "sendToA" 的事件,并传递数据
      bus.$emit('sendToA', '你好,组件A!我是组件B~')
    }
  }
}
</script>

5.UniApp中分包

通过将代码拆分为主包和多个分包,实现按需加载,提升应用性能。

5.1分包概念
  1. 主包:包含启动页、TabBar 页面及所有分包都需用到的公共资源(如全局组件、工具类),是应用首次启动时必须加载的部分。

  2. 分包:按功能模块拆分的代码包,只有当用户访问分包内的页面时,才会触发下载(H5 端除外,H5 会打包为单独 chunk,按需加载)。

  3. 限制

    • 微信小程序:主包 + 所有分包大小不超过 20MB,单个分包不超过 2MB(最新限制可能放宽,以官方文档为准)。

    • 其他平台(如 App、支付宝小程序等)也有各自的大小限制,需参考对应平台规范。

5.2分包配置方法

项目根目录的 pages.json 中配置 subPackages(或 subpackages,大小写不敏感)

javascript 复制代码
{
  "pages": [
    // 主包页面(必须放在 pages 数组中)
    {
      "path": "pages/index/index",
      "style": { ... }
    },
    {
      "path": "pages/login/login",
      "style": { ... }
    }
  ],
  "subPackages": [
    // 分包 1:用户模块
    {
      "root": "pages/user", // 分包根目录(需手动创建文件夹)
      "pages": [
        {
          "path": "profile/profile", // 页面路径,完整路径为 pages/user/profile/profile
          "style": { ... }
        },
        {
          "path": "settings/settings", // 完整路径:pages/user/settings/settings
          "style": { ... }
        }
      ]
    },
    // 分包 2:商品模块
    {
      "root": "pages/goods",
      "pages": [
        {
          "path": "list/list",
          "style": { ... }
        }
      ]
    }
  ]
}
5.3分包预加载与页面跳转

页面跳转:分包内页面的跳转路径需使用完整路径(包含分包根目录)。

javascript 复制代码
// 从主包跳转到分包页面
uni.navigateTo({
  url: '/pages/user/profile/profile'
});

// 分包内页面互跳(也需完整路径)
uni.navigateTo({
  url: '/pages/goods/list/list'
});

分包预加载 :配置分包在特定时机预加载(进入主包某页面),在 pages.json 中添加 preloadRule。

javascript 复制代码
{
  "preloadRule": {
    // 当进入主包的 index 页面时,预加载 user 分包
    "pages/index/index": {
      "network": "all", // 网络环境:all(不限)/ wifi(仅wifi)
      "packages": ["pages/user"] // 需预加载的分包 root 列表
    },
    // 当进入 goods/list 页面时,预加载其他分包
    "pages/goods/list/list": {
      "network": "wifi",
      "packages": ["pages/order"]
    }
  }
}

6.其他的一些面试问题前期有面过

6.1生命周期,promise,事件循环(同步任务,微任务),canvas,输入地址流程,页面渲染流程,git提交代码,markdown样式调整,响应原理,数据更改后未渲染,created与mounted操作dom节点,echarts图表的实际运用。
相关推荐
葡萄城技术团队4 小时前
Vue 生态下前端 Excel 导入导出终极方案:SpreadJS 实战指南
vue.js
葡萄城技术团队4 小时前
SpreadJS 赋能在线 Excel:协同编辑与精细化权限管控的技术实现
前端
Chloe_lll4 小时前
threejs(七)PBR材质
开发语言·javascript·材质
转转技术团队4 小时前
转转商品中心微前端升级之路
前端
love530love5 小时前
【笔记】解决 ComfyUI 安装节点 ComfyUI-Addoor (葵花宝典)后启动报错:No module named ‘ComfyUI-Addoor’
linux·运维·前端·人工智能·windows·笔记·python
zzywxc7875 小时前
解锁 Rust 开发新可能:从系统内核到 Web 前端的全栈革命
开发语言·前端·python·单片机·嵌入式硬件·rust·scikit-learn
知新坊5 小时前
RustDesk 完整部署教程:支持 Web 管理后台和网页客户端远程,保姆级教学来了!
前端
敲敲了个代码5 小时前
UniApp 多页面编译优化:编译时间从10分钟到1分钟
开发语言·前端·javascript·学习·uni-app
景彬5 小时前
小红书小组件开发 最早踩坑版
前端·微信小程序