升级指南

Quasar CLI 基于 Vite 或者 Webpack

现在有基于 vite 和基于 webpack 两种版本的 Quasar CLI 可供选择。

组合式和选项式 API

您会发现文档的示例代码中都采用了 Vue 3 的组合式 API。但是这并不代表您也必须使用组合式 API,您仍然可以选择使用选项式 API。事实上,继续维护选项式 API 会使得升级过程更简单一些。升级成功之后我们更推荐您使用组合式 API,但这是可选的。

视频教程
New

点击下面的海报将打开一个 Youtube 播放列表,介绍如何将您的 Quasar CLI 项目从 Quasar v1 升级到 Quasar v2 的过程。随着我们使用 Quasar v2 的更新,它可能会失去同步,但它可能会帮助您开始。

老的 v2 升级到最新的 v2

UMD 版本

只需将引用 Quasar 及其所有 CSS 和 JS 链接中的版本号字符串替换为较新版本即可。

Quasar CLI 版本

# 在一个 quasar UI v2 的项目中运行以下命令

# 检查 quasar 有关可更新的包
$ quasar upgrade

# do the actual upgrade
$ quasar upgrade --install

建议也将 vue & vue-router 套件保持最新:

# 可选的,但是推荐
$ yarn add vue@3 vue-router@4

注意代码编辑器的终端

如果您在使用一个代码编辑器集成的终端来运行 quasar upgrade 命令,并获得了一个 Command not found 或者 @quasar/cli version appears to be undefined报错,那么您需要转到代码编辑器终端的设置,并取消选中添加“node_modules/”选项(或其等效项)。将“bin”从项目根目录设置为%PATH%,然后重新启动代码编辑器。

Quasar Vite plugin 版本

$ yarn upgrade quasar

可选的,您可能也想保证最新的 @quasar/vite-plugin

建议同时将 vue and @quasar/extras 保持最新:

# 可选的,但是推荐
$ yarn add vue@3 @quasar/extras@latest

Vue CLI 版本

$ yarn upgrade quasar

可选的,您可能也想保证最新的 vue-cli-plugin-quasar

建议同时将 vue and @quasar/extras 保持最新:

# 可选的,但是推荐
$ yarn add vue@3 @quasar/extras@latest

从 v1 迁移到 v2

这个指南适用于使用了 Quasar CLI 或 UMD 版本的项目,但是其中一些信息可能也对 Vue CLI 版本的项目有帮助。

对于已经在项目中使用 Vue CLI 的开发者,您可以查看如何安装与 Quasar v2 一起使用的 vue-cli-plugin-quasar 。您还需要对 main.js 进行一些更改,也要升级您的 Vue CLI 以支持 Vue 3。目前最好的方法是为 Vue 3 生成一个新的 Vue-CLI 项目,然后按照 Vue-CLI 插件 quasar 的安装步骤 i,检查该/src 文件夹中发生的更改,然后将相同原则应用于新的 Vue CLI 项目中。

WARNING

  • Quasar CLI for Quasar v1 only had the option to use Webpack. But now you can choose between Quasar CLI with Vite (currently in BETA) and Quasar CLI with Webpack. For upgrading purposes, you might want to upgrade to Quasar CLI with Webpack first, and then maybe try out Quasar CLI with Vite.
  • The rest of this guide will focus on Quasar CLI with Webpack.

Intro

We’ve put in a lot of work, so the transition from Quasar v1 to v2 is as painless as possible. Don’t be afraid by the length of this page, as it doesn’t reflect the effort that you need to put into upgrading your app to Quasar v2 (we just tried to make it as complete as possible). The API of Quasar components, directives and plugins has minor changes, but we kept the breaking changes to a bare minimum. We’ve also added some new cool features to some components.

Quasar UI v2 is based on Vue 3, as opposed to the previous version which was based on Vue 2. This means that your app code (Vue components, directives, etc) should be Vue 3 compliant too, not just the Quasar UI source-code. If you are using additional libraries in your app, please make sure that you are using their Vue 3 versions.

Quasar UI v2 is not just a port to Vue 3 and Composition API. There are lots of significant performance enhancements in Quasar’s algorithms too! You’ll love it!

