@roundjs/fission-utils
v1.0.14-alpha.1
Published
## 说明
Downloads
1
Readme
@roundjs/composition-ali
说明
@roundjs/composition-ali
是基于 reactivity
api 的小程序开发库,它能让你用 Composition API
写小程序,就像写 Vue 3 一样。
- 微信小程序:@roundjs/composition-wx
- 支持:微信,qq,百度,字节,京东,快手,飞书
- 支付宝小程序:@roundjs/composition-ali
- 支持:支付宝,钉钉,口碑
功能导航:
使用
npm i @roundjs/composition-ali
# or
yarn add @roundjs/composition-ali
(ps:1.1.xx之后的版本使用方式 由Page(createPage())
改为更简洁的直接 createPage()
)
Page
import { createPage, reactive, computed } from '@roundjs/composition-ali';
createPage({
setup() {
const state = reactive({
count: 0,
double: computed(() => state.count * 2),
});
function increment() {
state.count++;
}
return {
state,
increment,
};
},
});
在使用上为了不影响原小程序语法,先使用 createPage
包装一层:
Page(obj)
-> createPage(obj)
如果 setup
返回一个对象,则对象的属性将会被合并到页面实例上,可以直接在页面模版中使用。
<button onTap="increment">
Count is: {{ state.count }}, double is: {{ state.double }}
</button>
注意 setup
返回的 ref
在模板中会自动解开,不需要写 .value
。
setup
- 调用时机
setup
会在 onLoad
阶段被调用。返回的数据和方法也会在此时才会被合并到页面实例上,所以模版初次渲染时数据可能是 undefined
。不过小程序模版对此做了兼容,所以不用担心会报错。
- 参数
setup
函数的第一个参数与 onLoad 的参数相同。
createPage({
setup(query) {
// query 为打开当前页面路径中的参数
},
});
生命周期
生命周期对应关系:
import { createPage, onShow, onHide, onUnload } from '@roundjs/composition-ali';
createPage({
setup() {
onShow(() => {
console.log('show');
});
onHide(() => {
console.log('hide');
});
onUnload(() => {
console.log('unload');
});
},
});
| 原生 | 组合式 api | | :---------------: | :---------------: | | onLoad | setup | | onShow | onShow | | onReady | onReady | | onHide | onHide | | onUnload | onUnload | | onTitleClick | onTitleClick | | onReachBottom | onReachBottom | | onPullDownRefresh | onPullDownRefresh | | onShareAppMessage | onShareAppMessage | | onPageScroll | onPageScroll | | onTabItemTap | onTabItemTap |
为了兼容自定义hooks
,页面也可以使用 onMounted
和onUnmounted
生命周期
createPage
第二个参数为配置项,以下两个生命周期需要配置才可生效
onPageScroll
onShareAppMessage
onPageScroll
监听页面滚动会引起小程序渲染层与逻辑层的通信。为避免定义空的 onPageScroll
监听造成不必要的性能损耗,需要使用 createPage
的第二个参数提前告知 composition-ali
是否会调用 onPageScroll()
钩子。
import { createPage, onPageScroll } from '@roundjs/composition-ali';
createPage(
{
setup() {
onPageScroll(({ scrollTop }) => {
console.log('scrollTop:', scrollTop);
});
},
},
{
listenPageScroll: true, // 默认为 false
}
);
onShareAppMessage
由于小程序会根据是否定义了 onShareAppMessage
监听来决定页面是否可以转发,所以需要使用 createPage
的第二个参数提前告知 Vue Mini 是否会调用 onShareAppMessage()
钩子。又由于 onShareAppMessage
会返回自定义转发内容,所以一个页面只能有一个 onShareAppMessage
监听。
import { createPage, onShareAppMessage } from '@roundjs/composition-ali';
createPage(
{
setup() {
// 仅第一次调用,且 `canShareToOthers` 为 `true`,且 `onShareAppMessage` 选项不存在时才生效。
onShareAppMessage(() => {
return {
title: '小程序示例',
desc: '小程序官方示例Demo,展示已支持的接口能力及组件。',
path: 'page/component/component-pages/view/view?param=123',
};
});
},
},
{
canShareToOthers: true, // 默认为 false
}
);
原生混用
import { createPage, ref } from '@roundjs/composition-ali';
createPage({
setup() {
const count = ref(0);
function increment() {
count.value++;
}
return {
count,
increment,
};
},
data: {
number: 0,
},
add() {
this.setData({ number: this.data.number + 1 });
},
});
如果名称相同,setup()
返回的数据或方法会覆盖原生语法声明的数据或方法。你应该避免出现这种情况。
请不要在其他选项中访问 setup()
返回的数据或方法,这将引起混乱。如果确实有此需求,应该将相关逻辑搬到 setup()
内。
简洁语法
createPage(() => {
const count = ref(0);
function increment() {
count.value++;
}
return {
count,
increment,
};
});
Component
组件 setup
函数第一个参数为 props
(跟 vue3 一样,不可解构使用)
第二个参数包含emit
方法向父组件通知
(注意props
声明方式跟原生小程序写法不一样)
import { createComponent, watch } from '@roundjs/composition-ali';
createComponent({
emits: ['change'],
props: {
count: {
default: 0
},
},
setup(props, { emit }) {
console.log(props.count)
watch(
() => props.count,
(val) => {
emit('change')
console.log('watch props.count', val)
}
);
const count = computed(() => props.count * 2);
return {
count,
};
},
});
生命周期
生命周期对应关系:
| 原生 | 组合式 api | | :--------: | :---------: | | didMount | setup | | didMount | onMounted | | didUpdate | onUpdated | | didUnmount | onUnmounted | | onError | onError |
页面声明周期
组件可使用部分页面的声明周期: onShow
onHide
onPullDownRefresh
onReachBottom
onPageScroll
onTabItemTap
在组件里使用onShow
时可能会错过初次的onShow
调用
App
import { createApp } from '@roundjs/composition-ali';
createApp({
setup() {
const greeting = 'Hello World!';
return {
greeting,
};
},
});
注意
createApp
需要注意,setup
返回的对象不会经过处理,依然是响应式
返回什么就是什么:
createApp({
setup() {
const greeting = ref('Hello World!');
return {
greeting,
};
},
});
const app = getApp();
console.log(app.greeting.value); // Hello World!
生命周期
生命周期对应关系:
| 原生 | 组合式 api | | :------------------: | :------------------: | | onLaunch | setup | | onShow | onAppShow | | onHide | onAppHide | | onError | onAppError | | onPageNotFound | onPageNotFound | | onUnhandledRejection | onUnhandledRejection |
响应式 api
响应式 api 跟 vue3 使用相同,可参考 响应式 api 文档
响应性基础 API
- reactive
- readonly
- isProxy
- isReactive
- isReadonly
- toRaw
- markRaw
- shallowReactive
- shallowReadonly
Refs
- ref
- unref
- toRef
- toRefs
- isRef
- customRef
- shallowRef
- triggerRef
Computed 与 watch
- computed
- watchEffect
- watchPostEffect
- watchSyncEffect
- watch
(watch
参数 flush: 'post'
或者 使用watchPostEffect
api,可在数据改变并且小程序页面完成渲染后触发回调)
Effect 作用域 API
- effectScope
- getCurrentScope
- onScopeDispose
hooks
useNextTick
{
setup() {
const nextTick = useNextTick()
const count = ref(0)
const changeCount = () => {
count.value++
nextTick(() => {
// dom更新后
})
await nextTick()
}
}
}
也可从setup
的context
中引入
{
setup(xxx, { nextRender }) {
const count = ref(0)
const changeCount = () => {
count.value++
nextRender(() => {
// dom更新后
})
await nextRender()
}
}
}
useApp
跟小程序的getApp
不一样的是可在createApp
的setup
里使用
依赖注入
与 Vue
一样,composition-ali
提供了依赖注入功能,以解决 props
深度透传的问题。它们是一对 provide / inject
函数,它们的使用方式和 API
均与 Vue
一致。
Provide
// parent-component.js
import {
createComponent,
ref,
provide,
readonly,
} from '@roundjs/composition-ali';
createComponent({
setup() {
const count = ref(0);
function increment() {
count.value++;
}
provide('count', readonly(count));
provide('increment', increment);
},
});
Inject
// deep-child-component.js
import { createComponent, inject } from '@roundjs/composition-ali';
createComponent({
setup() {
const count = inject('count');
const increment = inject('increment');
return {
count,
increment,
};
},
});
注意 依赖注入对执行顺序有所要求,
provide
必须先于inject
执行,所以在createPage
的setup
函数中调用provide
可能会遇到问题。
AOP
AOP(切面编程),主要对 App/Page/Component
内方法调用进行统一劫持,可用于埋点,链路分析,日志等功能
import { aop, setupAOP } from '@roundjs/composition-ali';
const pageAop = aop(
{
onLoad(args, name) {
console.log('所有页面onLoad调用之前都会触发', args);
},
onShareAppMessage: {
after(result, args, name) {
console.log(`${name}方法被调用之后,after一般获取函数返回值操作`);
return result;
},
},
},
(args, name) => {
console.log('other 其他函数调用');
}
);
// 装载全局,要在createApp/createPage/defineComponent之前调用
setupAOP(({ page, app, component }) => {
page.add(pageAop);
});
- aop(AopOptions, Other)
- aop(Other)
aop
方法有两个参数,AopOptions
代码劫持某一具体函数,Other
代表劫持除了AopOptions
内声明的其他函数
可以只传入Other
来劫持所有函数调用
after请务必返回result
结果
aop 函数只会劫持一层对象,如需多层可用以下写法:
aop({
onShow(args, name) {} // 函数形式默认 before
onHide: { // 对象形式 before after
before(args, name) {}
after(result, args, name) {return result}
}
methods: aop({ // 深度劫持
handleClick(args, name) {}
})
}, {
before(args, name) => { // Other 也可以写成对象形式,可通过name来判断对象名
console.log('除了onShow,onHide的方法都会触发Other')
}
})
优化路径
可通过修改配置参数来启用优化路径模式
import { setGlobalConfig, createPage } from '@roundjs/composition-wx';
// 全局配置
setGlobalConfig({
optimizePath: true,
});
// or
// 优先级更高的局部配置
createPage({ setup() {} }, { optimizePath: true });
createComponent({ setup() {} }, { optimizePath: true });
在 createPage
和 createComponent
上配置优先级更高,会先取示例上的配置,然后取全局配置
启用 优化路径 模式后,setData
会采用路径形式来修改数据,例:
list[0].deep.name = 'xxx'
这个修改中,如果不启用 optimizePath
则默认修改的是整个 list
: setData({ list })
,如果 list 数据过长就会造成性能下降
如果启用 optimizePath
则会精确修改变动值 setData({ 'list[0].deep.name': 'xxx' })
,从而提高 setData
性能
ps:因为optimizePath
模式会多出来 diff
数据的时间,实际上会比原生 setData({ 'list[0].deep.name': 'xxx' })
慢,但是比不启用optimizePath
直接 setData({list})
更快