-
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)
})
完整代码下图
-
更加规范的props和emits
在vue3中,父子组件传值的props和emits写法更加规范(命名更统一),体现在:v-model的变化
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,如果需要避免这个情况则可以使用 动态组件方式:
参考
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 内部会做一些优化处理。
报错如下图
九、遇到网页白屏或者不报错就是进不去的时候,需要把压缩去掉跟打印打开,然后重新发一下版,这样可以快速定位到报错信息。
十、 使用 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 中组件名字是驼峰命名,在模板中是使用小写横线分割,所以注意下
十三、关于项目中 vue3 使用 watch 的时候捕获不到旧值得问题,请看我下面链接中写的文档
传送门:computed 与 watch 的区别
传送门:vue3 中 watch、watchEffect 区别
十四、 关于项目中大家经常犯的错,就是一个对象从外面传进来,然后重新赋值,然后操作新赋值的对象,会导致外面的那个对象也跟着改变。这是由于引用传值导致的。属于值传递中的基础。因为引用传值只会赋值地址。并不会赋值里面的对象、只是赋值这个对象中的地址。所以改了某个属性。那么两个对象都会同步变化。关于这方面的知识点。建议百度一下。好好弄清楚。避免经常犯错,项目中都是通过 import _cloneDeep from 'lodash/cloneDeep'
深克隆来解决。项目中全局搜索_cloneDeep
即可
十五、 使用 时,一定要给加上 el-radio-group 分组,一定要避免 每个里面添加 v-model 双向绑定。增加父节点 el-radio-group 在父节点上绑定即可。类似 js 中事件委托。这样不需要关注有多少个 el-radio。
错误写法:
读写
只读
只写
正确写法
读写
只读
只写
十六、切换路由的时候报错 parentComponent.ctx.deactivate is not a function
1、查看是否使用了动态组件
这种方式
2、 是否使用了包裹
解决方式,一般只需要在绑定 key 即可。
如下面代码
如果上面没有: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 对象 并导出
二十、如果给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,或者影响整个布局。
二十四、
在setup中函数尽量使用function声明,因为使用let或者const声明的话,虽然变量会被提升,但是如果在初始化之前调用变量就会形成一个暂时性死区。导致报错。如果原来是正常运行着的。但是依赖升级或者重新安装之后出现了这个错误。那肯定就是这个原因造成的。所以大家在写代码的时候一定要注意一下。变量声明一定要放在最上方。函数尽量使用function。不要哪里用到了就在哪里去声明。写过后端的童鞋们都会有个习惯就是变量的声明都是放在最前面。
ps容易出现错误
如下:
ReferenceError: Cannot access ‘xxx‘ before initialization
拓展知识点:
- var的创建和初始化被提升,赋值不会被提升。
- let的创建被提升,初始化和赋值不会被提升。
- function的创建、初始化和赋值均会被提升。