Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
zhangfisher committed Aug 16, 2024
1 parent acafcc7 commit dcbc185
Show file tree
Hide file tree
Showing 15 changed files with 91 additions and 103 deletions.
12 changes: 6 additions & 6 deletions example/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ import { useState } from 'react'
import classnames from "classnames"
// import UseStateDemo from './UseStateDemo'
import ComputedDemo from './computeds/basic'
import NetworkForm from './forms/network'
import UserForm from './forms/userform/UserForm'
import UserFormWithValidate from "./UserFormValidate"
// import NetworkForm from './forms/network'
// import UserForm from './forms/userform/UserForm'
// import UserFormWithValidate from "./UserFormValidate"

const menuItems=[
// {id:"render",title:"useState",component:<UseStateDemo/>},
// {id:"computed",title:"计算属性",component:<ComputedDemo/>},
{id:"computed",title:"计算属性",component:<ComputedDemo/>,default:true},
// {id:"render",title:"useState",component:<UseStateDemo/>},
// {id:"user",title:"用户",component:<UserForm/>},
{id:"user_valid",title:"校验",component:<UserFormWithValidate/>,default:true},
// {id:"user_valid",title:"校验",component:<UserFormWithValidate/>,default:true},
// {id:"network",title:"网络",component:<NetworkForm/>},
]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@


import React from "react"
import { ReactFC } from "./types";
import store from "./computeds/basic/computed"
import { ReactFC } from "../../types";
import store from "./computed"
import {ColorBlock} from "@speedform/demo-components";

const UserInfo:ReactFC<React.PropsWithChildren> = ()=>{
Expand Down
38 changes: 19 additions & 19 deletions example/src/computeds/basic/computed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,25 +80,25 @@ const storeDefine= {
sales:{
total:0,
},
actions:{
addBook(name:string,author:string,price:number,count:number){
return (state:MyStateType)=>state.books.push({
name,
price,
author,
count,
// @ts-ignore
total:(book:any)=>book.price*book.count
})
},
async addBookAsync(data:{name:string,price:number,author:string,count:number}){
await delay(1000)
// @ts-ignore
data.total =(book:any)=>book.price*book.count
// 模拟异步请求
return (state:MyStateType)=>state.books.push(data)
}
}
// actions:{
// addBook(name:string,author:string,price:number,count:number){
// return (state:MyStateType)=>state.books.push({
// name,
// price,
// author,
// count,
// // @ts-ignore
// total:(book:any)=>book.price*book.count
// })
// },
// async addBookAsync(data:{name:string,price:number,author:string,count:number}){
// await delay(1000)
// // @ts-ignore
// data.total =(book:any)=>book.price*book.count
// // 模拟异步请求
// return (state:MyStateType)=>state.books.push(data)
// }
// }
}

const store = createStore(storeDefine)
Expand Down
4 changes: 2 additions & 2 deletions example/src/computeds/basic/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,8 @@ function ComputedDemo() {
<input style={{width:80}} value={newBook.price} onChange={(e)=>newBook.price=Number(e.target.value)}/>
<input style={{width:80}} value={newBook.count} onChange={(e)=>newBook.count=Number(e.target.value)}/>
</div>
<button onClick={()=>state.actions.addBook(newBook.name,newBook.author,newBook.price,newBook.count)}>添加书籍</button>
<button onClick={()=>state.actions.addBookAsync(newBook)}>异步添加书籍</button>
{/* <button onClick={()=>state.actions.addBook(newBook.name,newBook.author,newBook.price,newBook.count)}>添加书籍</button>
<button onClick={()=>state.actions.addBookAsync(newBook)}>异步添加书籍</button> */}
</div>
</Card>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@


import React from "react"
import { ReactFC } from "./types";
import { ReactFC } from "../../types";
import {ColorBlock} from "@speedform/demo-components";
import { createStore } from "@speedform/reactive";

Expand All @@ -18,16 +18,14 @@ export type AccountStateType = {
};
}
const storeDefine= {
state:{
user:{
id:'zhangfisher',
firstName:'zhang',
lastName:'tom',
fullName:(user:AccountStateType['user'])=> {
return (user.firstName+user.lastName) as string
}
}
}
}
}