IMPORTANT!

  • No IE11 support - Vue 3 does not support IE11 either. If IE11 support is mandatory for your project(s), then continue using Quasar UI v1.
  • In order to support Node 13+ (and for many other benefits) we have upgraded Webpack from v4 to v5. You may need to upgrade your webpack plugins accordingly.
  • Quasar Stylus variables are no longer available (only Sass/SCSS). This does NOT mean that you can’t use Stylus anymore though.
  • Node v10 reached its End Of Life and so support for it has been dropped. Be sure to update Node (to at least v12.22.1) and npm/yarn on your system accordingly to the new constraints, which include fixes for latest know security issues. This Node version also include native ESM module support, which will help us futher modernize Quasar codebase under the hood during Quasar v2 lifecycle without breaking changes.

Before you start with this journey of upgrading your project from v1 to v2, you should know a few additional things:

  1. Read the documentation before asking questions on Discord server or forums.
  2. Prepare a CodePen so staff can help you, if you think you’ve found an issue.
  3. Dig into the Quasar source code (it’ll help you understand the framework as well as teach you best practices for programming with Vue).
  4. Don’t use framework components as mixins unless absolutely necessary (wrap them if you need to).
  5. Don’t target inner component stuff with CSS selectors unless absolutely necessary.
  6. We recommend yarn whenever possible because of its speed and efficient use. However, when using globals, we still recommend using npm, especially if you use nvm (Node Version Manager).
  7. Use git for repository management and make regular commits, it is like taking notes on the process and lets you revert to a previous state in case you get stuck.
  8. Use Quasar boot files for any pre-mounting app routines.
  9. Finally, become a backer/sponsor and get access to the special Discord support chat room for priority support. This also helps the project survive.

If you get stuck, check out the forums or visit our Discord server for help which comes not just from staff, but from the community as well.

Info

It should be noted that we have tried our hardest to make sure everything in the Upgrade documentation is correct. However, because this has been a manual process, there are likely errors. If you find any, don’t be afraid to make a PR and propose a change to make corrections.

Initial Steps

There are two paths you can follow. They are described below. Choose the path that fits your needs best. We do, however, recommend the first option.

Option 1: Convert a project

Important!

This guide assumes that you are currently using a @quasar/app v2 project. You will upgrade it to Quasar CLI with Webpack for Quasar v2 (the package is now named @quasar/app-webpack to better differentiate it from Quasar CLI with Vite).

Before starting, it is highly suggested to make a copy of your current working project or create a new branch with git.

  1. Ensure you have latest @quasar/cli:
$ yarn global add @quasar/cli@latest
# or: npm i -g @quasar/cli@latest
  1. Stylus related: Are you using Stylus and Quasar Stylus variables? Then before anything, convert all those files to Sass/SCSS (including src/css/app.styl -> src/css/app.sass or app.scss). If you still want to use Stylus in your project (without Quasar Stylus variables), then you’ll also need to install the stylus related packages (which are no longer supplied by “@quasar/app” out of the box):
# only if you still want to use Stylus (but without Quasar Stylus variables)
$ yarn add --dev stylus stylus-loader
  1. Upgrade Node to at least v12.22.1, npm to at least v6.14.12 and yarn to at least v1.17.3.
# if you are already using a lts/erbium version (eg. 12.14.0), take note of its version, it should be listed at "lts/erbium" row
$ nvm list

# if you're using `nvm` helper on Linux (https://github.com/nvm-sh/nvm)
$ nvm install 12.22.1 && nvm alias default lts/erbium && nvm use default
# if you're using `nvm` helper on Windows (https://github.com/coreybutler/nvm-windows)
$ nvm install 12.22.1 && nvm use 12.22.1

# uninstall previous "lts/erbium" version, we suppose 12.14.0 was already installed in our case
nvm uninstall 12.14.0
  1. Remove folders .quasar, node_modules and package-lock.json or yarn.lock file. This generally isn’t needed, but in some cases it will avoid trouble with yarn/npm upgrading the packages for the purpose of this guide.
  2. Uninstall: @quasar/app
$ yarn remove @quasar/app
  1. Install: @quasar/app-webpack v3, quasar v2, vue v3 and vue-router v4 packages (the last two are no longer supplied by @quasar/app):
$ yarn add --dev @quasar/app-webpack@3
$ yarn add quasar@2 vue@3 vue-router@4
  1. Remove .quasar and node_modules folders, and package-lock.json/yarn.lock file, then run npm install/yarn install to regenerate the lock file. This forces the upgrade of the whole dependency graph (deep dependencies included) and avoids troubles with mismatching packages, especially webpack 5 related ones.
  2. If you are using ESLint, then edit /.eslintrc.js:
