美文网首页
Vue3 踩坑记,持续更新

Vue3 踩坑记,持续更新

作者: 默默无闻的小人物 | 来源:发表于2021-09-18 09:33 被阅读0次
  • props的.sync在vue3中被移除
  • vue2中写法:
    组件内部:

定义 props:{name: String}
更新:$emit('update:name', 'xxxxx')
调用组件时::name.sync="name"

  • vue3中:
    组件内部:

定义:props:{name: String},emits:['update:name'],
更新:$emit('update:name', 'xxxxx')
调用组件时:v-model:name="name"
参考分页控件

  • 在setup() 里调用this.$xxxx 全局方法
// getCurrentInstance 获取当前实例
import { getCurrentInstance } from ‘vue’
const { ctx } = getCurrentInstance()
ctx.$xxxx
  • 在reactive里包含 ref的值时 不需要.value 否则会丢失响应

错误写法:

const name= ref('')
const body = reactive({
params: name.value // 会丢失响应
})

正确写法:

const name= ref('')
const body = reactive({
params: name
})
  • 使用provide 跟inject依赖注入时,provide 的是响应式对象,那inject的时候也是响应式对象。但是在reactive里包含 ref的值时 不需要.value 否则会丢失响应
  • reactive 不可以全量赋值,否则会丢失响应,如下:
let body = reactive({
    params: 'text'
})
错误: body = {} 
正确:body.params = 'text2'

这里我们可以封装一个函数用来快速赋值 reactive,并且页面会响应。代码如下:

/**
 * 将reactiveObj对象转换成targetObj对象的格式
 * 为解决 reactiveObj直接赋值targetObj还能在页面上进行响应
 * @param {reactive} reactiveObj  [setup中需要赋值的reactive对象]
 * @param {Object} targetObj [目标对象]
 */
export const setReactiveObj = (reactiveObj, targetObj) => {
  if (Array.isArray(targetObj)) {
    if (reactiveObj && reactiveObj.length) {
      reactiveObj.length = 0
    }
  }
  for (const key in targetObj) {
    if (Object.hasOwnProperty.call(targetObj, key)) {
      const val = targetObj[key]
      reactiveObj[key] = val
    }
  }
}

// 用法也很简单,例子如下
// 打开配置页
    function openDrawer(row) {
      drawer.value = true
      setReactiveObj(rowData, row) // rowData 是 reactive响应式代理对象,row是普通的对象
      getInfo(rowData.id)
    }
  • element-plus 中的tabs 组件,会默认加载所有tab的里面的内容,并不是只在切换的时候才加载。他的原理是显示隐藏,类似v-show
  • 项目编译的时候不报错,但是一直卡住在某个步骤比如一直卡在 98%。造成的原因很大一部分是因为某个组件中引入其他路径有问题。不存在或者错误写法。例如这么写: import {} from ''
  • 表单如果只有一个input的时候,回车会触发表单的提交导致页面刷新。这个问题原生上就有,注意加上@submit.prevent,阻止默认行为
  • 解决打包生产环境的时候报错 INTLIFY_PROD_DEVTOOLS is not defined

只需要在vue.config.js里面配置下面这句即可

    // 解决打包生产环境的时候报错 __INTLIFY_PROD_DEVTOOLS__ is not defined
    new webpack.DefinePlugin({
          __INTLIFY_PROD_DEVTOOLS__: JSON.stringify(false)
    })

完整代码下图


image.png
  • 更加规范的props和emits

在vue3中,父子组件传值的props和emits写法更加规范(命名更统一),体现在:v-model的变化

<template>
    <child-component v-model:value="myValue"></child-component>
</template>

v-model:value等同于props:'value'和emits('update:value')

需要指定emits,为了便于管理,建议在emits中定义所有用到的emit

export default {
   emits: ['update:value', 'otherEmit'],
   setup(props, { emit }) {
     emit('update:value')
     emit('otherEmit')
   },
 }
  • $listeners被移除

事件监听器也被包含还在了$attrs中,现在属性透传更方便了

  • $children 被移除

如果想访问子组件,使用$refs

  • 事件API被移除

$on,$off,$once不再使用。2.x的EventBus方法不能再使用。

  • Filter被移除

不能再用|使用filter。Sad。

  • 当使用 watch 选项侦听数组时,只有在数组被替换时才会触发回调。换句话说,在数组被改变时侦听回调将不再被触发。要想在数组被改变时触发侦听回调,必须指定 deep 选项
watch: {
  bookList: {
    handler(val, oldVal) {
      console.log('book list changed')
    },
    deep: true
  },
}
  • vue 打包后出现"Vue DevTools failed to load SourceMap: Could not load content : net::ERR_FILE_NOT_FOUND"错误

