自由灵活,简单便捷的前端框架
fedom: 前端DOM渲染方案
安装&使用:
$ npm i fedom -S // 安装fedom
// 配置webpack 的 module.rules 选项, 解析.js文件
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env',],
plugins: [
// ... // 其他配置
...require("fedom/babel_config_plugins.js"), // 支持 jsx 编译
],
}
}
}
import "fedom"; // 引入fedom
API:
const {
// 渲染方法
render,
// 组件&生命周期
onMounted, // 渲染后
onUnmount, // 卸载前
onReused, // 使用缓存后
Component, // 类组件
// model&view
VaryValue, // 单个动态值
VaryList, // 动态列表
VaryMap, // 动态所有键值
// 路由
Router,
DecorateSync, // 同步路由函数组件修饰器
DecorateSyncMore, // 同步路由函数组件默认配置修饰
DecorateAsync, // 懒加载路由函数组件修饰器
DecorateAsyncMore, // 懒加载路由函数组件默认配置修饰
// 其他工具
Promising, // 进行中的Promise
utils, // 工具集合对象
} = window.$fd;
功能列表:
1 JSX模板渲染
render 渲染方法
支持渲染 VaryValue(动态值) / Array(列表) / Promise(异步渲染) / fdNode(jsx) / Node(原生dom节点) / text(其他任意作为文本渲染)
// 如渲染 fdNode
render(
<div>JSX内容渲染</div>,
document.getElementById("#app")
)
ref
ref={<Promising>} Promise异步执行
let refVal = Promising();
refVal.then((node)=>{
console.log(node); // 若绑定在组件根节点,则为组件context
})
// 该节点渲染完毕后, refVal 将 resolved
<div ref={refVal}>aaa</div>
ref={callback} 回调函数形式
2 视图的渲染&动态更新: model<->view
数据模型
VaryValue 动态值,动态更新视图
let vv = VaryValue(val, trimFn);
trimFn 默认为: val=>val; // 无格式化
初始渲染通知
vv.mounted(()>{
// vv在视图中被渲染后调用
})
更新视图
vv.set((originVal, trimedVal)=>{
return '设置的值'
})
model取值
vv.get(true)
vv.get(false)
vv.$$
动态化监听
vv.watch((nextVal, prevVal, trimedNextVal, trimedPrevVal)=>{
// vv被设置值时调用
})
动态化开关
vv.on() 关闭动态响应
vv.off() 开启动态响应
vv.kill() kill掉vv, 不可逆操作
动态值依赖
let vv1 = VaryValue.depend([vv], (lst)=>{
return '-' + lst[0]
})
VaryList 动态列表,优化列表渲染, 继承自VaryValue
let vl = VaryList(listVal, trimFn);
提供各种列表的更新方法
vl.$insert(id, list) // 指定位置开始插入若干项
vl.$remove(id, len) // 指定位置开始删除指定个数项
vl.$update(id, val) // 更新指定项为指定的值
vl.$slice(id1, id2) // 返回指定范围内的项
vl.$unshift(val1, val2, ...)
vl.$push(val1, val2, ...)
vl.$shift()
vl.$pop()
vl.$map(()=>{ })
vl.$set(list) // 全量更新
VaryMap 动态值集合
let vm = VaryMap(mapVal, trimFn)
vm.$insert(key, val)
vm.$update(key, val)
vm.$get()
vm.$set(()=>{ return newMapVal })
vm.$each(()=>{})
vm.$remove(key1)
vm.key2 map中的指定key对应的VaryValue值
动态内容类型
vary组件
vary标签
vary属性
额外提供两个便捷控制属性
fd_if={VaryValue(bol)}
fd_show={VaryValue(bol)}
vary子节点
整个数组
单个子节点
文本内容
3 组件化
class组件
class Cpnt extends Component {
constructor(props){
super(props)
}
onMounted(elem){
console.log('渲染完毕');
}
onUnmount(){
console.log('组件卸载');
}
onReused(elem){
console.log('组件缓存');
}
render(){
return (
<section>
</section>
)
};
}
function组件 (推荐使用函数组件代替类组件)
function Cpnt(props, context){
context.onMounted = (elem)=>{
console.log('渲染完毕');
}
context.onUnmount = (elem)=>{
console.log('组件卸载');
}
context.onReused = ()=>{
console.log('组件缓存');
}
return (
<section>
</section>
);
}
类hook的生命周期: 该使用方式,可逻辑抽离管理
onMounted(ctx, ()=>{}) // 渲染完毕后
onUnmount(ctx, ()=>{}) // 卸载前
onReused(ctx, ()=>{}) // 缓存页面重载
组件通信
<VaryValue>.watch() // 监听属性的动态值变化
<component>.xxx(val) // 子组件的方法被调用
组件状态共享/多组件通信
使用集中的动态值导出, 在需要的地方引入, 即可进行状态共享,视图更新
// store.js
export const statusA = VaryValue(1);
// 组件A 引入, 可更新和使用
import { statusA } from '../store.js';
// 更新
statusA.set((val)=>{
return val+1;
})
// 使用(渲染结果)
<div>{ statusA }</div>
css命名空间: fedom框架标识了组件内的所有节点
配合loader使用: @justfn/css-scope-loader
4 路由 Router
// 静态方法
Router.push(hashPath, hashQuey) // 路由跳转
Router.replace(hashPath, hashQuey) // 路由跳转(不保留当前记录)
Router.forward() // 前进一步
Router.back() // 后退一步
Router.go(num) // 前进/后退num步
Router.parseURL(url) // 解析指定url,url默认为:location.href
const router = Route({
routes: [
{
path: '/',
// 路由懒加载
component: (preRoute, newRoute)=>import('../pages/homePage.js')
// 注意非懒加载也需使用函数返回的形式: 可额外为页面组件提供路由参数
// component: (preRoute, newRoute)=>homePage,
alias: '/home', //
isCache: true, // bol,是否缓存, 默认: false
// 其他额外可自定义放置的参数
extra: {
title: '首页',
},
// 子路由
children: [
{
path: 'pageA', // 简化逻辑, 不区分 '/pageA' 或 'pageA'
component: (preRoute, newRoute)=>import('../pages/pageA.js')
extra: {
title: '页面A',
},
},
],
},
],
root: document.querySelector("#app"),
beforeEach(oldRoute, newRoute){
if (newRoute.hashPath==='/forbid') {
return false;
}
return true;
},
afterEach(oldRoute, currentRoute){
let routeOption = currentRoute.option || {};
let routerExtra = routeOption.extra || {};
let title = routerExtra.title || '页面标题';
document.title = title;
},
})
let router = Router(options) // 多次调用 Router, 总会返回唯一的 router 对象
// 实例属性
router.getOld // 前一路由信息对象
router.getNew // 当前路由信息对象
router.routes // 所有配置的路由信息列表
// 实例方法
router.backUntillTo(url, dftUrl) // 返回到指定URL,不存在则返回到dftUrl
5 其他工具方法
utils 工具集对象
.html(str) 将富文本解析为可渲染的内容
待办TODO
bug: scoped css
写框架文档
错误/编译错误 提示优化
性能优化:
DOM操作性能优化
组件根节点可为一数组 实现非单一节点功能
--------------------------------------------------------------------------------