// old way
parserOptions: {
  parser: 'babel-eslint'
},
extends: [
  'plugin:vue/essential' // or equivalent
]

// NEW way
parserOptions: {
  parser: '@babel/eslint-parser'
},
extends: [
  'plugin:vue/vue3-essential' // or equivalent
]

Also upgrade ESLint deps. Example:

"@babel/eslint-parser": "^7.0.0", // replaces babel-eslint !
"eslint": "^7.14.0",
"eslint-config-standard": "^16.0.2",
"eslint-plugin-import": "^2.19.1",
"eslint-plugin-node": "^11.0.0",
"eslint-plugin-promise": "^5.1.0",
"eslint-plugin-quasar": "^1.0.0",
"eslint-plugin-vue": "^7.0.0",
"eslint-webpack-plugin": "^2.4.0" // replaces eslint-loader !
  1. If you are using Vuex, you will need to manually install it:
$ yarn add vuex@4
# or
$ npm install vuex@4
  1. Edit quasar.config.js > framework > lang. It will be explained in the “Quasar language packs” section on this page.
// old way
framework: {
  lang: 'en-us'
}

// NEW way
framework: {
  lang: 'en-US'
}
  1. Check all your manually installed webpack plugins to be compatible with Webpack 5 (the vast majority should already be compatible). Also update quasar.config.js > devServer config to match webpack-dev-server v4.
  2. Follow the rest of the guide. You’ll need to adapt to the breaking changes of the new versions of Vue 3, Vue Router 4, Vuex 4, Vue-i18n 9 and any other vue plugin that you are using.
  3. Upgrade your other project dependencies (especially ESLint related ones).

Option 2: Create a project

Second option is to create a fresh project and port to it bit by bit. We see this option as a worst case scenario (where you encounter problems with Vue 3 and Vue Router v4 rather than with Quasar itself) and we only mention it for the completeness of this guide.

You can generate a new Quasar v2 project as shown below and then you can port your app to it.

$ yarn create quasar
# pick "App with Quasar CLI" and "Quasar v2"
# decide if you want "Quasar CLI with Vite" (beta) or "Quasar CLI with Webpack"

Webpack v5

In order to support Node 13+ (and for many other benefits) we have upgraded Webpack from v4 to v5. You may need to upgrade your webpack plugins accordingly.

Nodejs polyfills

Webpack v5 removed the Nodejs polyfills for the web client builds. If you are using packages for the web client that rely on Nodejs API (they shouldn’t!), you will get errors saying that some packages are missing. Examples: Buffer, crypto, os, path.

These need to be addressed by the package owners. But if you don’t want to wait and just want to run your app/website (with a bit of risk), then you can manually install node-polyfill-webpack-plugin (yarn add --dev node-polyfill-webpack-plugin) then reference it in quasar.config.js > build > chainWebpack. Example:

// quasar.config.js
build: {
  chainWebpack (chain) {
    const nodePolyfillWebpackPlugin = require('node-polyfill-webpack-plugin')
    chain.plugin('node-polyfill').use(nodePolyfillWebpackPlugin)
  }
}

Webpack devserver

As part of the upgrade to Webpack 5, Quasar CLI now supplies webpack-dev-server v4 and webpack-dev-middleware v4 which come with their own breaking changes. This influences quasar.config.js > devServer options. Below are some of the most used props:

Prop nameTypeDescription
devMiddlewareObjectConfiguration supplied to webpack-dev-middleware v4
httpsBoolean/ObjectSame as before with webpack 4
onBeforeSetupMiddlewareFunctionReplaces “before”
onAfterSetupMiddlewareFunctionReplaces “after”
proxyObject/ArraySame as before with webpack 4

TIP

If you’ve tampered with quasar.config.js > devServer then you might be interested in a list of all the breaking changes proposed by webpack-dev-server v4: release notes. Check if any apply to you.

webpack-chain

WARNING

At the moment of writing these lines, webpack-chain has not been updated to fully support Webpack 5. This has impact over all quasar.config.js > chainWebpack{…} methods. While these methods will still work, the newer parts of the configuration introduced in Webpack 5 are not (yet) available. For those parts, the extendWebpack* methods should be used, until webpack-chain is fully Webpack 5 compatible.

App.vue

You’ll need to edit src/App.vue and remove the wrapper <div id="q-app">. You don’t (and should NOT) need it anymore.

<!-- old way -->
<template>
  <div id="q-app">
    <router-view />
  </div>
</template>

<!-- NEW way -->
<template>
  <router-view />
