用数据驱动框架vandf创建dropdown组件
vandf是开源的数据驱动开发框架,非常容易创建可重用的响应式组件,话不多说,直接动手撮代码(其中的css使用了tailwind CSS)。
1.安装vandf库
npm i vandf
2.定义组件
Van是一个基础组件类,可以通过继承或直接调用的方式来使用,通过它的实例进行一些配置,具体的使用方法可以参考github仓库的使用文档:github.com/abbasky/van…
import {Van} from "vandf";
class Dropdown extends Van {
constructor(id){
super(id)
//注册视图模型
this.view(DropdownView)
//创建一个按钮
let button = this.kid('button')//定义一个子名称为’button‘的子组件
.tag('button')//element的类型tagName为'button'
.view(ButtonView)//注册视图模型
.html('Dropdown')//设置dropdown的按钮标签
//创建一个弹出层
let popper = this.kid('popper-list').view(PopperView)
//创建一个选项列表
popper.kid('list-item')
.tag('a')
.view(ListItemView)
.model(ListItemModel)//
}
}
3.创建Dropdown视图模型
class DropdownView {
constructor(){
//定义一个弹出层的状态
this._states = {display:false}
}
states(){
//返回状态,将状态向子层传递
return this._states;
}
create (node) {
//注册全局click事件,在禁止选项列表click事件时
//可以认为非dropdown的click事件,此时隐藏弹出层。
node.addEventListener('click', e => {
if(!this._states.display){return}
this._states.display = false;
node.update();
})
//接受选项选中的事件
.on('selected', e => {
console.log(e.data)
})
}
}
4.创建Button视图模型
class ButtonView {
states(s) {
//接收父组件的状态,通过接收父组件的状态实现状态共享
this._states = s;
}
create (node) {
node.on('click', e => {
//停止原生“click”事件冒泡
e.rawEvent.stopPropagation();
//修改状态
this._states.display = !this._states.display;
//更新父组件,因为弹出层在父组件的子组件,而非Button组件的子组件。
node.parent().update()
},true)//传递true参数,注册原生事件。
}
}
//图标视图模型
class IconPathView {
constructor(_, config) {
//接收配置信息,配置信息中含有图标的path值
this._config = config;
}
//通过渲染,将配置信息中icon的path值
render(node){
let c = this._config;
node.attr('d', c.icon)
}
}
5.定义弹出层视图模型
class PopperView {
states(s) {
//接收父层传递的状态值
this._states = s;
}
render (node) {
//根据display状态值设置弹出层弹出或隐藏状态
node.classed('hidden', !this._states.display)
}
}
6.定义选项列表的数据模型和视图模型
class ListItemModel{
constructor(){
this._selIndex = undefined;
}
get selIndex (){return this._selIndex}
get selItem () {return this._selIndex ? this._items[this._selIndex] : undefined}
//supply可以接收顶层一层层传递的数据d,返回值为提取的数组
supply(d) {
this._items = d.list;
return d.list
}
selected(index) {this._selIndex = index}
}
class ListItemView {
constructor(model){
this._model = model;
}
create (node,i){
node.on('click', e => {
this._model.selected(i);
node.emit('selected', this._model.selItem)
}, true)
}
render(node, d, i){
node.text(d)
.classed('bg-blue-100', this._model.selIndex === i)
}
}
7.准备数据
const data = [
"Your Profile",
"Your Projects",
"Help",
"Settings",
"Sign Out"
]
const down = "M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
8.使用组件
let app = Van.new('app')
Dropdown.new('dropdown', app.id)
.supply({list:data})
.config({icon:down})
app.attach(document.querySelector("#app"))
9.总结
用vandf开发的组件,组件的定义、数据模型、视图模型完全结构,每一部分都是可重用的,组合起来也是可重用的,非常适合组件的开发。组件之间可以通过事件、状态共享、配置等实现数据通信,可以非常容易的实现低耦合,高可用的组件开发,且运行效率极高,大家不妨一试。