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、slotTeleport、SuspensedefineAsyncComponent参考: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即可
//vue2const asyncComponent = () => import('./asyncComponent.vue')// 或者const asyncComponent = {component: () => import('./asyncComponent.vue')}
//vue3 ,需要使用defineAsyncComponent 声明// ... 像使用其他一般组件一样使用 AsyncCompimport { 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,// 展示加载组件前的延迟时间,默认为 200msdelay: 200,// 加载失败后展示的组件errorComponent: ErrorComponent,// 如果提供了一个 timeout 时间限制,并超时了// 也会显示这里配置的报错组件,默认值是:Infinitytimeout: 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
// vue2const 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
//vue3import { inject } from 'vue'export default {props: {theme: {default (props) {// `props` 是传递给组件的原始值。// 在任何类型/默认强制转换之前// 也可以使用 `inject` 来访问注入的 property// 使用inject后,实例中可直接使用this.theme调用return inject('theme', 'default-theme')}}}}
// vue3const 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.jsimport 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.jsconst 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) // 0await 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修改的