</template>

Vue 3

Since you will also switch to Vue 3, it’s best that you also take a look at its migration guide after finishing reading this migration guide.

If you’re using .vue files, you’ll most likely have a fairly easy transition because 1) vue-loader (supplied by @quasar/app) is the one parsing the SFC syntax and instructing Vue 3 on what to do and 2) you can still use the Options API (although we recommend that you convert to the newer and better Composition API).

We suggest that you first convert your project to Quasar v2 while maintaining Options API (because your components are already in Options API form and you probably want to ensure everything is working first). After this transition, you can convert all your Vue components to Composition API, but in no way is this a requirement.

Along with Vue3, there is a new major version of Vue Router v4, which has its own breaking changes you should be aware of. There’s also the new Vuex v4 too.

Vue 3 breaking changes examples

One of the most important breaking changes when dealing with Vue 3 is how v-model works. It is now an alias to the model-value + @update:model-value combo, instead of value + @input. This has impact on all Quasar components using v-model. If you’re writing your components in .vue files, then you don’t need to worry about it as vue-loader correctly translates it for you.

Also, if you emit custom events from your Vue components, you will need to explicitly specify them like below:

<script>
// your Vue component;
// let's assume that we emit 'ok' and 'myEvent' events
// from this component

export default {
  // ...
  emits: [ 'ok', 'myEvent' ],
  // ...
}
</script>

Vue Router v4

This is a Vue 3 ecosystem upstream breaking change. Update src/router files to match Vue Router v4’s API. Vue Router v4 comes with its own breaking changes. Especially note below how we are dealing with the 404 error.

// default src/router/index.js content:

import { createRouter, createMemoryHistory, createWebHistory, createWebHashHistory } from 'vue-router'
import routes from './routes'

export default function (/* { store, ssrContext } */) {
  const createHistory = process.env.SERVER
    ? createMemoryHistory
    : process.env.VUE_ROUTER_MODE === 'history' ? createWebHistory : createWebHashHistory

  const Router = createRouter({
    scrollBehavior: () => ({ left: 0, top: 0 }),
    routes,

    // Leave this as is and make changes in quasar.config.js instead!
    // quasar.config.js -> build -> vueRouterMode
    // quasar.config.js -> build -> publicPath
    history: createHistory(process.env.MODE === 'ssr' ? void 0 : process.env.VUE_ROUTER_BASE)
  })

  return Router
}
// default src/router/routes.js content:
const routes = [
  {
    path: '/',
    component: () => import('layouts/MainLayout.vue'),
    children: [
      { path: '', component: () => import('pages/Index.vue') }
    ]
  },

  // Always leave this as last one,
  // but you can also remove it
  {
    path: '/:catchAll(.*)*',
    component: () => import('pages/Error404.vue')
  }
]

export default routes

If you use TypeScript, you must replace the RouteConfig interface occurrences with RouteRecordRaw.

Vuex v4

First step that you need to take is that you need to manually install Vuex into your app.

$ yarn add vuex@4
# or:
$ npm install vuex@4

This is a Vue 3 ecosystem upstream breaking change. You’ll need to update src/store files to match Vuex v4’s API. Notice the “createStore” import from vuex and its usage in an example below. For informative purposes: Vuex migration to 4.0 from 3.x

// default src/store/index.js content:
import { createStore } from 'vuex'
// import example from './module-example'

export default function (/* { ssrContext } */) {
  const Store = createStore({
    modules: {
      // example
    },

    // enable strict mode (adds overhead!)
    // for dev mode and --debug builds only
    strict: process.env.DEBUGGING
  })

  return Store
}

Vue-i18n v9

This is a Vue 3 ecosystem upstream breaking change. Update src/boot/i18n.js file to match Vue-i18n v9’s API. Vue-i18n comes with its own breaking changes.

Since this package isn’t provided by @quasar/app, you must update the dependency in your project via yarn add vue-i18n

// default src/boot/i18n.js content:

import { createI18n } from 'vue-i18n'
import messages from 'src/i18n'
// You'll need to create the src/i18n/index.js/.ts file too

export default ({ app }) => {
  // Create I18n instance
  const i18n = createI18n({
    locale: 'en-US',
    messages
  })

  // Tell app to use the I18n instance
  app.use(i18n)
}

If you use TypeScript, remove the existing augmentation of ‘vue/types/vue’ as it has been integrated into the upstream package.

@vue/composition-api