const accountStore = createStore<typeof storeDefine>(storeDefine)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ const userDefine = {
title: "验证码",
validate: computed(async (value: string) => {
return value.length > 3
})
},[])
},
submit: { // 这是一个动作,
title: "提交wifi",
Expand Down
5 changes: 5 additions & 0 deletions example/src/forms/network/form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,11 @@ globalThis.Network = Network;
export default Network;


Network.setState(draft=>{
draft.fields.title.value="123"
draft.fields.ip.value="123"
})



// const form = createForm({
Expand Down
24 changes: 12 additions & 12 deletions packages/core/src/action.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@

import { ReactNode, useCallback, useRef, RefObject,useState} from "react";
import React from "react";
import type { FormStore, RequiredFormOptions } from "./form";
import type { FormDefine, FormStore, RequiredFormOptions } from "./form";
import { AsyncComputedDefine, AsyncComputedGetter, AsyncComputedObject, ComputedDescriptor, ComputedDescriptorDefine, ComputedOptions, ComputedParams, Dict, RuntimeComputedOptions, computed, getValueByPath} from '@speedform/reactive';
import { omit } from "flex-tools/object/omit";
import { getFormData } from "./serialize";
Expand Down Expand Up @@ -259,7 +259,7 @@ export function createActionComponent<State extends Dict = Dict>(store:FormStore

const actionState = getValueByPath(state,actionKey,".")
const actionRunner = useActionRunner(actionState,props)
const actionCanceller = useActionCanceller(state,actionKey)
const actionCanceller = useActionCanceller(actionState,actionKey)
// 用来引用当前动作
const ref = useRef<HTMLElement>(null)

Expand Down Expand Up @@ -345,23 +345,23 @@ export type UseActionType = <Scope extends Dict=Dict,R=any>(executor:AsyncComput
* })
*
*/
export function createUseAction<State extends Dict = Dict>(store:FormStore<State>) {
export function createUseAction<State extends FormDefine = FormDefine>(store:FormStore<State>) {
// useAction本质上就是创建一个计算属性
return function useAction<Scope extends Dict=Dict,R=any>(executor:AsyncComputedGetter<R,Scope>,options?:ComputedOptions<R> & {name?:string}){
const ref = useRef<string | null>()
const [state,setState] = store.useState()
const [actionKey] = useState(()=>options?.name ? options?.name : getId())
const [actionName] = useState(()=>options?.name ? options?.name : getId())
if(!ref.current){
setState((draft:any)=>{
if(!(actionKey in draft.actions)){
draft.actions[actionKey] = {
execute:action(executor,options)
}
if(!(actionName in state.actions)){
setState((draft:any)=>{
draft.actions[actionName] = {
execute:action(executor,options)
}
})
}
})
ref.current = actionKey
ref.current = actionName
}
return getValueByPath(state,['actions',actionKey]).execute as FormActionState['execute']
return getValueByPath(state,['actions',actionName]).execute as FormActionState['execute']
}

}
4 changes: 2 additions & 2 deletions packages/core/src/form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@ export const defaultFormProps = {
readonly : false,
enable : true,
visible : true,
actions : {},
fields : {}
fields : {},
actions : {}
}

export type FormEnctypeType = 'application/x-www-form-urlencoded' | 'multipart/form-data' | 'text/plain'
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/hooks/useForm.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useRef } from "react"
import { createForm, FormDefine, FormSchema, RequiredFormOptions } from "../form"
import { createForm, FormDefine, FormOptions, FormSchema } from "../form"


/**
Expand All @@ -18,7 +18,7 @@ import { createForm, FormDefine, FormSchema, RequiredFormOptions } from "../fo
* @param options
* @returns
*/
export function useForm<State extends FormDefine=FormDefine>(schema:()=>State,options?:RequiredFormOptions<FormSchema<State>>) {
export function useForm<State extends FormDefine=FormDefine>(schema:()=>State,options?:FormOptions<FormSchema<State>>) {
type FormType = ReturnType<typeof createForm<State>>
const ref = useRef<FormType>()
if(ref.current==null){
Expand Down
42 changes: 18 additions & 24 deletions packages/reactive/src/reactives/helux.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ import { getValueByPath } from "../utils/getValueByPath";



export class HeluxReactiveable<T extends Dict =Dict> extends Reactiveable<T>{
private _stateCtx:ISharedCtx<T>
constructor(state:T,options?:IReactiveableOptions){
export class HeluxReactiveable<State extends Dict =Dict> extends Reactiveable<State>{
private _stateCtx:ISharedCtx<State>
constructor(state:State,options?:IReactiveableOptions){
super(state,options)
this._stateCtx = sharex<T>(state as any,{
this._stateCtx = sharex<State>(state as any,{
stopArrDep: false,
moduleName:options?.id ?? getRndId(),
onRead:(params)=>{
Expand All @@ -24,53 +24,47 @@ export class HeluxReactiveable<T extends Dict =Dict> extends Reactiveable<T>{
})
}
get state(){
return this._stateCtx.state as ComputedState<T>
return this._stateCtx.state as ComputedState<State>
}
/**
* const [ state ] = useState()
* const [ firstName ] = useState<string>((state)=>state.firstName)
* const [ fullName ] = useState<string>((state)=>state.firstName+state.lastName)
* const [ fullName,updateFullName ] = useState<string,string[]>(
* const [ fullName,setFullName ] = useState<string,string[]>(
* (state)=>state.firstName+state.lastName,
* (state,value)=>{
* state.firstName = value[0]
* state.lastName = value[1]
* }
* )
* updateFullName(['zhang','fisher])
* setFullName(dratf=>{draft.firstName='zhang';draft.lastName='fisher'})
*
* @param getter
* @param setter
* @returns
*/
useState<Value=T,SetValue=Value>(
getter?:StateGetter<RequiredComputedState<T>,Value>,
setter?:StateSetter<RequiredComputedState<T>,SetValue>
):[Value,(value:SetValue)=>void]{
useState<Value=State>(getter?:StateGetter<RequiredComputedState<State>,Value>):[Value,(updater:(draft:State)=>void)=>void]{
const [ state,setState ] = this._stateCtx.useState()
const value = (typeof(getter)==='function' ? getter(state as RequiredComputedState<T>) : state) as Value
const updateValue = (typeof(setter)=='function' ?
(value:SetValue)=>{
//@ts-ignore
setState((draft:any)=>{
setter.call(draft,draft as any,value)
})
} : setState ) as (value:SetValue)=>void

return [ value, updateValue ]
const value = (typeof(getter)==='function' ? getter(state as RequiredComputedState<State>) : state) as Value

return [ value, setState as unknown as (updater:(draft:State)=>void)=>void ]
}

setState(fn:(draft:T)=>void):void{

setState(fn:(draft:State)=>void):void{
//@ts-ignore
this._stateCtx.setState(fn)
}
sync(path: string[]): ((event: any) => void) {
return this._stateCtx.sync(path)
}
/**
* 创建计算属性
* @param fn
* @param depents
* @param options
*/
createAsyncComputed(params: CreateAsyncComputedOptions<ComputedState<T>>): string {
createAsyncComputed(params: CreateAsyncComputedOptions<ComputedState<State>>): string {
const {initial,onComputed,depends,options} = params
this._stateCtx.mutate({
// 收集依赖
Expand All @@ -97,7 +91,7 @@ export class HeluxReactiveable<T extends Dict =Dict> extends Reactiveable<T>{

return options.id as string
}
createComputed(params:CreateComputedOptions<ComputedState<T>>):string{
createComputed(params:CreateComputedOptions<ComputedState<State>>):string{
const {onComputed,options} = params
this._stateCtx.mutate({
fn:(draft,{input})=>{
Expand Down
15 changes: 11 additions & 4 deletions packages/reactive/src/reactives/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,7 @@ export class Reactiveable<State extends Dict = Dict>{
get state():ComputedState<State>{
throw new Error("state not implemented.")
}
useState<Value=State,SetValue=Value>(
getter?:StateGetter<RequiredComputedState<State>,Value>,
setter?:StateSetter<RequiredComputedState<State>,SetValue>
):[Value,(value:SetValue)=>void] {
useState<Value=State>(getter?:StateGetter<RequiredComputedState<State>,Value>):[Value,(updater:(draft:State)=>void)=>void] {
throw new Error("useState not implemented.")
}
/**
Expand All @@ -85,6 +82,16 @@ export class Reactiveable<State extends Dict = Dict>{
runComputed(id:string,options?:RuntimeComputedOptions):void{
throw new Error("runComputed not implemented.")
}
/**
* 用在input的onChange事件中,用于同步输入框的值到状态
* <input onChange={store.sync(['user','name'])} />
*
* @param path
*/
sync(path:string[]):((event:any)=>void){
throw new Error("sync not implemented.")
}


markRaw<V=any>(value:V):V{
throw new Error("makeRaw not implemented.")
Expand Down
1 change: 1 addition & 0 deletions packages/reactive/src/store/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ export function createStore<T extends Dict>(data:T,options?:Partial<StoreOptions
store.useState = createUseState<T>(store)
store.setState = createSetState<T>(store)
store.enableComputed = (value:boolean=true)=>store.options.enableComputed = value
store.sync = store.reactiveable.sync.bind(store.reactiveable)
// store.sync = store.stateCtx.sync
// 侦听
store.watch = createWatch<T>(store)
Expand Down
2 changes: 1 addition & 1 deletion packages/reactive/src/store/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ export type IStore<State extends Dict = Dict> = {
watchObjects : WatchObjects<State>

// 用来同步表单时使用
sync : ISharedCtx<ComputedState<State>>['sync']
sync : (path:string[])=>((event:any)=>void)
// 简单事件触发与侦听
on : Emitter<StoreEvents>['on']
off : Emitter<StoreEvents>['off']
Expand Down
Loading

0 comments on commit dcbc185

Please sign in to comment.