为什么捐赠
API 浏览器
应用扩展安装 API

此页面指的是 src/install.js 文件,该文件仅在安装应用扩展时执行。并非所有应用扩展都需要安装 - 这是一个可选步骤。

文件基本结构示例

// can be async
export default function (api) {
  // props and methods for "api" Object
  // are described below
}

api.engine

包含正在使用的 Quasar CLI 引擎(作为字符串)。示例:@quasar/app-vite@quasar/app-webpack

api.hasVite

布尔值 - 是否在 @quasar/app-vite 上运行。

api.hasWebpack

布尔值 - 是否在 @quasar/app-webpack 上运行。

api.extId

包含此应用扩展的 ext-id(字符串)。

api.prompts

是一个对象,它包含此应用扩展安装时提示的答案。有关提示的更多信息,请查看 提示 API

api.resolve

解析正在运行此应用扩展的应用程序中的路径。无需导入 path 并自行解析路径。

// resolves to root of app
api.resolve.app('src/my-file.js')

// resolves to root/src of app
api.resolve.src('my-file.js')

// resolves to root/public of app
// (@quasar/app-webpack v3.4+ or @quasar/app-vite v1+)
api.resolve.public('my-image.png')

// resolves to root/src-pwa of app
api.resolve.pwa('some-file.js')

// resolves to root/src-ssr of app
api.resolve.ssr('some-file.js')

// resolves to root/src-cordova of app
api.resolve.cordova('config.xml')

// resolves to root/src-electron of app
api.resolve.electron('some-file.js')

// resolves to root/src-bex of app
api.resolve.bex('some-file.js')

api.appDir

包含正在运行此应用扩展的应用程序根目录的完整路径(字符串)。

api.hasTypescript
@quasar/app-vite 1.6+
@quasar/app-webpack 3.11+

/**
 * @return {Promise<boolean>} host project has Typescript active or not
 */
await api.hasTypescript()

api.hasLint
@quasar/app-vite 1.6+
@quasar/app-webpack 3.11+

/**
 * @return {Promise<boolean>} host project has ESLint or not
 */
await api.hasLint()

api.getStorePackageName
@quasar/app-vite 1.6+
@quasar/app-webpack 3.11+

/**
 * @return {Promise<string|undefined>} 'pinia' | 'vuex' | undefined
 */
await api.getStorePackageName()

api.getNodePackagerName
@quasar/app-vite 1.6+
@quasar/app-webpack 3.11+

/**
 * @return {Promise<'npm' | 'yarn' | 'pnpm' | 'bun'>}
 */
await api.getNodePackagerName()

api.compatibleWith

确保应用扩展与通过 semver 条件安装在宿主应用程序中的包兼容。

如果 semver 条件不满足,则 Quasar CLI 会报错并停止执行。

semver 条件示例:'1.x || >=2.5.0 || 5.0.0 - 7.2.3'

/**
 * @param {string} packageName
 * @param {string} semverCondition
 */
api.compatibleWith(packageName, '1.x')
更复杂的例子

if (api.hasVite === true) {
  api.compatibleWith('@quasar/app-vite', '^2.0.0-beta.1')
}
else {
  api.compatbileWith('@quasar/app-webpack', '^4.0.0-beta.1')
}

api.hasPackage

通过 semver 条件确定某个包是否安装在宿主应用程序中。

semver 条件示例:'1.x || >=2.5.0 || 5.0.0 - 7.2.3'

/**
 * @param {string} packageName
 * @param {string} (optional) semverCondition
 * @return {boolean} package is installed and meets optional semver condition
 */
if (api.hasPackage('vuelidate')) {
  // hey, this app has it (any version of it)
}
if (api.hasPackage('quasar', '^2.0.0')) {
  // hey, this app has Quasar UI v2 installed
}

api.hasExtension

检查另一个应用程序扩展是否已 npm 安装并由 Quasar CLI 调用。

/**
 * Check if another app extension is installed
 *
 * @param {string} extId
 * @return {boolean} has the extension installed & invoked
 */
if (api.hasExtension(extId)) {
  // hey, we have it
}

api.getPackageVersion

获取宿主应用程序包的版本。

/**
 * @param {string} packageName
 * @return {string|undefined} version of app's package
 */
console.log( api.getPackageVersion(packageName) )
// output examples:
//   1.1.3
//   undefined (when package not found)