发生错误的原因是vue.config中的publicPath配置成了 '/'
1.解决办法 修改vue.config中的publicPath:"./"

module.exports = {
  publicPath: './', //部署项目的时候的基本url,替代原来的Baseurl,默认是'/'
}

五、element-plus 中的 tabs 组件,会默认加载所有 tab 的里面的内容

并不是只在切换的时候才加载。他的原理是显示隐藏,类似 v-show,如果需要避免这个情况则可以使用 动态组件方式: <components :is="xxx"> 参考
src\modules\physical-model\components\model-config-drawer\index.vue 组件

六、 项目编译的时候不报错,但是一直卡住在某个步骤比如一直卡在 98%。造成的原因很大一部分是因为某个组件中引入其他路径有问题。不存在或者错误写法。例如这么写: import {} from ''

七、 表单如果只有一个 input 的时候,回车会触发表单的提交导致页面刷新。这个问题原生上就有,注意加上@submit.prevent,阻止默认行为。 参考组件:src\modules\physical-model\components\add-attr-dialog\index.vue

八、 如果声明了 async 但是里面又没有用到 await 的话,可能会导致打包编译的时候报错。例如下面的写法:

onBeforeMount(async () => {
      isLoginControl()
        .then((r) => {
          show.value = true
        })
        .catch((err) => {
          console.log(err)
        })
    })

声明了 async 但是函数里面并没有结合 await 使用。运行的时候不报错,只有在打包生产的时候才报错,因为打包生产的时候 vue cli 内部会做一些优化处理。
报错如下图


async声明但没使用await导致的报错.png

九、遇到网页白屏或者不报错就是进不去的时候,需要把压缩去掉跟打印打开,然后重新发一下版,这样可以快速定位到报错信息。

十、 使用 setup 语法时,模板中用到了的响应式变量一定要声明,并且确保 return 出去了。虽然不会直接报错,但是会报不存在警告,容易引起一些列 bug。列如为什么组件值 undefined 啊,拿不到方法等。

十一、组件里面如果有 emit 了方法,则组件里面一定要在头部显示声明 emits。不然会报警告

export default defineComponent({
  name:'add-devices-dialog',
  components:{
    UploadConfigTable,
    SelectTemplateDialog
  },
  emits: ['handleClick', 'handleDeviceTotal'], // 显示声明
  setup(props, context) {
    let active = ref(0)
    let showDialog = ref(false)
    const addForm = ref(null)
    let selectTemplateRefs = ref(null)
    let uploadConfigTableDevice = ref(null)
  }

十二、 组件中声明 prop跟event处理器参数时,需要区分一下。请注意看下图说明,如十一点中声明 emits,在模板中是使用小写横线分割。在 js 中使用驼峰命名。所以在项目中我们可以看到 js 中组件名字是驼峰命名,在模板中是使用小写横线分割,所以注意下

大小写不敏感.png

十三、关于项目中 vue3 使用 watch 的时候捕获不到旧值得问题,请看我下面链接中写的文档

传送门:computed 与 watch 的区别

传送门:vue3 中 watch、watchEffect 区别

十四、 关于项目中大家经常犯的错,就是一个对象从外面传进来,然后重新赋值,然后操作新赋值的对象,会导致外面的那个对象也跟着改变。这是由于引用传值导致的。属于值传递中的基础。因为引用传值只会赋值地址。并不会赋值里面的对象、只是赋值这个对象中的地址。所以改了某个属性。那么两个对象都会同步变化。关于这方面的知识点。建议百度一下。好好弄清楚。避免经常犯错,项目中都是通过 import _cloneDeep from 'lodash/cloneDeep'深克隆来解决。项目中全局搜索_cloneDeep 即可

十五、 使用 <el-radio></el-radio>时,一定要给加上 el-radio-group 分组,一定要避免 每个<el-radio>里面添加 v-model 双向绑定。增加父节点 el-radio-group 在父节点上绑定即可。类似 js 中事件委托。这样不需要关注有多少个 el-radio。

错误写法:

<el-radio :label="0" v-model="argsForm.rwType" disabled>读写</el-radio>
<el-radio :label="1" v-model="argsForm.rwType" disabled>只读</el-radio>
<el-radio :label="2" v-model="argsForm.rwType" disabled>只写</el-radio>

正确写法

<el-radio-group v-model="argsForm.rwType" disabled>
    <el-radio :label="0">读写</el-radio>
    <el-radio :label="1">只读</el-radio>
    <el-radio :label="2">只写</el-radio>
</el-radio-group>

十六、切换路由的时候报错 parentComponent.ctx.deactivate is not a function

1、查看是否使用了动态组件 <component :is="xx">这种方式

2、 是否使用了 <keep-alive></keep-alive>包裹

解决方式,一般只需要在 <component> </component> 绑定 key 即可。

如下面代码

 <keep-alive :include="tagsList">
    <component :is="Component" :key="route.name" />
  </keep-alive>

如果上面没有:key 则可能会偶尔报错。

十七、 打包之后上了生产环境的时候报错 __INTLIFY_PROD_DEVTOOLS__ is not defined

解决方式需要在 webpack 配置中增加如下配置代码

    // 解决打包生产环境的时候报错 __INTLIFY_PROD_DEVTOOLS__ is not defined new webpack.DefinePlugin({
        __INTLIFY_PROD_DEVTOOLS__: JSON.stringify(false)
    }),