If you’ve been using Composition API package for Vue 2, you’ll need to change all imports to point towards the Vue package.

// OLD, @vue/composition-api way
import { ref } from '@vue/composition-api'

// New Vue 3 way
import { ref } from 'vue'

If you were using the deprecated context.root object, you must refactor your code to avoid using it, as it’s not available anymore.

Delete src/boot/composition-api boot file and the corresponding entry from quasar.config.js. Then uninstall the @vue/composition-api package:

$ yarn remove @vue/composition-api

If you use TypeScript, prepare to reload VSCode many times, as all upgrades will cause typings cache problems.

Quasar components

Vue 3 and v-model

The v-model is now an alias to the model-value + @update:model-value combo, instead of value + @input. This has impact on all Quasar components using v-model. If you’re writing your components in .vue files then you don’t need to worry about it as vue-loader correctly translates it for you.

Suggestion: you may want to do a search and replace for :value and @input. Please be careful on replacing the :value as some components (QLinearProgress, QCircularProgress) are not tied to v-model and still use value as a property.

Vue 3 and scoped slots

All slots are now acting in the same manner as the scoped slots in Vue 2. If you’re using Options API, then you can do a search and replace for this.$scopedSlots (and replace it with this.$slots).

QDrawer/QDialog/QMenu/QTooltip

Use “class” and “style” attributes instead of “content-class” / “content-style” props for the above mentioned Quasar components.

QBtn/QItem/QBreadcrumbs/QRouteTab

New props: href, target.

For QBtn, it is no longer necessary to specify type="a" when using href prop.

The href prop is especially useful for UMD if you don’t also inject Vue Router.

QBtn/QRouteTab

If you were using the to prop and delaying navigation in your @click handler:

// OLD way
function onClick (e, go) {
  e.navigate = false // <<<--- this changed
  // ...maybe later call go()?
}

// NEW way
function onClick (e, go) {
  e.preventDefault() // <<<--- this changed
  // ...maybe later call go()?
}

QBreadcrumbsEl

Removed “append” prop because Vue Router v4 has also dropped it. Added “tag” and “ripple” properties.

QCarousel

Added “transition-duration” prop.

QColor

Added “no-header-tabs” prop.

QChatMessage

Now by default, the “label”, “name”, “text” and “stamp” are protected from XSS attacks. This means that all of the *-sanitize props have been dropped, as this behavior has now become the standard in Quasar. Should you wish to display HTML as content for these props, you now need to explicitly specify them through new Boolean props (*-html).

Removed Boolean propNew opposite equivalent Boolean prop
label-sanitizelabel-html
name-sanitizename-html
text-sanitizetext-html
stamp-sanitizestamp-html

QDate

When @update:model-value event (equivalent of the old @input) is triggered, the contents of the first parameter no longer contain the (deprecated) changed prop.

QDialog

Added “no-shake”, “transition-duration”. Use “class” and “style” attributes instead of “content-class” / “content-style” props.

QExpansionItem

Removed the “append” property because Vue Router v4 has also dropped it.

(New) Connecting to QForm

Should you wish to create your own Vue components that need to connect to a parent QForm (for validation purposes), we’ve made it easier for you:

// Composition API variant

import { useFormChild } from 'quasar'

useFormChild ({
  validate,     // Function returning a Boolean (or a Promise resolving to a Boolean)
  resetValidation, // Optional function which resets validation
  requiresQForm // Boolean -> if "true" and your component
                //   is not wrapped by QForm it then displays
                //   an error message
})

// some component
export default {
  setup () {
    // required! should return a Boolean
    function validate () {
      console.log('called my-comp.validate()')
      return true
    }

    function resetValidation () {
      // ...
    }

    useFormChild({ validate, resetValidation, requiresQForm: true })
  }
}
// Options API variant

import { QFormChildMixin } from 'quasar'

// some component
export default {
  mixins: [ QFormChildMixin ],

  methods: {
    // required! should return a Boolean
    validate () {
      console.log('called my-comp.validate()')
      return true
    },

    // optional
    resetValidation () {
      // ...
    }
  },

  // ...
}

QInnerLoading

Added “label”, “label-class” and “label-style” props.

QImg

This component has been redesigned from the ground up. It now makes use of a more modern API. The immediate effects are that it uses less RAM memory and runtime is much faster.

Added properties: “loading”, “crossorigin”, “fit”, “no-spinner”, “no-native-menu”, “no-transition”. Removed properties: “transition”, “basic” (now equivalent to “no-spinner” + “no-transition”) Changed property “no-default-spinner” to “no-spinner”.