api.extendPackageJson

辅助方法,用于使用新属性扩展 package.json。如果指定现有属性,则 **将覆盖** 它们。

/**
 * @param {object|string} extPkg - Object to extend with or relative path to a JSON file
 */
api.extendPackageJson({
  scripts: {
    'electron': 'quasar dev -m electron'
  }
})

上面的示例将 npm 脚本添加到应用程序的 package.json 中,这样您就可以执行 yarn electron(或等效的 npm run electron)。

api.extendJsonFile

使用新属性扩展 JSON 文件(深度合并)。如果指定现有属性,则会覆盖它们。

/**
 * @param {string} file (relative path to app root folder)
 * @param {object} newData (Object to merge in)
 */
api.extendJsonFile('src/some.json', {
  newProp: 'some-value'
})

api.render

渲染(复制)来自您的应用扩展模板(您指定的任何文件夹)到应用程序根目录的文件夹。保持与模板文件夹相同的文件夹结构。

如果应用程序中已存在一些文件,则会询问用户是否应覆盖它们。

需要调用 render() 的文件的相对路径。

/**
 * Render a folder from extension templates into devland
 * Needs a path (to a folder) relative to the path of the file where render() is called
 *
 * @param {string} templatePath (relative path to folder to render in app)
 * @param {object} scope (optional; rendering scope variables)
 */
api.render('./path/to/a/template/folder')

文件名边缘情况

如果您要渲染一个以点开头的模板文件(即 .env),您将必须遵循特定的命名约定,因为点文件在将您的插件发布到 npm 时会被忽略

# templates containing dotfiles must use an
# underscore instead of the dot in their names:

some-folder/_env

# When calling api.render('./some-folder'), this will be
# rendered in the project folder as:

/.env

如果您要渲染一个文件名实际上以下划线开头的文件,则文件名必须以 __(两个下划线字符而不是只有一个)开头

some-folder/__my.css

# When calling api.render('./template'), this will be
# rendered in the project folder as:

/_my.css

使用范围

您还可以通过与 lodash/template 语法进行插值,将一些决策代码注入要渲染的文件中。

例子

src/install.js

// (my-folder is located in same folder as
// the file in which following call takes place)
api.render('./my-folder', {
  prompts: api.prompts
})

假设我们也使用一个 提示 API 文件。它会询问用户是否想要“功能 X”并将答案存储在一个名为“featureX”的变量中。

我们可以在渲染它们的过程中,对渲染的文件的外观进行一些决定。这样就无需创建两个文件夹,并根据一些决定来决定渲染哪一个。

src/my-folder/some-file.js

<% if (prompts.featureX) { %>
const message = 'This is content when "Feature X" exists'
<% } else { %>
const message = 'This is content when we don\'t have "Feature X"'
<% } %>

可能性仅受您的想象力限制。

api.renderFile

与 api.render() 类似,区别在于此方法渲染单个文件。

/**
 * Render a file from extension template into devland
 * Needs a path (to a file) relative to the path of the file where renderFile() is called
 *
 * @param {string} relativeSourcePath (file path relative to the folder from which the install script is called)
 * @param {string} relativeTargetPath (file path relative to the root of the app -- including filename!)
 * @param {object} scope (optional; rendering scope variables)
 */
api.renderFile('./path/to/a/template/filename', 'path/relative/to/app/root/filename', {
  prompts: api.prompts
})

api.renderFile('./my-file.json', 'src/my-file.json')

api.getPersistentConf

获取此扩展的内部持久配置。如果没有,则返回空对象。

/**
 * @return {object} cfg
 */
api.getPersistentConf()

api.setPersistentConf

设置此扩展的内部持久配置。如果它已经存在,它将被覆盖。

/**
 * @param {object} cfg
 */
api.setPersistentConf({
  // ....
})

api.mergePersistentConf

深度合并到此扩展的内部持久配置中。如果扩展没有设置任何配置,这本质上等同于首次设置它。

/**
 * @param {object} cfg
 */
api.mergePersistentConf({
  // ....
})

api.onExitLog

添加一条消息,以便在 App CLI 完成安装应用扩展并即将退出后打印。可以多次调用以注册多个退出日志。

/**
 * @param {string} msg
 */
api.onExitLog('Thanks for installing my awesome extension')