vue
路由懒加载
当打包构建应用时,JavaScript 包会变得非常大,影响页面加载。如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就会更加高效。
Vue Router 支持开箱即用的动态导入,这意味着你可以用动态导入代替静态导入:
1 | // 将 |
component
(和 components
) 配置接收一个返回 Promise 组件的函数,Vue Router 只会在第一次进入页面时才会获取这个函数,然后使用缓存数据。这意味着你也可以使用更复杂的函数,只要它们返回一个 Promise :
1 | const UserDetails = () => |
HashRouter和 HistoryRouter的区别和原理?
hashRouter原理
- HashRouter 使用 URL 的哈希(即
#
符号后面的部分)来模拟完整的 URL 路径。 - 当哈希值改变时(例如从
#home
变为#about
),页面不会重新加载。相反,这种变化可以通过 JavaScript 捕捉到,并且可以用来动态地加载视图而不刷新页面。 - 哈希变化不会导致浏览器向服务器发送请求,因为哈希永远不会被包括在 HTTP 请求中。
使用场景
不支持HTML5,适合老的浏览器
适用那些不需要SEO的
HistoryRouter原理
- HistoryRouter 利用 HTML5 的 History API 来维护浏览历史记录和 URL 的变化。
- 使用
pushState
、replaceState
方法和popstate
事件来实现 URL 的变化而不重新加载页面。 - 当这些方法被调用时,它们会改变浏览器的 URL 地址栏,但不会发送请求到服务器。
两者区别
url格式:HashRouter包括#符号,HistoryRouter:不带
服务器配置:HashRouter不需要特殊的服务器配置,因为 URL 的哈希部分永远不会发送到服务器。HistoryRouter
需要服务器对所有可能的路由请求返回同一个 HTML 文件,否则用户直接访问http://example.com/about
可能会导致 404 错误,除非服务器特别配置了路由规则。
浏览器兼容:hashRouter:在所有浏览器中都能工作,historyRouter:需要浏览器支持
SEO:前者不利于搜索,后者有利于
Vue2.0 双向绑定的原理与缺陷?
Vue 2.0 使用 Object.defineProperty 来实现响应式系统。这个方法允许对一个对象的属性进行拦截,当属性被访问或修改时,Vue 可以捕捉到这些变化并做出相应的响应,如视图更新。
- 响应式对象:
- Vue 在初始化实例时对 data 对象的属性执行递归遍历,使用
Object.defineProperty
将它们转化为 getter/setter,并收集依赖(即数据与视图之间的依赖关系),这是其双向绑定的核心。
- Vue 在初始化实例时对 data 对象的属性执行递归遍历,使用
- 依赖收集:
- 当渲染函数被执行时,会读取到使用的属性,属性的 getter 函数就会执行。在 getter 函数中,会将当前的 watcher(观察者,即依赖)添加到这个属性的依赖列表中。
- 派发更新:
- 当属性的值发生变化时,setter 会被调用,它会通知所有依赖于该属性的 watcher 对象,执行它们的 update 方法,引起视图的重新渲染。
缺陷:
新增或删除属性:Vue 2.0 不能检测到对象属性的添加或删除。因此,如果你需要在对象上添加新的属性,需要使用 Vue.set
或者 this.$set
方法。
Vue3.0 实现数据双向绑定的方法?
原理:
Vue 3.0 引入了 Composition API 和使用 Proxy 对象来实现响应式系统,这是一种更为高效和强大的方式。
- Proxy:
- Vue 3.0 使用
Proxy
对象包裹 data 对象,可以拦截对象的任意属性的读取和修改操作,包括属性添加和删除等操作。 Proxy
可以监听动态添加的属性和删除的属性,也可以监听数组索引和长度的变化。
- Vue 3.0 使用
- Reactivity API:
- Vue 3.0 提供了
reactive
,ref
, 和computed
等 API 来创建响应式数据。 reactive
用于创建响应式对象,ref
用于创建响应式的基本类型值。
- Vue 3.0 提供了
react
React生命周期的各个阶段是什么?
初始化阶段
constructor()
: 构造函数,用于初始化组件的状态。static getDerivedStateFromProps()
: 接收新的 props 和旧的 state,返回一个对象来更新 state,或者返回 null 表示不需要更新。render()
: 渲染组件,返回一个 React 元素。
更新阶段:
shouldComponentUpdate()
: 接收新的 props 和 state,返回一个布尔值来决定是否需要重新渲染组件。static getSnapshotBeforeUpdate()
: 在组件更新之前(DOM 更新之前)调用,可以返回一个值,该值会在 componentDidUpdate 中作为参数传入。
渲染输出阶段:
render()
: 组件的输出,返回一个 React 元素。
卸载阶段:
componentWillUnmount()
: 组件卸载之前调用,用于清理工作,如定时器、事件监听器等。
挂载后阶段:
componentDidMount()
: 组件挂载(即添加到 DOM 后)之后立即调用,常用于执行 DOM 操作、发起网络请求等。
更新后阶段:
componentDidUpdate()
: 组件更新后调用,可以访问最新的 props 和 state,用于执行依赖于 DOM 的操作。
错误处理阶段:
static getDerivedStateFromError()
: 接收一个错误参数,返回一个对象来更新 state,或者返回 null 表示不需要更新。componentDidCatch()
: 接收一个错误参数和一个信息对象,信息对象包含组件堆栈等,用于错误边界的异常处理。
函数组件
,生命周期主要由 React Hooks 提供:
- 初始化:
- 使用
useState
来定义状态。
- 使用
- 依赖项获取:
- 使用
useEffect
来处理副作用和生命周期。
- 使用
- 更新:
useEffect
的第二个参数可以指定依赖项列表,当依赖项变化时触发更新。
- 卸载:
- 在
useEffect
中返回一个清理函数,用于组件卸载时执行清理操作。
- 在
ReactRouter基本用法是什么?
用LInk组件创建
1 | import { Link } from 'react-router-dom'; |
使用Navigate组件
1 | import { Navigate } from 'react-router-dom'; |
动态路由
1 | <Route path="/users/:userId" element={<UserProfile />} /> |
保护路由
你可以使用 Navigate
组件来重定向未授权的用户:
1 | <Route |
嵌套路由:
一层层路由嵌套
使用Outlet等等
React组件间传值的方法有哪些?
Props 传递:常见
提升状态:
- 将状态提升到共同的父组件中,然后通过props将其传递给需要它的子组件。
1 | // 父组件 |
Context API:
- 当你想要跨多层组件传递数据时,可以使用Context API,它提供了一种方式,可以跨层级提供和访问数据。
1 | const MyContext = React.createContext(defaultValue); |
状态管理库:
- 使用如 Redux、MobX、Zustand 等状态管理库来管理跨组件的状态。
Refs:
- 使用Refs在组件间直接访问DOM节点或组件实例。
回调函数之类