For the detailed changes, please view the API Card on QImg page.

QPopupEdit

Some performance improvements have been made on this component and as a result you will need to now use the default slot.

<!-- old way -->
<q-popup-edit
  content-class="bg-primary text-white"
  buttons
  color="white"
  v-model="myModel"
>
  <q-input
    type="textarea"
    dark
    color="white"
    v-model="myModel"
    autofocus
  />
</q-popup-edit>

The NEW way is below. Notice v-slot="scope" is applied directly on <q-popup-edit> and using scope.value instead of myModel for the inner <q-input> component:

<q-popup-edit
  class="bg-primary text-white"
  buttons
  color="white"
  v-model="myModel"
  v-slot="scope"
>
  <q-input
    type="textarea"
    dark
    color="white"
    v-model="scope.value"
    autofocus
    @keyup.enter="scope.set"
  />
</q-popup-edit>

For more detailed information on the usage, please read QPopupEdit’s page.

QLayout

The @scroll event parameter now has a slightly different content:

{
  position, // Number (pixels from top)
  direction, // String ("top", "bottom")
  directionChanged, // Boolean
  inflectionPoint, // last position (from the top) when direction changed - Number (pixels)
  delta // difference since last @scroll update - Number (pixels)
}

QOptionGroup

Added “label” and “label-N” slots.

QRouteTab

Added “ripple” property.

QScrollArea

QScrollArea has been redesigned so that it now supports both vertical and horizontal scrolling simultaneously.

  • Added props: “vertical-bar-style” and “horizontal-bar-style” (that come on top of “bar-style” which is applied to both vertical and horizontal scrolling bars)
  • Added props: “vertical-thumb-style” and “horizontal-thumb-style” (that come on top of “thumb-style” which is applied to both vertical and horizontal scrolling bar thumbs)
  • Removed prop: “horizontal” (now obsolete as QScrollArea support both vertical and horizontal scrolling simultaneously)
  • The “getScrollPosition” method now returns an Object of the form { top, left } (example: { top: 5, left: 0 })
  • The “setScrollPosition” and “setScrollPercentage” methods now require a new first param (named “axis” with values either “horizontal” or “vertical”): (axis, offset[, duration])

QScrollObserver

Replaced property “horizontal” with “axis” (String: “vertical”, “horizontal”, “both”; default value: “vertical”).

The @scroll event parameter now has a slightly different content:

{
  position: {
    top, left // Numbers (pixels)
  },
  direction, // String ("top", "right", "bottom" or "left")
  directionChanged, // Boolean
  inflectionPoint: { // last position when direction changed
    top, left // Numbers (pixels)
  },
  delta: { // difference since last @scroll update
    top, left // Numbers (pixels)
  }
}

QSelect

  • The “itemEvents” prop has been dropped from the “option” slot. That information is now contained within the “itemProps”. This change is a logical result Vue 3’s flattening of the rendering function’s second parameter (“on”, “props” etc. merged together into a single Object).
  • New method: “blur()”

QSlider/QRange

New props: track-size, thumb-size, marker-labels, marker-labels-class, switch-label-side, switch-marker-labels-side, inner-min, inner-max, thumb-color, track-color, track-img, inner-track-color, inner-track-img, selection-color, selection-img.

New props specific to QRange: left-thumb-color, right-thumb-color

New slots: marker-label, marker-label-group

QTable

Renamed the “data” property to “rows” (to solve TS conflict issue with “data” incorrectly inferred as the “data()” method of a Vue component).

New prop: “column-sort-order”. New “columns” definition prop (“sortOrder”) and now “style” and “classes” can be Functions too.

Due to the new v-model feature of Vue 3, which replaces the “.sync” modifier, :pagination.sync="..." now need to be used as v-model:pagination="..."

QTable/QTree

Due to the new v-model feature of Vue 3, which replaces the “.sync” modifier, the following properties need to be used differently:

Old wayNew way
pagination.sync=“varName”v-model:pagination=“varName”
selected.sync=“varName”v-model:selected=“varName”
expanded.sync=“varName”v-model:expanded=“varName”

QTabs

Added “active-class” prop.

QTooltip/QMenu/QDialog/QStepper/QTabPanels

Added “transition-duration” property.

QSkeleton

Added “animation-speed” prop.

QUploader

The QUploaderBase component has been removed in favor of the createUploaderComponent util.

Quasar directives

