vue-control v1.1.3
Vue-Control辅助器
注意本package中的dom节点和text节点封装尚未完善,酌情使用,目前Vue组件封装的较为完善
用来让vue表现得更像一个control,支持添加控件,包括获取slots的Element数组等,黑心为IElement代理类型,可代理三种不同的vue节点:实例,text,dom节点,使用统一的接口操作时间,属性等
主要部分
核心类与接口
//表示一个节点
export interface IElement {
node: VNode;
type: ElementType;
getProp(name: string): any | undefined;
setProp(name: string, value: any): boolean;
listen(name: string, cbk: Function): boolean;
unlisten(name: string, cbk: Function): boolean;
}
有三个class实现了此接口 1. VueElement 表示一个vue组件实例 2. DomElement 表示一个dom节点实例 3. TextElement 表示一个text节点 每个类都有一个静态的create函数用来创建此类的节点并执行检查,定义如下
create(node: VNode): IElement | null;
我们推荐使用node函数创建IElement,这是一个通用创建函数,具体在下方说明
构建部分
构建部分核心为node函数,定义如下:
export declare function node(node: VNode): IElement;
此函数从一个vue的VNode节点创建一个Element
但一般不直接使用此函数,而是使用一下工具函数
1. element() 可以从一个vue实例创建一个Element,可以在如mounted之类的函数中使用element(this)来获取与本组件对应的Element
2. slots() 可以从一个vue实例的slots中创建一个Slots对象,此对象定义如下:
export interface Slots {
[slotname: string]: IElement[];
}
- children() 函数,可以从一个vue实例得到一个element数组,表示其直接子节点列表,如果没有子节点,返回空数组
判断部分
下面三个函数用来在使用时判断情况:
export declare function isdom(ele: IElement): ele is DomElement;
export declare function iscomponent(ele: IElement): ele is VueElement;
export declare function istext(ele: IElement): ele is TextElement;
每一个的含义不言自明,通过使用if判断可以自动启动编辑器的智能提示,提供某些element特有的属性,如textelement的text属性,以及一些约束,如textelement的setProp和getProp只能接受text一个属性名
示例
以下是一个不怎么好的例子
//容器组件
import {int, str} from "ts-pystyle"
import vue,{CreateElement as h, VNode} from "vue"
//这里导入node 和element两个函数 其中node可以从vnode得到element element可以从
//vue实例得到自己的element
import {node, element} from "vue-control"
export const selectEvent="select";
let a=vue.extend({
render(h){
//!这是使用vue control 监听事件
let ele=element(this);
ele.listen(selectEvent,()=>{
alert("hello 这是使用element体系得到的")
});
//!这是在有实例的情况下使用实例本身的on函数监听事件
ele.node.componentInstance?.$on("click",()=>alert("testtest"));
////
let childs=this.$slots.default as VNode[];
console.log(childs);
//给每个childs添加事件
//这里考虑用map
childs.filter(v=>v.tag!=null&&v.componentOptions!=null).forEach((v,i)=>{
//! 这是使用vue control进行的事件监听
node(v).listen("click",()=>{
alert("asdfasdf");
})
console.log(v.data)
// if(v.data==null) return;
debugger;
//这是自己进行事件监听
if(!v.componentOptions) return;
//只有它存在的时候也就是是vue组件的时候才
v.componentOptions.listeners=v.componentOptions?.listeners??{};
let on=v.componentOptions.listeners as any;
//保留原始监听器
let nclick=[] as Function[];
if(on.click!=null)
if(on.click instanceof Array) nclick=nclick.concat(on.click);
else nclick.push(on.click);
on.click=nclick;
on.click.push((e?:string)=>{
//响应事件
//理论上 接受的vnode都是TabButton的组件实例
//或者好歹都得有一个active属性和一个click事件 click事件传递一个
//string作id 如果为null就直接用idx
let idx=str(i);
let sid=e??idx;
//触发事件
this.$emit(selectEvent,sid);
// this.$emit("click","hellio");
//打印
alert(`click${sid}`)
})
})
return h("div",{style:"background:red; height:100px;"},childs);
}
})
export default a;
此组件可以对内部传入的子节点做修改,增加统一的事件监听,可以使用箭头函数以得到独立的this上下文和闭包,灵活度高于template写法
更新内容 1.2.0
添加了each函数,用于在render或mounted等函数中加入updated事件的工作,类似hooks的功能,用法
...
mounted(){
each(this,()=>{
//可保持值恒定为1
element(this).setProp("test",1);
})
}
总结
本helper包用于在vue中执行各种element相关操作,某些必须以传统control形式而非以所谓的数据驱动和mvc方式进行的工作,如控件封装和容器组件编写,在容器组件中改变slot传入的子组件的行为等,并不符合 匹配数据驱动视图的基本模式的情况
如果将slots传入的组件也看做props,则容器组件本应该有针对slots的完整操作能力,这与数据驱动试图并不矛盾,slots作为props也算数据的一部分
本helper包主要用于抽象逻辑封装,如单选 切换等