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

mpwjs

v1.0.0

Published

微信小程序增强型框架

Downloads

5

Readme

简介

对小程序原生框架进行扩展,提供新的特性以及一些通用功能。

使用方法:

  1. 包装原生 App、Component 对象:
import { wrap } from 'mpwjs'

const wApp = wrap(App) // App工厂
const wComponent = wrap(Component) // 组件工厂
const wView = wrap(Component) // 页面工厂

// 全局扩展
wApp.mixin({ ... })
wComponent.mixin({ ... })
wView.mixin({ ... })
  1. 使用 wApp 创建应用:
wApp()
  1. 使用 wComponent/wView 创建组件或者页面:
wView({
    name: 'User',
    props: {
        id: {
            type: String,
        },
    },
    data: {
        name: '',
        age: '',
    },
})

ps: 上述 Demo 没有使用wView = wrap(Page)是因为 Page 早期(<2.9.2)无法使用Behavior,而且在组件化编程体验上面跟Component不一致,所以统一使用Component

自定义选项

在支持原生对象所有配置的基础上,增加了自定义选项:

| 配置项 | 说明 | 备注 | | --------------------------------------------- | --------------- | ------------------------------------------------ | | name: string | 组件名称 | 利于调试 | | props: object | 组件属性定义 | 用法跟 Vue 的 props 一致,可以代替原properties | | mixins: Array<options> | 混入 | 支持嵌套,如minxins: [{ mixins: [...]}] | | store: Store | 全局状态对象 | 详情见全局状态管理 | | use: {[local:string]:string} | 引入 store 状态 | | | computed:{[key:string]:(data) => any} | 计算属性 | 文档 | | watch: {[objPath:string]:(...vals) => void} | 数据观测 | 文档 | | cache: string[] \| object[] | 路由级数据缓存 | 利用Storage实现 | | globalCache: string[] \| object[] | 全局数据缓存 | 利用Storage实现 |

mixins 说明

支持小程序原生 options 以及自定义 options,如果使用如下 mixins:

const B = {
    mixins: [D],
}

const C = {
    mixins: [E],
}

// A
{
    mixins: [B, C],
}

那么混入顺序为:D->B->E->C->A

use 说明

use 声明是为了将 store 状态引入到本地。基本格式为:

{
    use: {
        localName: 'storeName'
    }
}

比如use: { myUser: "user" },那么本地就可以使用this.data.myUser访问 store 中的 user。

局部引用

storeName 支持 object-path,从而可以实现局部 store 状态引入:

{
    // 只使用用户头像
    use: {
        avatar: 'user.avatar'
    }
}

通配符

引用 store 状态时,请牢记一个规则:父级状态发生改变时,会通知子级;但是子级状态发生改变时,不会通知父级。

比如在页面上引用用户信息use: { user: "user" },那么当$store.setData({ user: newUser})时,页面上引用的 user 会响应式更新。如果是$store.setData({{ "user.avatar": "xx.png" })(只修改用户头像),页面上的 user 不会更新。

如果我们想引用多个 user 的子状态,但是又不想挨个去声明,那么我们可以使用通配符user: { user: "user.**" }user.**表示我们既引用 user 状态,同时也监听其下所有子状态的更改。

cache 配置说明

{
    cache: {
        [key: string]: {
            value?: any, // 默认值
            expire?: number, // 过期时间(毫秒)
            user?: boolean, // 是否区分登录用户
            query?: boolean, // 是否区分查询字符串
        }
    }
}

或者简单罗列 key:

{
    cache: Array<string>
}

globalCache 配置与 cache 一致。两者不同地方在于缓存命名空间不同,globalCache 存放于data:xxx,而 cache 存放于data:path/to/some/page/xxx

cache 配置后,即可作为普通 data 数据来使用,框架本身会负责及时更新 Storage。另外如果 globalCache 与 cache 中有重名配置,优先使用 cache。

全局状态管理

全局状态管理是一个常见需求,因此 mpwjs 提供了一套简单易行的方案。

创建 Store

import { createStore } from 'mpwjs'

const store = createStore({
    // 自定义状态
    data: {
        // 用户会话信息
        user: {
            // 用户头像
            avatar: '',
            // 权限
            access: {},
        },
    },
})

// 全局混入,之后凡事通过wView创建的组件都可通过use选项来引入该store的状态
wView.mixin({
    store,
})

修改 Store

store 提供了 setData 方法(类似原生 setData 方法,支持 object-path)。比如:

store.setData({
    // 修改用户头像
    'user.avatar': 'xx.png',
})

组件内部可以使用$store.setData。比如:

wView({
    use: {
        user: 'user',
    },
    methods: {
        onClick() {
            // 修改用户头像
            this.$store.setData({
                'user.avatar': 'xx.png',
            })
        },
    },
})

切记只有通过 store.setData 才是全局有效的。

监听 Store

支持通过store.watch监听状态改变(类似小程序的 observer),比如:

// 当user以及其下子状态发生改变时,都会触发watcher
this.$store.watch('user.**', (user) => {
    // ...
})

不过 $store.watch 是一个偏底层的 api,一般只在框架层面使用。平时书写 View 页面时,直接使用 watch 选项即可:

wView({
    use: {
        user: 'user',
    },
    // 既支持本地data,也支持storeData
    watch: {
        user: function () {
            // ...
        },
    },
})

自定义生命周期

| 事件名 | 说明 | 备注 | | -------------- | ---------------------- | -------------------------------------------------- | | beforeLaunch | 在 appLaunch 之前发生 | 以异步队列运行,且会拦截 launch 事件 | | beforeEnter | 在组件 attach 之前发生 | 以异步队列运行,且会拦截 attached、load、show 事件 | | beforeShow | 在组件 show 之前发生 | 以异步队列运行,且会拦截 show 事件 |

页面间通信

微信小程序通过getCurrentPages()可以获取到当前的页面栈,如果这些页面之间希望通信的话,则可以使用全局混入的$tab 对象,比如:

// 监听其它页面的消息
this.$tab.addMessageListener(({ message, origin }) => {
    console.log(message, origin)
})
// 发送消息给{ name:"home" }页面
this.$tab.postMessage({ type: 'loaded', data: 'hello world!' }, 'home')
// 广播消息
this.$tab.postMessage({ type: 'loaded', data: 'hello world!' }, '*')
// 发给所有path以`/detail`结尾的页面
this.$tab.postMessage({ type: 'loaded', data: 'hello world!' }, /\/detail$/)
// A页面: 广播消息并期待一个应答
this.$tab.postMessage(
    { type: 'load', data: 'hello world!' },
    '*',
    // callback
    (err, res) => {
        console.log(res) // nice to meet you!
    }
)

// B页面: 监听消息
this.$tab.addMessageListener(({ message, origin, answer }) => {
    // 收到消息500ms后回应
    setTimeout(() => answer(null, 'nice to meet you!'), 500)
})