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 🙏

© 2024 – Pkg Stats / Ryan Hefner

weact-cli

v0.6.3

Published

用JSX快速开发小程序

Downloads

94

Readme

weact 用JSX快速开发小程序

travis-ci Code coverage Dependence License

weact实现了用JSX和ES6/7来开发小程序,你可以在一个jsx文件中编写页面或组件,并把关联的JSX代码和引用包编译成小程序代码,然后在小程序开发者工具中调试代码。因为使用了JSX和ES标准语法,你可以轻松地把已有的JSX代码重构成小程序,当然你也可以使用喜欢的语法高亮,语法检查器等工具。

最新版本Version支持

  • JSX,ES6/7标准语法
  • 单文件开发小程序模块
  • 引用NPM包
  • async/await
  • Promise化微信小程序/小游戏API
  • 导入CSS/Sass/Less样式文件

下个小版本将支持

  • 用React方式开发小程序组件

安装包*./node_modules/weact-cli/examples/* 有使用weact的例子,也可以从https://github.com/haojy/weact-startup获取例子。

快速上手

教程

安装


在项目里安装weact-cli,

npm install -D weact-cli
npx weact

JSX小程序


让我们开始写一个Hello world的小程序,只需要两个文件:app.jsx,index.jsx, 通常页面代码会被放在./pages目录下,

src/
├── app.jsx
└── pages
    └── index.jsx

weact只把app.jsx作为目标文件,也就是说所有需要的页面需要在app.jsx中被import进来。在这个例子中,只有一个页面index可以import。我们还需要继承weact.App来声明小程序的app, 这里只export一个空的类, App.jsx 会详细说明怎么定义app,

// src/app.jsx
import { App } from 'weact'
import './pages/index.jsx' // app应用的页面,需要import

export default class extends App {
}

和app一样,所有页面要继承weact.Page,并被export才可以。与应用不同的是,页面有render()方法来定义显示部分,在render方法里返回JSX标签,在语法上这和React Component的render相同。weact会根据render方法里返回的标签,自动编译出WXML文件, 从JSX到WXML 会说明如何用JSX写出符合WXML定义的标签。weact.WXSS利用ES6字符串模版的能力,可以在jsx中声明符合WXSS语法的样式,这样样式就会被weact编译成对应的WXSS文件。

// src/pages/index.jsx
import { Page, WXSS } from 'weact'

WXSS`
.hi {
  color: blue;
}
`
export default class extends Page {
  render() {
    return (
      <view class="hi">
        Hello World!
      </view>
    )
  }
}

这样,一个基于JSX的小程序就完成了。

实战JSX开发小程序 中有更多的例子可以参考。

生成小程序


上面的代码都存放在./src目录下,然后执行

npx weact ./src # 等同于 weact ./src/app.jsx ./dist

在当前目录下会生成./dist目录,里面全是根据jsx文件编译出的小程序代码,

dist/
├── app.js
├── app.json
└── pages
    └── index
        ├── index.js
        ├── index.wxml
        └── index.wxss

微信开发者工具添加项目,项目目录设置成./dist, 然后就可以在模拟器中看到运行结果了。

从JSX到WXML


weact可以在语法上把JSX编译成WXML,下面列表给出两种语言的在语法上的对应关系。

语法 | JSX | WXML ----|-----|----- 数据绑定 | <view>{message}</view> | <view> {{ message }} </view> 属性 | <view id={`${prefix}-item}`>hi</view> | <view id="{{prefix}}-item">hi</view> 关键字 false | <view checked={false}>hi</view> | <view checked="{{false}}">hi</view> 关键字 | <view checked>hi</view> | <view checked="{{true}}">hi</view> 三元运算 | <view hidden={flag ? true: false}>hi</view> | <view hidden="{{flag ? true : false}}">hi</view> 算数运算 | <view>{a + b} + {c} + d</view> | <view>{{a + b}} + {{c}} + d</view> 逻辑判断 | <view if={length > 5}>hi</view> | <view wx:if="{{length > 5}}">hi</view> 字符串运算 | <view>{"hello " + name}</view> | <view>{{"hello " + name}}</view> 数组 | <view for={[zero, 1, 2, 3, 4]}>  {item}</view> | <view wx:for="{{[zero, 1, 2, 3, 4]}}">  {{item}} </view> 对象 | <view data={{ foo: 0, bar: 1 }}>hi</view> | <view data="{{ foo: 0, bar: 1 }}">hi</view> 数据访问 | <view>{object.key} {array[0]}</view> | <view>{{object.key}} {{array[0]}}</view> for 循环 | <view for={array} key="message">  {index}:{item.message}</view> | <view wx:for="{{array}}" wx:key="message">  {{index}}:{{item.message}}</view> if 条件 | <view if={condition}>hi</view> | <view wx:if="{{condition}}">hi</view> if else | <view if={x > 5}>1</view><view elif={x > 2}>2</view><view else>3</view> | <view wx:if="{{x > 5}}">1</view><view wx:elif="{{x > 2}}">2</view><view wx:else>3</view> block 条件 | <block if={true}>  <view> 1 </view> </block> | <block wx:if="{{true}}">  <view> 1 </view> </block> block 循环 | <block for={[1, 2, 3]}>  <view>{index}:{item}</view></block> | <block wx:for="{{[1, 2, 3]}}">  <view>{{index}}:{{item}}</view></block> 事件处理 | <button bindtap={handleTap}>Next</button>| <button bindtap="handleTap">Next</button> onXXX == bindxxx | <button onTap={this.handleTap}>Next</button> | <button bindtap="handleTap">Next</button>

App.jsx


小程序在json文件中进行全局配置,用JSX把这些配置写成App的类属性,对比参考 小程序配置 。同样,App的 生命周期函数,自定义公共变量,自定义公共函数等属性 都可以写成类属性。weact把app.jsx编译成对应的app.json,app.js, app.wxss。

export default class extends App {

  debug = true

  window = {
    navigationBarTitleText: '你好,小程序',
    navigationBarTextStyle: 'black',
    navigationBarBackgroundColor: '#f4f5f6',
    backgroundColor: '#f4f5f6',
  }

  tabBar = {
    color: '#333333',
    backgroundColor: '#ffffff',
    list: [
      {
        pagePath: 'pages/index/index', // 编译后js路径
        text: '🏠',
      },
      {
        pagePath: 'pages/page1/page1',
        text: 'Page 1',
      },
    ],
  }

  myData = '自定义公共变量',

  hello() { return '自定义公共函数' }

  // 生命周期函数
  onLaunch() { console.log('app: hello world') }
  onShow() { console.log('app: yes, I am') }
  onHide() { console.log('app: just minutes') }
  onError() { console.log('app: woops') }
}

Page.jsx


类似App.jsx,页面的 生命周期函数和其他属性 也写成Page的类属性。除此之外,

  • Page的render()函数定义页面显示,
  • 标签使用参考小程序基础组件
  • 组件的事件处理函数在Page中直接定义类函数
export default class extends Page {

  data = {
    // 页面数据
  }

  myData = '自定义公共变量',

  handleTap() { console.log('自定义公共函数') }

  // 生命周期函数
  onLoad() { console.log('page index: loading...') }
  onShow() { console.log('page index: yes, I am') }
  onReady() { console.log('page index: I am ready now') }
  onHide() { console.log('page index: just minutes') }
  onUnload() { console.log('page index: bye...') }
  onReachBottom() { console.log('page index: we get to the most bottom') }
  onPullDownRefresh() { console.log('page index: pull down') }
  onPageScroll() { console.log('page index: scrolling...') }
  onShareAppMessage() { console.log('page index: share this') }

  render() {
    return (
      <view>
        Hello World!
        <button onTap={this.handleTap}>下一页</button>
        <navigator url="/pages/page1/page1">跳转到Page 1</navigator>
        <navigator url="/pages/page2/page2">跳转到Page 2</navigator>
      </view>
    )
  }
}

导入样式

weact支持在JSX文件中直接引用CSS/SASS/SCSS/LESS文件,所有引用的文件会被编译成单个样式文件app.wxss。根据具体使用的样式文件类型,安装对应的编译器

样式类型 | 安装包 ----------|------------- css | 内置,无需安装 sass/scss |yarn add node-sass --dev less | yarn add less --dev stylus | yarn add stylus --dev

比如,

import './index.css'
import './page1.scss'du y
import './page2.less'

支持在单个文件中引用多个不同样式文件,只要安装好对应的编译器。

模版==函数式Component


小程序的模版可以理解成,没有状态的函数式Component。weact会把返回JSX标签的函数编译成模版,使用这类组件时,只要确保import的名字和定义的一样就可以。

// src/components/flex.jsx
export default function flex({
  direction,
}) {
  return (
    <view>
      <view class="section">
        <view>flex-direction: ${direction}</view>
        <view style={`display:flex;flex-direction:${direction};`}>
          <view class="flex-item bc_green">1</view>
          <view class="flex-item bc_red">2</view>
          <view class="flex-item bc_blue">3</view>
        </view>
      </view>
    </view>
  )
}

// src/pages/index.jsx
import { Page } from 'weact'
import flex from '../components/flex.jsx'


export default class extends Page {
  render() {
    return (
      <view>
        <flex direction="row" />
        <flex direction="column" />
      </view>
    )
  }
}

组件


用weact自定组件更类似写react Component,像Page一样显示声明继承Compnent类就可以。组件的属性可以用propTypesdefaultProps来定义,分别对应着properties[...].typeproperties[...].value。属性类型由weact.PropTypes定义如下

PropTypes | 小程序属性类型 ----------|------------- string | String number | Number bool | Boolean object | Object array | Array

在下面的例子里ab就是组件属性。如果你了解react,你会比较熟悉这种定义Component的方式。 另外,自定义的方法和事件响应函数可以直接定义为类属性,weact在编译时把这些函数放在methods属性里。

import { Component, PropTypes } from 'weact'
export default class extends Component {
  static propTypes = {
    a: PropTypes.string
    b: PropTypes.bool
  }
  static defaultProps = {
    a: 'world',
    b: true,
  }
  state = {
    open: true,
    x: 'hi',
    item: {
      index: 0,
      time: '2016-09-15'
    }
  }

  render() {
    const { a, b } = this.props
    const { open } = this.state
    return (
      <view>
        <view x={b} y="str">hi {a} </view>
        <view for={[1, 2, 3]} > </view>
        <view for={array} for-index="i" for-item="node"> </view>
      </view>
    )
  }
}

组件关系

weact会根据父子组件的引用关系,自动编译出relations的定义。来看看下面的例子,父组件parent引用了子组件child。

// ./parent.jsx
import { Component, PropTypes } from 'weact'
import child from './child.jsx'
export default class extends Component {
  render() {
    return (
      <view>
        父级组件
        <child />
      </view>
    )
  }
}
// ./child.jsx
import { Component, PropTypes } from 'weact'
export default class extends Component {
  render() {
    return (
      <view>
        子级组件
      </view>
    )

  }
}

weact编译后在各自的js文件里自动生成关系定义,而不用手动定义。

// ./parent.js
  relations: {
    "../child/child": {
      type: "child"
    }
  },
// ./child.js
  relations: {
    "../parent/parent": {
      type: "parent"
    }
  },

React组件

TODO

引用模块


虽然小程序暂不支持直接引入NPM包,但支持类CommonJS的模块引用。weact在语法上实现ES模块间引用, 用babel-plugin-transform-modules-commonjs解析成CommonJS的包;NPM包也会被拷贝到modules目录下。weact模块并没有代码存在,暂时只为了符合语法。

import方式 | JS/JSX | 小程序 ----------|--------|------- 模块间 | import reducer from './reducer' | var _reducer = require("./reducer.js"); NPM包 | import redux from 'redux' | var _redux = require("modules/redux.js"); 引用Page | import './pages/index.jsx' | app.json {"pages":["pages/index/index"]} 引用Component | import Component from '../components/Component.jsx' | *.json: {"usingComponents":{"Component":"../../components/Component/Component"}} 引用Template | import MsgItem from './MsgItem.jsx' | wxml <import src="../MsgItem.wxml" />

引用的NPM包需用npm或yarn安装

Promise和async/await


weact支持Promise的相关语法,也支持async/await。你可以在App和Page的类方法上使用async来定义异步函数,然后就可以在这函数内使用await来处理异步或Promise函数。为了方便用await方式调用微信小程序API的异步函数,weact内置的模块Promise化了这些接口,具体使用方法参考 Promise化微信小程序/小游戏API

// in page.jsx
import { wx } from 'weact'  // 引用Promise化的wx接口
export default class extends Page {
  async onLoad() {
    const wait = () => new Promise((resolve, reject) => {
      setTimeout(function() {
        resolve('小程序')
      }, 1000)
    })
    const who = await wait() // 调用自定异步函数
    console.info(who)
    const systemInfo = await wx.getSystemInfo() // 调用Promise化的wx接口
    console.info(systemInfo)
  }
}

async/await最终执行依赖于目标设备的支持

Promise化微信小程序/小游戏API


weact内置了Promise化的微信小程序和小游戏的API, 编译后会引入weact.js。Promise化的规则

  • 接口含参数successfail的API被Promise化,其他参数不变
  • success对应Promise.resolvefail对应Promise.reject
  • 参数complete暂不支持
  • 保留已有同步接口(Sync结尾的函数)和监听接口(以on/off开头的函数)
import { Page, wx } from 'weact'

export default class extends Page {
  state = {
    storage: 'nothing',
  }
  onLoad() {
    // 原接口 wx.getStorage({ key, success, fail, complete })
    wx.getStorage({ key: 'store' }) 
    .then(rs => {
      this.setState({ storage: rs})
    }, err => {
      this.setState({ storage: err.errMsg})
    })
  }
  render () {
    ...
  }

详细API的使用参考

命令行用法


使用: weact [options]

  • source 源码目录路径或app.jsx文件路径
  • target 代码生成路径=./dist

options:

  • -v, --version 显示版本
  • -h, --help 显示当前内容
  • -w, --watch Watch源码变化,自动更新代码

例子:

  • 在当前路径./dist目录下生成代码

weact examples/01.hello.world/

  • 指定代码生成路径

weact examples/01.hello.world/ ./your_distribution

  • watch模式, 根据源码改动,自动更新生成代码

weact -w examples/01.hello.world/