项目中遇到的问题
大纲链接 §
[toc]
推荐阅读 Vite真香之路 问题记录
pnpm add -g pnpm安装路径提示错误 无法升级 The location of the currently running pnpm differs from the location where pnpm will be installed ⇧
复现
- 运行
pnpm add -g pnpm 会报如下错误:
1 2 3 4Nothing to stop. No server is running for the store at C:\Users\XXX\AppData\Local\pnpm\store\v3 The location of the currently running pnpm differs from the location where pnpm will be installed Current pnpm location: C:\Users\XXX\AppData\Roaming\npm Target location: C:\Users\XXX\AppData\Local\pnpm
解决
- 使用
npm install -g pnpm
参考
- mac The location of the currently running pnpm differs from the location where pnpm will be installed
- 安装pnpm
- pnpm中文
build遇到报错 The service was stopped: write EPIPE ⇧
failed to load config from xxx\vite.config.ts error during build:Error: The service was stopped: write EPIPE- 重启服务即可 抽风,同端口号
3000被占用- 管理员模式 打开终端 运行
net stop winnat && net start winnat
- 管理员模式 打开终端 运行
如何在生命周期中恰当地处理异步与异步传递数据
createdmounted- 组件间传递数据
登录注册 错误时也跳转 ⇧
- 已解决 bug
解决 使用tsx语法 使用slot插槽报错 [Vue warn]: Slot "default" invoked outside of the render function: this will not track dependencies used in the slot. Invoke the slot function inside the render function instead. ⇧
- 请求先后
- 先获取总的数据 前一个生命周期
onBeforeMount
参考
- arco-design-vue issues Select组件不显示placeholder属性 #236
- Add a class to every child of a slot
- In Vue.js can a component detect when the slot content changes
ts 动态声明字符串模板变量类型 ⇧
|
|
样式设置了overflow-x: hidden;导致了window.scrollTo失效 ⇧
@/components/BlogBody.tsx
- 记录当前滚动位置
const scrollTop = document.documentElement.scrollTop || document.body.scrollTop; - 记录初始/上一次滚动位置
oldScrollTop.value = scrollTop;,初始为const oldScrollTop = ref(0); - 记录对比当前和上一次滚动位置差值
const scrollStep = scrollTop - oldScrollTop.value; scrollStep为正 向下 隐藏导航栏;为负 向上 显示导航栏1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56import {defineComponent, onMounted, onUnmounted,} from 'vue'; // props const BlogBodyProps = { isSHow: Boolean }; export default defineComponent({ name: 'BlogBody', props: BlogBodyProps, components: {}, emits: ['showHeaderFooter'], setup(props, ctx) { // 获取 节点,非实时响应式 const main = ref(); const oldScrollTop = ref(0); // 按滚动方向自动显示/隐藏 回调 const scrollingCB = () => { // 滚动条距文档顶部的距离(做兼容处理) // 注意是对象 document.documentElement 的属性 scrollTop // 监听 window.document 的元素 documentElement.scrollTop 属性值变化 const scrollTop = document.documentElement.scrollTop || document.body.scrollTop; // 滚动条滚动的距离 const scrollStep = scrollTop - oldScrollTop.value; // 更新——滚动前,滚动条距文档顶部的距离 oldScrollTop.value = scrollTop; // 关键 scrollStep 为正 向下 隐藏导航栏; // 为负 向上 显示导航栏 scrollStep < 0 ? (ctx.emit('showHeaderFooter', true)) : (ctx.emit('showHeaderFooter', false)); }; onMounted(() => { window.document.addEventListener('scroll', scrollingCB); }); onUnmounted(() => { window.document.removeEventListener('scroll', scrollingCB); }); return { main, }; }, render() { return ( <main ref={(el) => this.main = el}> <router-view/> </main> ); } });
@/components/Layout.tsx
|
|
@/styles/layout.module.scss
|
|
参考
- stackoverflow window.pageYOffset is always 0 with overflow-x: hidden
- stackoverflow overflow-x:hidden still can scroll
- window.pageYOffset is always 0 with overflow-x: hidden
- CSS Tricks How to Make an Unobtrusive Scroll-to-Top Button
- CSS深入理解之overflow 笔记
- Vue实现某个元素监听滚动条失效问题(scrollTop一直等于0 )
- 溢出 | overflow
- overflow Runebook.dev
- css笔记 - 张鑫旭css课程笔记之 overflow 篇
报错[Vue warn]: Unhandled error during execution of render function ref=Ref< undefined > ⇧
render()函数中的数据在组件创建时,直接调用beautifyDate()时还未初始化,导致报错- 解决方法:在调用异步方法
getBlogDetail()内部,执行方法beautifyDate(),并赋值给已定义的响应式数据createdAt.value - 在
render()函数中使用this.createdAt而不是直接调用beautifyDate()
css modules 中如何使用 深入组件样式? ⇧
- 想使用jsx写法编写组件的时候,无法使用scoped这个用法
- 因为jsx等同于一个js文件,里面可写不了template与style标签
- tsx直接使用字符串
return <div class="test">,会导致样式文件会挂载到全局的style标签上,且类名没有任何转译,这样就会容易造成样式污染 - 要覆盖子组件内部的元素样式
cover-ant.scss
|
|
在路由中使用 defineAsyncComponent动态引入组件 ⇧
原来
@/router/index.ts
|
|
import('xxx')必须是静态字符串,不可动态拼接- 否则报错
The above dynamic import cannot be analyzed by vite
改为使用
defineAsyncComponentAPI
- 返回
promisedefineAsyncComponent(() => {return new Promise((resolve, reject) => {...})})
- 使用
import函数作为返回值:defineAsyncComponent(() => (import('./components/MyComponent.vue')))
- vue3 Async Components
@/router/index.ts
|
|
使用
defineAsyncComponent动态加载组件时,会出现警告1[Vue Router warn]: Component "default" in record with path "/" is defined using "defineAsyncComponent()". Write "() => import('./MyPage.vue')" instead of "defineAsyncComponent(() => import('./MyPage.vue'))".代替原来的静态引入
import BlogIndex from '@/pages/blog/index/BlogIndex';直接动态引入
() => import('./MyPage.vue'))
@/router/index.ts
|
|
参考与相关类似问题 ⇧
- [Vue warn]: Failed to resolve component when tried to create global component stackoverflow
- Dynamically Import Vue Component Based On URL Params stackoverflow
- Invalid VNode type: undefined (undefined) - when used with
- Vue js import components dynamically
- Vue warn: Invalid VNode type: undefined (undefined)
报错[Vue warn]: Invalid VNode type: undefined (undefined) ⇧
- 识别不出节点的类型
- 是由于我在JSX中写了不合法的注释节点
{{/*xxxxx*/}}
自定义组件 JSX 事件 ⇧
使用自定义事件
- 要声明一个自定义事件:
onHandleSubmit - 子组件
- 声明选项
emits: ['handleSubmit',], - 在
setup选项中传参setup(props, ctx) {} - 定义 发布方法
const clickHandler = () => {ctx.emit('handleSubmit');} - 返回
return {clickHandler} - 在
render方法中使用render() {return <button onClick={this.clickHandler}></button>}
- 声明选项
- 父组件
- 在
setup选项中 - 定义 处理逻辑的方法
const clickHandler = () => {} - 在
render方法中使用自定义事件<UserSubmitBtnTip onHandleSubmit={this.clickHandler}/>
- 在
判断键盘抬起时,键盘值
- 自定义组件中有
<input/>,事件keyup不能绑定在自定义组件上,而是绑定在内部的的<input/>上 - 通过
props传一个keyUpHandler到内部 - 无修饰符,只能使用
event: KeyboardEvent中的event.key来判断,是否按下Enter键["Enter"].includes(event.key)
UserInput.tsx
|
|
Login.tsx
|
|
参考
- Vue JS - Conditional keyup.enter is not working stackoverflow
- JSX Introduction by facebook
- Using Vue 3 with JSX and TypeScript
- Lightweight Components with Vue 3 and JSX
- Programming VIP Vue-3 props, $emit, slot, render, JSX and createElement
- Vue3 Listening to Events
- Vue3 Declaring Emitted Events
- Emitting and Listening to Events
- How to emit event from JSX functional component in Vuejs
- 在vue3中编写jsx的两种方式
- vue中正确使用jsx语法的姿势分享1
- vue中正确使用jsx语法的姿势分享2
- 在vue中使用jsx的正确姿势3
- vue使用typeScript+jsx报错问题
JSX不支持在
setup方法中写defineEmits
- 必须换成选项写法
emits: ['xxx', 'update:xxx']
vite2 jsx/tsx 写vue提示:React is not defined ⇧
🚑 解决引入 module 类型报错 ⇧
- vuex4.0中使用typescript, vuex4.0中modules的ts使用,vue3 + vuex4.0 + typescript 使用详情
- vuex4 中 typescript 的使用,以及 store 的一些坑
- Vue状态管理:使用Pinia代替Vuex坑
- 抛弃 Vuex,使用 Pinia
- 赋予Vuex 4.x 更好的 TypeScript体验
- vuex@4 + TypeScript
- Vuex4 对 TypeScript 并不友好,所以我选择 Pinia
- 如何在TypeScript中使用Vuex
pinia 遇坑 ⇧
- 报错
Uncaught Error: [🍍]: getActivePinia was called with no active Pinia. Did you forget to install pinia? - 在
router中使用的例子,必须在钩子函数中声明const store = useStore(),而不是在钩子外 - Pinia官网示例
- Pinia官网示例 Using a store outside of a component
- Pinia官网示例 Using the store outside of setup()
- github issue #666 I can’t use pinia outside of component setup
stackoverflow Vue: Can’t access Pinia Store in beforeEnter vue-router
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24import { createRouter } from 'vue-router' const router = createRouter({ // ... }) // ❌ Depending on the order of imports this will fail const store = useStore() router.beforeEach((to, from, next) => { // we wanted to use the store here if (store.isLoggedIn) next() else next('/login') }) // Good way below router.beforeEach((to) => { // ✅ This will work because the router starts its navigation after // the router is installed and pinia will be installed too const store = useStore() if (to.meta.requiresAuth && !store.isLoggedIn) return '/login' })
@at-root 使用css预处理器写css时缩小嵌套层级 ⇧
嵌套过深
- css是从右到左解析的,所以层数越多对于解析会越不利
- 后代选择器会增加样式权重,造成样式权重越来越高的恶性循环
- 滥用 less sass 的嵌套写法会让代码不易于阅读
别让你的嵌套层级超过四层,不然就重构
- 在Sass中还提供了一个
@at-root的功能,可以让你直接跳出去。这样也可以避免嵌套层级过深 - 命名方式上可以解决,如:BEM
- 提取公用逻辑
@at-root
|
|
相似问题:前端路由多层级嵌套太深且重复的问题
使用引入的组件时报错TS2604: JSX element type 'XXX' does not have any construct or call signatures. ⇧
是因为组件未使用
defineComponent1 2 3 4 5<script lang="ts"> export default { ... }; </script>
改为以下示例,即可
|
|
网站搜索只能搜到react的相关内容
https://stackoverflow.com/questions/53449101/typescript-type-definition-ts2604-jsx-element-type-something-does-not-have-a | javascript - Typescript type definition: TS2604: JSX element type ‘something’ does not have any construct or call signatures - Stack Overflow https://segmentfault.com/q/1010000040209283 | 我想在.ts文件中使用JSX.Element对象,要怎么写。 - SegmentFault 思否 https://www.jianshu.com/p/ece127ffc996 | (转载)使用TS报错:TS7026: JSX element implicitly has type ‘any’…处理总结 - 简书 https://stackoverflow.com/questions/46080760/error-ts2604-jsx-element-type-does-not-have-any-construct-or-call-signatu | reactjs - Error TS2604: JSX element type ‘…’ does not have any construct or call signatures - Stack Overflow https://stackoverflow.com/questions/31815633/what-does-the-error-jsx-element-type-does-not-have-any-construct-or-call | reactjs - What does the error “JSX element type ‘…’ does not have any construct or call signatures” mean? - Stack Overflow https://stackoverflow.com/questions/54143658/typescript-ts2604-jsx-element-type-drawer-does-not-have-any-construct-or-call | reactjs - Typescript TS2604: JSX element type ‘Drawer’ does not have any construct or call signatures - Stack Overflow https://stackoverflow.com/questions/53452966/typescript-3-jsx-element-type-component-does-not-have-any-construct-or-call-s | javascript - TypeScript 3: JSX element type ‘Component’ does not have any construct or call signatures. [2604] - Stack Overflow https://stackoverflow.com/questions/34971155/typescript-error-ts2604-how-to-fix | reactjs - Typescript Error: TS2604 - How to fix? - Stack Overflow https://github.com/Microsoft/TypeScript-React-Starter/issues/44 | error TS2604: JSX element type ‘Provider’ does not have any construct or call signatures. · Issue #44 · microsoft/TypeScript-React-Starter https://www.imooc.com/wenda/detail/629578 | 用于从字符串创建 JSX 元素的正确 TypeScript 类型_慕课猿问
setup()中写return () => (JsxDOM)和在render() {return (JsxDOM)}选项中写 ⇧
setup()中会覆盖掉render() {return (JsxDOM)}
IDE WebStorm 警告 在未导入 React 的情况下使用 JSX ⇧
- reactjs - 使用jsx不导入react
- 设置中关闭警告即可,React17+ 中无需再提示
- reactjs - React JSX 无需导入 React 即可工作
- 无需导入 React 即可使用 JSX
- 关于reactjs:使用JSX react / react-in-jsx-scope时,’React’必须在范围内?
- 不引入react的情况下使用JSX
- React17 使用 JSX 的情况下无须再显式导入 React
- 在没有导入的情况下使用JSX在React中显示图像
- React17 使用 JSX 的情况下无须再显式导入 React
- 拥抱 Vue 3 系列之 JSX 语法
- 在Vue中使用JSX的正确姿势
引入无props的组件时,报错 ⇧
.tsx文件1 2 3 4 5 6
render: () => { ... const BlogHeaderDOM = <BlogHeader></BlogHeader> const BlogFooterDOM = <BlogFooter></BlogFooter> ... }1 2 3 4 5 6 7 8 9> 解决方法 - 添加`props` --- ## 在`tsx`文件中写点击事件绑定方法时`<Button onClick={xxx}>...</Button>` 报类型错误 <a href="#catalogue"> ⇧ </a> - `... is not assignable to type '(((event: MouseEvent) => void) & ((...args: any[]) => any)) | undefined'.`tsx
import {Button, message} from ‘ant-design-vue’; import {defineComponent, inject} from ‘vue’; import ‘ant-design-vue/dist/antd.css’;
export default defineComponent({
name: ‘BlogIndex’,
props: {},
components: {},
setup(/props, ctx/) {
const popMessage = inject
});
1 2 3 4 5 6 |
- 解决方法:`<Button onClick={()=> {popMessage && popMessage.error('这是一条错误消息', 2)}}>博客首页</Button>`
- 必须再套一层箭头函数 `Try just wrapping the event handler in a fat arrow function:`
- `onClick={() => {addClient()}}`
- 参考[github issue: Mutation and TypeScript: Error when using onClick attribute with already declared interface](https://github.com/apollographql/react-apollo/issues/1841#issuecomment-377811526)
> 错误的范例 |
tsx import {Button, message} from ‘ant-design-vue’; import {defineComponent, inject} from ‘vue’; import ‘ant-design-vue/dist/antd.css’;
export default defineComponent({
name: ‘BlogIndex’,
props: {},
components: {},
setup(/props, ctx/) {
const popMessage = inject
1 2 3 |
return {
popMessageError
}; |
}, render() { // noinspection JSXNamespaceValidation return ( <> </> ); }
});
1 2 3 |
> [`vant UI`的写法](https://github.com/youzan/vant/blob/dev/packages/vant/src/card/Card.tsx)
- `<a onClick={(event: MouseEvent) => emit('click-thumb', event)}>...` |
tsx … render() { // noinspection JSXNamespaceValidation return ( <> </> ); } … ```
项目根目录不支持驼峰式命名 ⇧
- 使用短杠
-连接
端口号3000被占用 ⇧
- 重启
win10或win11的winnat服务 - Open PowerShell as Admin.
- stop winnat with command:
net stop winnat - start winnat again with command:
net start winnat - Error when starting dev server permission denied 127.0.0.1:3000 vite issue
- 使用
netstat -aon| findstr 3000找到对应进程 - 使用
taskkill /F /PID 8888杀死对应进程
误删了.idea文件 ⇧
.idea文件时webStorm项目的配置文件,删除会导致IDE识别文件目录,和布局错误- 如果误删了
.idea文件,可以点击文件菜单中的 修复IDE选项,根据事件日志中的提示,点选即可,重新加载项目目录
只用一种运行器 yarn | pnpm ⇧
pnpm为首选,一律使用pnpmyarn,混用时,yarn依赖优先