The only breaking change in this section is that we’ve removed the GoBack directive. Use the router reference instead to push/replace/go(-1).

// Composition API variant
import { useRouter } from 'vue-router'

setup () {
  const $router = useRouter()

  // go back by one record, the same as $router.back()
  $router.go(-1)
}
// Options API variant inside your component
this.$router.go(-1)
}

Quasar plugins

AppFullscreen plugin

The request() method now accepts another node while in fullscreen already.

Loading plugin

  • Added “boxClass” property
  • By default, the message is protected from XSS attacks. Should you wish to display HTML content with the “message” prop, you should also specify “html: true”. This behavior is completely opposite to that of Quasar v1, where you had the prop “sanitize” (not available anymore; enabled now by default) to NOT display HTML.

Dialog plugin

A few things changed:

  1. If you are using the Dialog plugin with a custom component, then you must now supply the component properties under “componentProps”:
// OLD, DEPRECATED v1 way
const dialog = this.$q.dialog({ // or Dialog.create({...})
  component: MyVueComponent,
  someProp: someValue,
  // ...
})

// New v2 way (Composition API)
import { useQuasar } from 'quasar'

setup () {
  const $q = useQuasar()
  // ...
  const dialog = $q.dialog({ // or Dialog.create({...})
    component: MyVueComponent,
    componentProps: {
      someProp: someValue,
      // ...
    }
  })
}

// New v2 way (Options API)
const dialog = this.$q.dialog({ // or Dialog.create({...})
  component: MyVueComponent,
  componentProps: {
    someProp: someValue,
    // ...
  }
})
  1. The parent and root props have been removed. Due to the Vue 3 architecture, we can no longer use a “parent” component for the provide/inject functionality. But you’ll still be able to use Vue Router/Vuex/etc. inside of your custom component.
  2. If invoking the Dialog plugin with a custom component then you need to add emits: [ 'ok', 'cancel' ] to your component as Vue 3 now requires an explicit list of events that the component might emit. You can also transform the component to Composition API. For detailed information please see Invoking custom component.
// the invoked component code
export default {
  // ...
  emits: [ 'ok', 'cancel' ],
  // ...
}

Meta plugin

// v1 way (OLD, DEPRECATED)
// some .vue file
export default {
  meta: {
    // ...definition
  }
}

The new way (Composition API or Options API):

// Composition API variant
// for some .vue file
import { useMeta } from 'quasar'

export default {
  setup () {
    // Needs to be called directly under the setup() method!
    useMeta({
      // ...definition
    })
  }
}
// Options API variant
// for some .vue file
import { createMetaMixin } from 'quasar'

export default {
  mixins: [
    createMetaMixin({ /* ...definition */})
    // OR dynamic:
    createMetaMixin(function () {
      // "this" here refers to the vue component
      return {
        /* ...definition... */
      }
    })
  ]
}

For detailed information please see Meta Plugin.

Quasar utils

date utils

The object literal property names provided for methods “addToDate” and “subtractFromDate” have been normalized: #7414.

OldNewChanged?
yearyearsYes
monthmonthsYes
daysdays-
hourshours-
minutesminutes-
secondsseconds-
millisecondsmilliseconds-

exportFile util

The exportFile() util (forces browser to download a file with your specified content) is enhanced with new features: you can specify bom (byte order mark) and/or a text encoding. More info.

scroll utils

Old method nameNEW method name
getScrollPositiongetVerticalScrollPosition
animScrollToanimVerticalScrollTo
setScrollPositionsetVerticalScrollPosition

color utils

Removed “getBrand” and “setBrand” from color utils. They are replaced by “getCssVar” and “setCssVar”:

// OLD, DEPRECATED v1 way:
import { colors } from 'quasar'

const { getBrand, setBrand } = colors
const primaryColor = getBrand('primary')
setBrand('primary', '#f3c')

// NEW v2 way:
import { getCssVar, setCssVar } from 'quasar'

const primaryColor = getCssVar('primary')
setCssVar('primary', '#f3c')

Quasar language packs

We have changed the language pack filenames to reflect the standard naming used by browsers. This will allow you to use $q.lang.getLocale() when you want to dynamically import the Quasar language pack file.

Full list of changes:

Old nameNew name
en-usen-US
en-gben-GB
az-latnaz-Latn
fa-irfa-IR
ko-krko-KR
kur-CKBkur-CKB
nb-nonb-NO
pt-brpt-BR
zh-hanszh-CN
zh-hantzh-TW

