npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

vue-to-quickapp-converter

v1.0.0

Published

A tool to convert Vue Single File Components to QuickApp UX components

Downloads

23

Readme

Vue to QuickApp Converter

将Vue单文件组件(.vue)转换为快应用组件(.ux)的工具。

功能特性

  • 模板转换: 将Vue模板语法转换为快应用模板语法
  • 脚本转换: 将Vue组件选项转换为快应用组件格式
  • 样式转换: 处理CSS语法差异和快应用特有样式
  • 批量转换: 支持单个文件或整个目录的批量转换
  • 可配置: 支持自定义转换规则和选项

安装

npm install

使用方法

命令行工具

# 转换单个文件
npm run convert -- input.vue output.ux

# 转换整个目录
npm run convert -- src/ dist/

# 查看帮助
npm run convert -- --help

转换规则

Template 模板转换

Vue指令转换

| Vue指令 | 快应用指令 | 说明 | |---------|------------|------| | v-if | if="{{condition}}" | 条件渲染 | | v-else-if | elif="{{condition}}" | 条件渲染 | | v-else | else | 条件渲染 | | v-show | show="{{condition}}" | 显示/隐藏 | | v-for | for="{{items}}" | 列表渲染(需要添加tid) | | v-model | value + @change | 双向绑定(特殊处理) | | v-bind: | : | 属性绑定 | | v-on: | @ | 事件绑定 |

HTML标签转换

| HTML标签 | 快应用组件 | 说明 | |----------|------------|------| | <div> | <div> | 容器组件(自动添加flex样式) | | <span> | <span> | 行内容器 | | <p>, <h1>-<h6> | <text> | 文本组件 | | <img> | <image> | 图片组件 | | <button> | <input> | 按钮组件 | | <input> | <input> | 输入组件 | | <textarea> | <textarea> | 多行输入 | | <ul>, <ol> | <list> | 列表组件 | | <li> | <list-item> | 列表项 |

事件转换

| Vue事件 | 快应用事件 | 说明 | |---------|------------|------| | @click | @click | 点击事件 | | @input | @change | 输入变化 | | @change | @change | 值变化 | | @focus | @focus | 获得焦点 | | @blur | @blur | 失去焦点 | | @submit | @submit | 表单提交 |

特殊处理

  • 动态绑定: 移除:style:class等的冒号前缀
  • 文本包裹: 纯文本内容自动用<text>标签包裹
  • v-for循环: 添加tid属性用于性能优化

Script 脚本转换

Vue组件选项转换

| Vue选项 | 快应用格式 | 说明 | |---------|------------|------| | data() | data: {} | 组件数据(函数转对象) | | props | props: {} | 属性定义 | | computed | computed: {} | 计算属性 | | watch | watch: {} | 监听器 | | methods | 平级方法 | 方法直接定义在组件中 | | mounted | onReady() | 组件准备完成 | | created | onInit() | 组件初始化 | | beforeDestroy | onDestroy() | 组件销毁前 |

数据转换示例

// Vue格式
export default {
  data() {
    return {
      count: 0,
      message: 'Hello'
    }
  },
  methods: {
    increment() {
      this.count++
    }
  }
}

// 快应用格式
export default {
  data: {
    count: 0,
    message: 'Hello'
  },

  increment() {
    this.count++
  }
}

Style 样式转换

不支持的CSS属性(自动移除)

/* 以下属性在快应用中不支持,转换时会自动移除 */
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
text-shadow: 1px 1px 1px #000;
transform: translateX(10px);
animation: fadeIn 0.3s ease;
transition: all 0.3s ease;
position: absolute;
z-index: 999;
gap: 10px;
overflow-x: auto;
cursor: pointer;

不支持的伪类选择器(自动移除)

