vscode
,官网也有讲 WebStorm
// .vscode/settings.json
{
"vetur.validation.template": false,
"vetur.validation.script": false,
"vetur.validation.style": false
}
volar
https://github.com/johnsoncodehk/volar脚手架
vuex换成了pinia https://pinia.vuejs.org/zh/
ref
实现,速度更快,由ref
和reactive
替换写在data中的数据(底层也是要转换成ref或reactive的)component
、slot
Teleport
、Suspense
defineAsyncComponent
参考:https://cn.vuejs.org/guide/essentials/lifecycle.html#lifecycle-diagram
vue2 option api | vue3 option api | vue 3 composition api |
---|---|---|
beforeCreate | beforeCreate | 不再需要,代码可直接置于setup中 |
created | created | 不再需要,代码可直接置于setup中 |
beforeMount | beforeMount | onBeforeMount |
mounted | mounted | onMounted |
beforeUpdate | beforeUpdate | onBeforeUpdate |
updated | updated | onUpdated |
beforeDestroy | 改为—> beforeUnmount | onBeforeUnmount |
destroyed | 改为—> unmounted | onUnmounted |
errorCaptured | errorCaptured | onErrorCaptured |
- | 新增—> renderTracked | onRenderTracked |
- | 新增—> renderTriggered | onRenderTriggered |
.sync
,直接使用v-model
即可
//vue2
const asyncComponent = () => import('./asyncComponent.vue')
// 或者
const asyncComponent = {
component: () => import('./asyncComponent.vue')
}
//vue3 ,需要使用defineAsyncComponent 声明
// ... 像使用其他一般组件一样使用 AsyncComp
import { defineAsyncComponent } from 'vue'
const AsyncComp = defineAsyncComponent(() => {
// 必须返回一个Promise对象
return new Promise((resolve, reject) => {
// ...从服务器获取组件
resolve(/* 获取到的组件 */)
})
})
//vue2的component改成了loader
//vue3 高级用法
const AsyncComp = defineAsyncComponent({
// 加载函数
loader: () => import('./Foo.vue'),
// 加载异步组件时使用的组件
loadingComponent: LoadingComponent,
// 展示加载组件前的延迟时间,默认为 200ms
delay: 200,
// 加载失败后展示的组件
errorComponent: ErrorComponent,
// 如果提供了一个 timeout 时间限制,并超时了
// 也会显示这里配置的报错组件,默认值是:Infinity
timeout: 3000
})
属性布尔值/非布尔值/枚举值变化
null
或undefined
$attrs 现在包含了所有传递给组件的 attribute,包括 class 和 style
详情参考:https://v3-migration.vuejs.org/zh/breaking-changes/attrs-includes-class-style.html
移除了$listeners,合并到了$attrs https://v3-migration.vuejs.org/zh/breaking-changes/listeners-removed.html
// vue2
<template>
<label>
<input type="text" v-bind="$attrs" v-on="$listeners" />
</label>
</template>
<script>
export default {
inheritAttrs: false
}
</script>
//vue3
<template>
<label>
<input type="text" v-bind="$attrs" />
</label>
</template>
<script>
export default {
inheritAttrs: false
}
</script>
移除了$children
https://v3-migration.vuejs.org/zh/breaking-changes/children.html
移除propsData
// vue2
const Comp = Vue.extend({
props: ['username'],
template: '<div>{{ username }}</div>'
})
new Comp({
propsData: {
username: 'Evan'
}
})
// vue3必须使用createApp方法
const app = createApp(
{
props: ['username'],
template: '<div>{{ username }}</div>'
},
{ username: 'Evan' }
)
inject
//vue3
import { inject } from 'vue'
export default {
props: {
theme: {
default (props) {
// `props` 是传递给组件的原始值。
// 在任何类型/默认强制转换之前
// 也可以使用 `inject` 来访问注入的 property
// 使用inject后,实例中可直接使用this.theme调用
return inject('theme', 'default-theme')
}
}
}
}
// vue3
const MyDirective = {
created(el, binding, vnode, prevVnode) {}, // 新增
beforeMount() {},
mounted() {},
beforeUpdate() {}, // 新增
updated() {},
beforeUnmount() {}, // 新增
unmounted() {}
}
Object
,只接受返回object
的 function
// vue3
<template>
<div>
<p>{{ text }}</p>
<button v-on:click="$emit('accepted')">OK</button>
</div>
</template>
<script>
export default {
props: ['text'],
emits: ['accepted']
}
</script>
$on
、$off
和 $once
方法,只保留了$emit
$on
、$off
和 $once
方法,不推荐使用(难以维护)
// eventBus.js
import emitter from 'tiny-emitter/instance'
export default {
$on: (...args) => emitter.on(...args),
$once: (...args) => emitter.once(...args),
$off: (...args) => emitter.off(...args),
$emit: (...args) => emitter.emit(...args),
}
替代Even Bus的方案
Props 和事件应该是父子组件之间沟通的首选。兄弟节点可以通过它们的父节点通信。
provide / inject 允许一个组件与它的插槽内容进行通信。这对于总是一起使用的紧密耦合的组件非常有用。
provide / inject 也能够用于组件之间的远距离通信。它可以帮助避免“prop 逐级透传”,即 prop 需要通过许多层级的组件传递下去,但这些组件本身可能并不需要那些 prop。
Prop 逐级透传也可以通过重构以使用插槽来避免。如果一个中间组件不需要某些 prop,那么表明它可能存在关注点分离的问题。在该类组件中使用 slot 可以允许父节点直接为它创建内容,因此 prop 可以被直接传递而不需要中间组件的参与。
全局状态管理,比如 Pinia。
$filter
过滤器
// vue3使用globalProperties 注册
// main.js
const app = createApp(App)
app.config.globalProperties.$filters = {
currencyUSD(value) {
return '$' + value
}
}
// 所有组合可使用
<template>
<h1>Bank Account Balance</h1>
<p>{{ $filters.currencyUSD(accountBalance) }}</p>
</template>
函数式组件
全局API的变化
会移动到应用实例上,以下是 Vue2 全局 API 及其相应的实例 API 列表:
2.x 全局 API | 3.x 实例 API (app ) |
---|---|
Vue.config | app.config |
Vue.config.productionTip | 移除 (见下方) |
Vue.config.ignoredElements | app.config.compilerOptions.isCustomElement (见下方) |
Vue.component | app.component |
Vue.directive | app.directive |
Vue.mixin | app.mixin |
Vue.use | app.use (见下方) |
Vue.prototype | app.config.globalProperties (见下方) |
Vue.extend | 移除 (见下方) |
所有其他不全局改变行为的全局 API 现在都是具名导出,文档见全局 API Treeshaking。
内联模板(inline-template) https://v3-migration.vuejs.org/zh/breaking-changes/inline-template-attribute.html
key属性的使用变化 https://v3-migration.vuejs.org/zh/breaking-changes/key-attribute.html
v-if
,v-if-else
,v-else
不再需要key<template v-for>
的 key 应该设置在 <template>
标签上 (而不是设置在它的子节点上)keycode(按钮修饰符)的变化
//vue2
<!-- 键码版本 -->
<input v-on:keyup.13="submit" />
<!-- 别名版本 -->
<input v-on:keyup.enter="submit" />
Vue.config.keyCodes = {
f1: 112
}
<!-- 键码版本 -->
<input v-on:keyup.112="showHelpText" />
<!-- 自定义别名版本 -->
<input v-on:keyup.f1="showHelpText" />
//vue3 直接使用键名,中线连接
<!-- Vue 3 在 v-on 上使用按键修饰符 -->
<input v-on:keyup.page-down="nextPage">
<!-- 同时匹配 q 和 Q -->
<input v-on:keypress.q="quit">
- 渲染函数 https://v3-migration.vuejs.org/zh/breaking-changes/render-function-api.html
- 就一点`h`函数不再是从参数中获取,是从全局导入
// Vue 3 渲染函数示例
import { h } from 'vue'
export default {
render() {
return h('div')
}
}
<!-- 模板 -->
<div id="red" v-bind="{ id: 'blue' }"></div>
<!-- 结果 -->
<div id="red"></div>
- vue3中看先后顺序,在后面的覆盖前面的
<!-- 模板 -->
<div id="red" v-bind="{ id: 'blue' }"></div>
<!-- 结果 -->
<div id="blue"></div>
<!-- 模板 -->
<div v-bind="{ id: 'blue' }" id="red"></div>
<!-- 结果 -->
<div id="red"></div>
v-model的变化 https://v3-migration.vuejs.org/zh/breaking-changes/v-model.html
使用watch监听数组(Array)的变化 https://v3-migration.vuejs.org/zh/breaking-changes/watch.html
// 不使用deep时,只有整个数组被替换才会触发watch
// 在vue2时,watch数组不需要使用deep,在vue2中,deep只是用在Object上
watch: {
bookList: {
handler(val, oldVal) {
console.log('book list changed')
},
deep: true
},
}
//vue2
// 修改数据
vm.msg = 'Hello'
// DOM 还没有更新
Vue.nextTick(function () {
// DOM 更新了
})
// vue3
// 需要引入
// 以传递一个回调函数作为参数,或者 await 返回的 Promise
<script>
import { nextTick } from 'vue'
export default {
data() {
return {
count: 0
}
},
methods: {
async increment() {
this.count++
// DOM 还未更新
console.log(document.getElementById('counter').textContent) // 0
await nextTick()
// DOM 此时已经更新
console.log(document.getElementById('counter').textContent) // 1
}
}
}
</script>
<template>
<button id="counter" @click="increment">{{ count }}</button>
</template>
表格如果字段多,有横向滚动条是不是不方便?可拖拽的滚动是不是就方便了?
使用create-vue创建vue3项目,vite,vue3
相对VUE2 ,VUE3做了哪些优化和改进呢?
vue项目,不使用window.location.reload(),如何刷新当前页面?
FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory
vue2.0 v-html指令有潜在的xss风险,如何解决?
vue项目通过axios怎么下载二进制文件或图片?
ant.design UI框架 同时使用v-model或value属性时, placeholder不显示
如何在VUE项目中添加stylelint,检查css,scss,less的语法问题,保证团队代码的规范统一
VUE全局函数
定义了服务端渲染的属性名称常量SSR_ATTR,定义了一些资产类型常量ASSET_TYPES,定义了生命周期相关钩子函数的函数名称
使用iviewui-admin框架构建管理系统时,遇到的各类问题
vue项目中动态图片路径拼接
vue下filter方法的调用
21个vue顶级UI框架: Vuetify,Quasar,Vue Material,Keen-UI,Buefy,Bootstrap Vue,Muse-UI,AT-UI,Vux,iView,Uiv,Vuikit,Onsen UI+Vue,Semantic UI+Vue,Fish-UI,Mint UI,Framework7 Vue,Cube UI,Vueblu,Ant Design Vue
&amp;amp;quot;.vue&amp;amp;quot;文件是如何解析成js对象的~
立个flag,看过年这段时间能不能把vue的源码读完?多年前看过jQuery的部分源码,如果想要更深入的了解vue,还是得从源码开始
vue源码阅读,慢慢学习
vue的生命周期函数
vue组件的数据data为什么一定要是函数 ?
Mint-ui this.$messagebox点取消时,报错:Uncaught (in promise) cancel
vue-validate使用
这就是个vue的坑。。。
vue如何监听enter事件?
vue使用axios进行form表单提交
vue中如何改变title标题
如果在vue2.0中使用NProgress进度条
Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。也是vue2.0官方推荐的,同时不再对vue-resource(vue1.0使用)进行更新和维护
分析Vue.js源码
npm run dev模式下,webpack4+vue2项目下,类似'/user/login'二级路由,刷新时静态资源路径不对,静态资源返回404
[Vue warn]: Error in render: "TypeError: Cannot read property 'matched' of undefined"
did you register the component correctly? For recursive components, make sure to provide the "name" option
vue.js如何查看注册了哪些组件,获取组件名称
vue底层的Virtual DOM就是基于snabbdom修改的