If you have configured a default Quasar language pack in your quasar.config.js, then you need to edit it:

// old way
framework: {
  lang: 'en-us'
}

// NEW way
framework: {
  lang: 'en-US'
}

You’ll also need to edit all your dynamic imports from quasar/lang/ to match the new syntax.

Quasar CSS

The color CSS variable names (all the brand related ones) have changed:

// old
--q-color-primary, --q-color-secondary, ...

// new
--q-primary, --q-secondary, ...

Quasar UMD

  • Due to the new Vue 3 architecture, the code for bootstrapping the app has changed and you will need to adapt accordingly.
  • There have been changes to the naming scheme of script and css tags to include the type of distubution. For example, the minified resources filenames now end in .prod.js/.prod.css. This was done to match Vue 3’s own file naming scheme.

TIP

For an in-depth look at the necessary UMD scripts and tags, please use our generator tool.

Quasar App CLI

This section refers to “@quasar/app” v3 package which supports Vue 3 and Quasar UI v2.

  • Dropped support for src/css/quasar.variables.styl. Also, if you still want to use Stylus as preprocessor (but without the Quasar Stylus variables) then you need to manually yarn/npm install stylus and stylus-loader as dev dependencies into your project (“@quasar/app” does not supply them anymore).
  • New quasar.config.js > build > vueLoaderOptions prop
  • Remove quasar.config.js > framework > importStrategy. Auto import works so great that is now used by default and as the only option.
  • The url-loader configuration has been enhanced so it now also supports “ico” files out of the box
  • If you have been using quasar.config.js > build > rtl in the form of an Object, then you must match these options now, since we’ve switched from the unmaintained postcss-rtl to postcss-rtlcss package.

If you have boot files, where you access and change the $q Object through Vue.prototype.$q, then you need to adapt this:

// old way in boot file
Vue.prototype.$q.iconSet.chip.remove = 'fas fa-times-circle'

// NEW way
export default ({ app }) => {
  app.config.globalProperties.$q.iconSet.chip.remove = 'fas fa-times-circle'
}

Nothing changed in regards to how App Extensions work. Please note that not all of our App Extensions are yet compatible with Quasar UI v2. We are working towards releasing new compatible versions of them.

TypeScript

Update src/shims-vue.d.ts to match Vue3 version.

Create a src/quasar.d.ts file and copy into it the content from here.

If you use ESLint, update the property into quasar.config.js:

// old way
supportTS: {
  tsCheckerConfig: { eslint: true },
},

// new way
supportTS: {
  tsCheckerConfig: {
    eslint: {
      enabled: true,
      files: './src/**/*.{ts,tsx,js,jsx,vue}',
    },
  },
},

This is due to upstream breaking changes of fork-ts-checker-webpack-plugin.

Quasar App CLI Electron mode

WARNING

If you have a project using the Quasar Electron mode, then it’s essential to read its own Electron mode upgrade guide.

Out of the box support for TS now available.

You can also enable ESLint for the main thread and the preload script now:

electron: {
  chainWebpackMain (chain) {
    chain.plugin('eslint-webpack-plugin')
      .use(ESLintPlugin, [{ extensions: [ 'js' ] }])
  },

  chainWebpackPreload (chain) {
    chain.plugin('eslint-webpack-plugin')
      .use(ESLintPlugin, [{ extensions: [ 'js' ] }])
  }
}

Quasar App CLI PWA mode

If you are using Workbox in InjectManifest mode, then it’s useful to know that the /src-pwa/custom-service-worker.[js|ts] is now being compiled too. This means that in your code you can now import with relative path too.

Due to the upgrade to Webpack 5, you will need to also upgrade workbox-webpack-plugin to v6+.

You can now enable ESLint for the custom service worker too. And it supports TS out of the box (in which case, rename the extension to .ts).

Enabling ESLint for the custom service worker is done by editing quasar.config.js:

pwa: {
  chainWebpackCustomSW (chain) {
    chain.plugin('eslint-webpack-plugin')
      .use(ESLintPlugin, [{ extensions: [ 'js' ] }])
  }
}

Quasar App CLI SSR mode

If you have a project using the Quasar SSR mode, then it’s essential to read its own SSR mode upgrade guide.

Out of the box support for TS now available.

Quasar Extras

Nothing changed. You can use it as for Quasar UI v1.

Quasar Icon Genie

Nothing changed. You can use it the same way as for “@quasar/app” v1 or v2 projects.