十八、 ref和reactive创建的响应式变量, 不能进行解构或展开, 否则变量将失去响应效果.如果要结构响应式变量, 需要通过toRefs转一下

 import { toRefs } from 'vue'
    export default {
      props: {
        currentId: {
          type: String,
          default: ''
        }
      },
      setup(props) {
      const { currentId } = toRefs(props)
        console.log(currentId.value)
      }
    }

十九、 在 setup 中获取组件的 ref 对象

  • 在组件上声明其 ref
  • 在 setup 函数中创建 与组件 ref 同名 ref 对象 并导出
   <template>
      <!-- 同名ref -->
      <test1 ref="test1Ref"></test1>
    </template>

    <script>
    import { ref } from 'vue'
    // 导入组件
    import test1 from './test1'
    export default {
      // 注册组件
      components: { test1 },
      setup () {
        // 创建同名ref
        const test1Ref = ref(null)

        // 导出ref
        return {
          test1Ref
        }
      }
    }
    </script>

二十、如果给reactive传递了其他对象(如时间对象),默认情况下修改对象界面不会自动更新,如果想更新,可以通过给对象重新赋值来解决

// 如下通过setDate方法直接更改变量值不会生效,页面不会更新

eleData.params.startTime.setDate(eleData.params.startTime + 1)

// 需要重新赋值,页面上才会更新
eleData.params.startTime = new Date(newStartTime)
eleData.params.endTime = new Date(newEndTime)

二十一、路由里面配置的的name一定要跟对应组件里面的name保持一直,不然keep-alive将找不到对应的组件来缓存!!!!!!!!!!!!!!!!

二十二、组件里面的name请使用驼峰命名不要使用 横线链接。并且组件名称要为多个单词组成

二十三、注意,虽然vue3中 template模板已经支持多个根节点。但是我们还是尽量不要这么用,最好还是保留一个根节点,把其他子组件包裹起来,不然会引起一些莫名的bug,或者影响整个布局。

二十四、

相关文章

  • Vue3 踩坑记,持续更新

    props的.sync在vue3中被移除 vue2中写法:组件内部: 定义 props:{name: Strin...

  • Flutter 踩坑🕳️ 记,持续更新~

    用这个包 agora_rtc_engine之后,IOS模拟器跑不起来了?,报错如下: ? 解决方法:升级一下pod...

  • weex 踩坑记(持续更新中……)

    消失了一个月,努力为新项目倒腾 weex 中,记录一下遇到的问题。之后还会持续更新~ 目前,我使用的 weex 都...

  • RecyclerView踩坑记(持续更新中……)

    1、 今晚把自己项目中的ListView换成了RecyclerView,结果就踩坑了item_layout进行了如...

  • Yii2.0踩坑记(持续更新)

    ActiveForm表单提交后,通过网页中Network可知表单数据已经向控制器提交。但是,控制器中却接受不到数据...

  • HTML前端样式踩坑记【持续更新】

    前言:一个小白在写前端代码过程中遇到的各种样式兼容问题记录 超长文本不自动换行超出边框的问题 需求:做一个展示错误...

  • spark踩坑记录(持续更新)

    1、如果在一个spark脚本需要用到某第三方类库,比如pymysql,则需要在集群的所有机器上都安装该类库,否则会...

  • uniapp踩坑记录--持续更新

    生命周期不生效 下午测了半天,我的生命周期函数onShow不生效,上网查询,貌似是小程序的问题,原因不明,代码如下...

  • iOS13适配

    参考: iOS13 适配踩坑 - 持续更新 iOS 13 适配要点总结 iOS 13 适配要点总结 1、prese...

  • zk学习踩坑

    持续更新中.... 硬件&软件环境 阿里云服务器服务器配置 zk版本 zookeeper-3.4.13 踩坑 本地...

网友评论

      本文标题:Vue3 踩坑记,持续更新

      本文链接:https://www.haomeiwen.com/subject/dhuegltx.html