vue3以及TS知识点和错误归纳

157 阅读2分钟

1. 常见问题

1.1 const reactive 及 props

  • 形如如下形式的代码是不能直接将 reactive 赋值的,即 obj = obj1 写法是错误的,obj 是常量,禁止直接赋值。修改方法有两种:
      1. obj.name = 'yyy'
      1. const obj = {test: {name: 'xxx'}}

方式一适用于参数很少的时候,可以直接内层赋值;当参数很多的时候,比如从后端请求到的数据,最好在内层嵌套一层,方便修改。

const obj = reactive({
  name: 'xxx'
})

// 方式二
const obj = reactive({
  test: {
    name: 'xxx'
  }
})
const test = reactive({
  test: {
    name: 'yyy'
  }
})
obj.test = test
  • reactive 引用问题
    • 在下面的代码中 someObj 也会变成响应式对象,当退出登录并重新登录后,会发现 obj1 的值和之前的一样,解决方案是将 someObj 中的对象移到 obj1 中。
// config.js
const someObj = {
  name: 'xxx',
  age: 'xxx'
}

// index.vue
import {someObj} from './config'
const obj1 = reactive(someObj)
  • props 传参值引用相同问题
    • 当父组件将要修改的表单参数传递给子组件时,此时子组件使用 props 来接收值,此时会使用另一个变量来保存初始值,方便在提交表单时可以比较修改后的值和初始值,这种情况我们修改在监听 props 时判断 init 变量是否为空,如果不为空,那么就不允许重新赋值。
    // parent
    const editedParams = reactive<someType>({
      name: 'xxx',
      age: 8
    })
    
    const openEditedDialog = (row: someType) => {
      Object.keys(editedParams).map(editedParams[item] = row[item])
    }
    
    // child
    const editionParams = reactive(props.editedParams)
    let editionParamsInit = reactive({})
    
    watch(() => props.editedParams, (newValue) => {
      const initKeys = Object.keys(editionParamsInit)
      if (!initKeys.length) editionParamsInit = JSON.parse(JSON.stringify(newValue))
      
      Object.keys(editionParams).map(item => editionParams[item] = newValue[item])
    }, { deep: true })
    
    const submitEditionDialog = () => {
      ...
      // after request status is 200/OK
      editionParamsInit = {}
      ...
    }
    
  • props 传参出现警告:Invalid prop:type check failed for prop

image.png

这种情况给参数一个初始值即可。比如:

// parent
const tableHeight = ref()

// child
const childTableHeight = ref(props.tableHeight)
watch(() => childTableHeight, () => {})

// 修改后
const tableHeight = ref(0)

1.2 ts对象赋值出现 Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 错误

  • 解决方案:在类型声明中使用 extends 继承对象的索引声明,此外在函数体中还需要进行类型收窄。
// 类型声明
export interface IObjectKeys {
  [key: string]: string | number | null
}
export interface IDetailKeys {
  patent: IObjectKeys
  patentExtension: IObjectKeys
  patentSummary: IObjectKeys
  patentClaim: IObjectKeys
  patentReview: IObjectKeys
}
export interface IBasicInfo1Edit extends IObjectKeys {
  id: number
  name: string | number
}

// 函数体
Object.keys(obj).map(
    (item) =>
      (obj[item] = someObj[item as keyof typeof someObj)
  )

PS: 上述函数体中的obj对象是参数个数较少的对象,someObj参数较多。有关此问题的详细解答:stackoverflow.com/questions/5…

1.3 前端配置 history 路由后出现 404

这个问题可以从前后端两个方向考虑:后端在 Nginx 配置问题的;前端配置问题。 可能是前端在 vue.config.js 中的 publicPath 配置错误,此时修改它即可正确访问。

image.png

1.4 响应式

响应式是通过函数数据二者一起实现的。

  • 函数
    • render
    • computed
    • watchEffect
    • watch
  • 数据
    • 响应式数据
    • 必须在函数中用到