/* 以下伪类选择器会被完全移除 */
.input::placeholder { color: #999; }
.button:hover { background: #blue; }
.link:focus { outline: none; }
.item:first-child { margin-top: 0; }
.element::before { content: ""; }

CSS简写属性转换

/* 转换前 */
.element {
  background: #ffffff;
  border: none;
  border: 1px solid #ccc;
}

/* 转换后 */
.element {
  background-color: #ffffff;
  border-width: 0px;
  border-style: none;
  /* border简写会被移除,建议使用具体属性 */
}

支持的CSS属性

/* 以下属性在快应用中完全支持 */
background-color: #ffffff;
color: #333333;
font-size: 16px;
font-weight: bold;
text-align: center;
line-height: 1.5;
margin: 10px;
padding: 20px;
border-radius: 4px;
width: 100px;
height: 50px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;

自动添加的样式

  • Flex布局: 所有<div>标签自动添加display: flex; flex-direction: column;
  • 布局检测: 如果已有display属性或class包含flex关键词,则不重复添加
  • CSS类生成: 无class的div会自动添加qa-flex-container

快应用特有功能

快应用专有组件

<!-- 快应用提供的特有组件 -->
<list>              <!-- 高性能列表 -->
<list-item>         <!-- 列表项 -->
<swiper>            <!-- 轮播组件 -->
<tabs>              <!-- 标签页 -->
<tab-bar>           <!-- 标签栏 -->
<tab-content>       <!-- 标签内容 -->
<refresh>           <!-- 下拉刷新 -->
<loading>           <!-- 加载指示器 -->
<progress>          <!-- 进度条 -->
<slider>            <!-- 滑块 -->
<switch>            <!-- 开关 -->
<picker>            <!-- 选择器 -->
<canvas>            <!-- 画布 -->
<web>               <!-- 网页视图 -->
<map>               <!-- 地图 -->

快应用专有事件

<!-- 快应用特有的生命周期和交互事件 -->
<div @appear="onAppear">     <!-- 组件出现 -->
<div @disappear="onDisappear"> <!-- 组件消失 -->
<div @swipe="onSwipe">       <!-- 滑动手势 -->

v-for循环优化

<!-- Vue写法 -->
<li v-for="item in items" :key="item.id">
  {{ item.name }}
</li>

<!-- 快应用写法(自动转换) -->
<list-item for="{{items}}" tid="$idx" :key="item.id">
  {{ item.name }}
</list-item>

使用示例

完整转换示例

Vue组件 (input.vue):

<template>
  <div class="container">
    <h1>{{ title }}</h1>
    <div class="form">
      <input v-model="message" placeholder="请输入内容" />
      <button @click="submit" :disabled="!message">
        提交
      </button>
    </div>
    <ul v-if="items.length">
      <li v-for="item in items" :key="item.id">
        {{ item.name }}
      </li>
    </ul>
  </div>
</template>

<script>
export default {
  data() {
    return {
      title: 'Hello QuickApp',
      message: '',
      items: []
    }
  },
  methods: {
    submit() {
      if (this.message) {
        this.items.push({
          id: Date.now(),
          name: this.message
        })
        this.message = ''
      }
    }
  }
}
</script>

<style>
.container {
  padding: 20px;
  background: #f5f5f5;
}

.form {
  margin: 20px 0;
  gap: 10px;
}

button:hover {
  background-color: #007AFF;
}
</style>

转换后的快应用组件 (output.ux):

<template>
  <div class="container" style="display: flex; flex-direction: column;">
    <text>{{ title }}</text>
    <div class="form" style="margin: 20px 0; display: flex; flex-direction: column;">
      <input value="{{message}}" @change="handleInputChange" placeholder="请输入内容" />
      <input @click="submit" disabled="{{!message}}">
        <text>提交</text>
      </input>
    </div>
    <list if="{{items.length}}">
      <list-item for="{{items}}" tid="$idx" :key="item.id">
        <text>{{ item.name }}</text>
      </list-item>
    </list>
  </div>
</template>

<script>
export default {
  data: {
    title: 'Hello QuickApp',
    message: '',
    items: []
  },

  submit() {
    if (this.message) {
      this.items.push({
        id: Date.now(),
        name: this.message
      })
      this.message = ''
    }
  },

  handleInputChange(evt) {
    this.message = evt.value
  }
}
</script>

<style>
.container {
  padding: 20px;
  background-color: #f5f5f5;
}

.form {
  margin: 20px 0;
}

/* 自动生成的flex布局样式 */
.qa-flex-container {
  display: flex;
  flex-direction: column;
}
</style>

项目结构

vue-ux/
├── src/                          # 源代码目录
│   ├── converters/               # 转换器模块
│   │   ├── template-converter.js # 模板转换器
│   │   ├── script-converter.js   # 脚本转换器
│   │   └── style-converter.js    # 样式转换器
│   ├── utils/                    # 工具模块
│   │   ├── acorn-parser.js       # Acorn AST解析器
│   │   ├── ast-parser.js         # 兜底AST解析器
│   │   ├── conversion-rules.js   # 转换规则配置
│   │   ├── parser.js             # Vue SFC解析器
│   │   ├── safe-parser.js        # 安全解析器
│   │   └── template-ast.js       # 模板AST工具
│   ├── converter.js              # 主转换器
│   └── index.js                  # 入口文件
├── bin/                          # 命令行工具
│   └── cli.js                    # CLI入口
├── examples/                     # 示例文件
│   ├── vue/                      # Vue组件示例
│   │   ├── Example.vue
│   │   ├── HelloWorld.vue
│   │   └── SimpleButton.vue
│   └── quickapp/                 # 转换后的快应用组件
│       ├── Example.ux
│       ├── HelloWorld.ux
│       └── SimpleButton.ux
├── tests/                        # 测试文件
│   ├── ast-parser.test.js        # AST解析器测试
│   ├── converter.test.js         # 转换器测试
│   ├── safe-parser.test.js       # 安全解析器测试
│   └── setup.js                  # 测试配置
├── jest.config.js                # Jest测试配置
├── package.json                  # 项目配置
├── package-lock.json             # 依赖锁定文件
└── README.md                     # 项目说明

核心模块说明

转换器模块 (src/converters/)

  • template-converter.js: 处理Vue模板到快应用模板的转换

    • Vue指令转换 (v-ifif)
    • HTML标签转换 (<p><text>)
    • 动态绑定处理 (:stylestyle)
    • 文本自动包裹 (<text>)
    • Flex布局自动添加
  • script-converter.js: 处理Vue脚本到快应用脚本的转换

    • data() 函数转换为 data 对象
    • methods 转换为平级方法
    • 生命周期钩子转换
    • v-model处理函数生成
  • style-converter.js: 处理CSS样式转换

    • 移除不支持的CSS属性
    • 移除不支持的伪类选择器
    • 简写属性转换 (backgroundbackground-color)
    • 警告信息收集

解析器模块 (src/utils/)

  • acorn-parser.js: 基于Acorn的AST解析器

    • 安全的JavaScript代码解析
    • 支持完整的ES2020语法
    • 多层回退机制
  • ast-parser.js: 自定义AST解析器

    • 轻量级JavaScript解析
    • 基本语法支持
    • 作为Acorn的备用方案
  • safe-parser.js: 安全字符串解析器

    • 正则表达式解析
    • 最后的回退方案
    • 基础数据类型支持
  • conversion-rules.js: 转换规则配置

    • 标签映射规则
    • 事件映射规则
    • 不支持属性列表
    • 样式转换规则
  • parser.js: Vue单文件组件解析器

    • 解析Vue SFC结构
    • 提取template、script、style
    • 生成快应用UX文件

主要功能特性

  1. 多层解析策略: Acorn → 自定义AST → 安全解析器
  2. 智能样式处理: 自动移除不支持属性,转换简写属性
  3. 完整的Vue语法支持: 指令、事件、双向绑定、生命周期
  4. 快应用优化: 自动添加flex布局,文本包裹,性能优化
  5. 详细的警告信息: 帮助开发者了解转换过程中的变化

注意事项

快应用限制

  1. CSS限制

    • 不支持::placeholder:hover等伪类选择器
    • 不支持background简写,需使用background-color
    • 不支持border简写,需使用border-widthborder-styleborder-color
    • 不支持gapcursoroverflow-x等属性
  2. JavaScript限制

    • 不支持v-model双向绑定,需手动处理value@change
    • 动态样式绑定不能使用冒号前缀(:stylestyle
    • 所有文本内容必须用<text>标签包裹
  3. 组件限制

    • <button>标签会转换为<input>组件
    • <p><h1>-<h6>标签会转换为<text>组件
    • <ul><ol><li>会转换为<list><list-item>

最佳实践

  1. 样式编写

    /* ✅ 推荐写法 */
    .button {
      background-color: #007AFF;
      border-width: 1px;
      border-style: solid;
      border-color: #007AFF;
    }
    
    /* ❌ 避免使用 */
    .button {
      background: #007AFF;
      border: 1px solid #007AFF;
    }
  2. 模板编写

    <!-- ✅ 推荐写法 -->
    <div class="container">
      <text>标题文本</text>
      <input value="{{inputValue}}" @change="handleChange" />
    </div>
    
    <!-- ❌ 避免使用 -->
    <div :style="dynamicStyle">
      标题文本
      <input v-model="inputValue" />
    </div>
  3. 脚本编写

    // ✅ 推荐写法
    export default {
      data: {
        count: 0
      },
    
      increment() {
        this.count++
      }
    }
    
    // ❌ 避免使用
    export default {
      data() {
        return { count: 0 }
      },
      methods: {
        increment() {
          this.count++
        }
      }
    }

开发

# 开发模式
npm run dev

# 运行测试
npm test

# 构建
npm run build