vue iview checkbox点击事件

vue iview checkbox点击事件,第1张

诉求:在做后台系统用户组权限这块,后台要求点击多选框时把当前ID传过去

但ivew Checkbox组件文档写的不全,于是研究了一番

CheckboxGroup v-model绑定所有勾选项,格式为数组、on-change事件可以获取当前所有勾选项,格式为数组

Checkbox用@clicknative绑定点击事件(直接用@click无反应),然后在事件里进行相应的 *** 作,把id传给后台

但是写的过程中发现了iview的bug,就是CheckboxGroup v-model绑定的数组渲染时后出现错误,会勾选错误,于是只能放弃iview用原始的checkbox

用原生checkbox就灵活多了,加@click,@change都可以,而且可以把数组直接传入方法里,也不需要$event获取

然后渲染勾选项直接v-model绑定就好,不用再处理为数组

写到这里请让我说一声iview垃圾!!!

对了说一句项目里用的iview2x by the way

对于一些快速迭代的产品来说,特别是移动端 C端产品,基于用户运营的目的,在 app首页给用户展示各种各样的d窗是很常见的事情,在产品初期,由于迭代版本和运营策略变化地还不是太大,所以可能觉得没什么,但当产品运营到后期,各种八竿子打不着的运营策略轮番上阵,d窗的样式、逻辑等都变了不知道多少遍的时候,问题就出来了

由于前期没有做好规划,首页的d窗组件可能放了十多个甚至更多,不仅是首页有,首页内又引入了十多个个子组件,这些子组件内也有,搞不好这些子组件内还有子组件,子组件的子组件同样还有d窗,每个d窗都有对应的一组控制显隐逻辑,分散在多个组件多个方法中,但是首页只有一个页面,你不可能让所有符合显示条件的d窗,全都一下子d出来,反正我是没见过这么做的 app,那么如何管理这些d窗就成了头等大事

而往往当你意识到这一点的时候,很可能也正是局势发展到无法控制的时候 治不了,等死吧

场景:Ad窗和 Bd窗位于主组件内,Cd窗位于主组件的子组件 C中,Dd窗位于主组件的子组件 B中,Ed窗位于主组件的子组件F的子组件G中

PM:我希望刚进入这个页面的时候,只有当 Ad窗 和 Bd窗以及 Cd窗,都不展示的时候,才展示 Dd窗,如果 Dd窗展示过了,除非 Bd窗之后又展示了一遍,否则无论什么情况下都不展示 Ed窗

FE:???

稍加思考一下,其实这件事情并不难办,交给后端通过接口控制所有d窗的显隐就行了 主要是架构的提前规划,以及低耦合的代码逻辑

d窗的配置化

先确定一个大体思路,首先,必须要明确地知道当前页面共有哪些d窗组件,包括页面的子组件以及子组件的子组件内的d窗组件,这是必须的,否则你连有哪些组件都不知道怎么精确控制?

所以,还是上面那句话,提前规划,防患于未然是很重要的,不然等页面迭代了几十版,当初写代码的人都不在了你才想到去统计一下页面上到底有多少个d窗,那真是够你喝一壶的

那么就需要在一个地方统一把这些d窗全记录下来,方便管理,于是可以得到下面这种数据结构:

// modalMapjs

export default {

// 记录首页 index页面内的d窗项

index: {

modalList: [{

name: 'modal_1',

level: 10,

show: true

}, {

name: 'modal_2',

level: 22,

show: true

}, {

name: 'modal_3',

level: 70,

show: true

}],

children: {

child1: {

modalList: [{

name: 'modal_1_1',

level: 8,

show: true

}, {

name: 'modal_1_2',

level: 62,

show: true

}],

children: {

child1_1: {

modalList: [{

name: 'modal_1_1_1',

level: 8,

show: true

}, {

name: 'modal_1_1_2',

level: 60,

show: true

}]

}

}

}

}

}

// 还可以继续记录其他页面的d窗结构

}

modalMapjs文件记录每个页面内所有的d窗项,例如,首页 index内的d窗项都在属性名index对于的值数据结构中,index这个页面主组件内存在两个 modal,可以分别命名为 modal_1和 modal_2,如果 index这个页面主组件的子组件内也有 modal,则继续嵌套,例如,index主组件的子组件 child1中也有 modal,那么就把 child1放到 index的 children中继续记录,以此类推

这种结构看起来比较清晰,主组件及主组件内的子组件内的 modal都很清晰,一目了然,当然,你可以不用这种结构,完全取决于你,这里就暂时这么定义

每个 modal除了 name之外,还有 level 和 show属性

level 用于标识当前 modal的层级,每个页面正常只能同时展示一个 modal,但如果有多个 modal都同一时间都满足展示的条件,则对比它们的 level值,哪个大就优先展示哪个,其余的忽略掉,杜绝一个页面可能提示展示多个d窗的情况;

show属性则是在 modal内部来决定 modal最终是否展示,这样一来就可以无视外界条件,很轻松地通过配置来禁止掉d窗的显示

通过发布/订阅模式来管理d窗

d窗的配置结构已经确定了,下一步就是对这些配置的管理了

一般情况下,多个页面同时满足条件需要进行展示的场景,大多数都是发生在刚进入页面,页面发出多个请求,这些请求的返回结果分别控制对应的一个d窗的展示

因为发出去的这些请求很可能分属于不同的业务线或部门管辖,相互独立,所以说如果把d窗的控制权交给后端来做,其实是有点困难的,再加上请求是异步的,前端想要用意大利面条式代码来保证d窗之间的互斥性也不太容易,综合起来,也就导致了当页面上迭代出了数十个以上d窗的时候,如果没有提前规划好,还是很容易出现d窗同时展示的问题的

这里暂时就以刚进入页面的情况为例,进行逻辑梳理

首先,我需要知道页面上有哪些d窗可能会在刚进入页面的时候d出来(即通过接口控制单个d窗的展现与否),然后在所有d窗的数据都拿到了的时候(即跟d窗相关的接口都已经返回数据),才进行d窗的展示

这种情况比较适合使用发布/订阅者模式,单个接口的数据返回就是一个订阅,当所有接口都订阅之后,就进行发布,也就是d窗展示

// modalManagejs

class ModalManage {

constructor (modalList) {

thismodalFlatMap = {}

thismodalList = modalList

}

//

}

通过 ModalManage类来管理d窗,此类在初始化时接收一个参数 modalList,这个参数其实就是刚进入页面时,页面上所有可能展示的d窗(包括子组件的d窗)的名称集合,也就是必须要知道页面上到底有多少个可能同时展示的d窗,以上述示例代码 modalMapjs为例, index页面的 modalList值就是 ['modal_1', 'modal_2', 'modal_3', 'modal_1_1', 'modal_1_2', 'modal_1_1_1', 'modal_1_1_2']

这里其实直接传d窗数量就行了,index中有 7个d窗可能同时展示,所以可以直接传 7,我这里之所以要传名称进去,实际上是为了方便调试,如果代码出问题了,比如页面上实际有 5个接口可以控制 5个d窗的展示,但你却只订阅了 4次,如果只传数字,你就需要一个个找过去看是哪一个忘记订阅了,但如果传名称,你一下子就能调试出来,也就是代码的可维护性会好一点

当页面上任意一个d窗的状态(即是否满足展示的条件)确定下来后,就进行订阅 *** 作:

// modalManagejs

add (name, dataInfo) {

// level, handler

if (thismodalListindexOf(name) !== -1) {

if (!thismodalFlatMap[name]) {

thismodalFlatMap[name] = dataInfo

thisnotify()

} else {

consolelog('重复订阅')

}

} else {

consolelog('无效订阅')

}

}

thismodalFlatMap是为了记录订阅列表,当订阅列表的长度和 modalList相同时,说明所有的d窗状态都已经准备就绪,可以根据这些d窗的优先级进行展示了,也就是 notify方法要做的事情

notify方法中,先排除掉属性 show为 false的d窗项,再对比剩下的d窗的 level,只展示 level最大的那个d窗:

// modalManagejs

notify () {

if (Objectkeys(thismodalFlatMap)length === thismodalListlength) {

const highLevelModal = Objectkeys(thismodalFlatMap)filter(key => thismodalFlatMap[key]show)reduce((t, c) => {

return thismodalFlatMap[c]level > tlevel thismodalFlatMap[c] : t

// 这个 { level: -1 } 只是为了给 reduce函数一个 initialValue,modal项的 level都应该大于这个 initialValue的 level值,即 -1

}, { level: -1 })

highLevelModalhandler()

}

}

使用单例模式管理嵌套组件以及多个页面的d窗

上述的 ModalManage类已经足以管理d窗了,但还有个问题,如果一个页面上的d窗,分散位于页面主组件及其子组件,甚至是子组件的子组件内,怎么办?

这个时候就需要使用单例了

// 单例管理

const manageTypeMap = {}

// 获取单例

function createModalManage (type) {

if (!manageTypeMap[type]) {

manageTypeMap[type] = new ModalManage(getAllModalList(modalMap[type]))

}

return manageTypeMap[type]

}

通过 createModalManage这个方法来创建 ModalManage实例,根据传入的 type来决定是否创建新的实例,如果单例管理对象 manageTypeMap中不存在 type对于的实例,则 new一个 ModalManage实例,存入 manageTypeMap中,并返回这个新实例,否则就返回 manageTypeMap中已经创建好了的实例

这样一来,无论d窗分散在多少个组件内,无论这些组件嵌套得有多深,都能够在保证代码低耦合的前提下,顺利地订阅/发布事件

这里的 getAllModalList方法是个工具方法,用于从 modalMap中获取页面对应的d窗数据结构:

// utiljs

const getAllModalList = modalInfo => {

let currentList = []

if (modalInfomodalList) {

currentList = currentListconcat(

modalInfomodalListreduce((t, c) => tconcat(cname), [])

)

}

if (modalInfochildren) {

currentList = currentListconcat(

Objectkeys(modalInfochildren)reduce((t, c) => {

return tconcat(getAllModalList(modalInfochildren[c]))

}, [])

)

}

return currentList

}

至于 createModalManage的参数type,其值可以就是一个字符串,例如如果需要管理首页 index上可能同时展示的所有的d窗,则可以将 type 的值指定为 index,在 index主组件以及其包含d窗的子组件内,都通过这个字段来获取 ModalManage单例对象:

const modalManage = createModalManage('index')

这样做同时也解决了另外一个问题,就是多个页面的d窗管理问题,index页面通过 index创建 ModalManage单例,详情页就可以通过 detail来创建

今天在使用<slot>插槽时,出来一个问题,那就是使用v-show的标签没有被执行

但是,<slot>插槽的功能是可以正常使用的。

废话不多说了,下面先看图,然后在说解决办法:

想要问题再现,照着上的写一些就行,我这里使用的modal模板是 iview 提供的,至于安装自己去官网上看

在中父组件使用了<slot>和v-show

解决办法:

v-show 改成 v-if

网上找到了解释是:

就跟<template></template>一样页面上跟本没有这个标签对,当然没办法在其上添加css display属性了,所以对 <slot> <template> 都不能使用 v-show 改用 v-if

slot 不能用v-show,只能使用v–if

在制作eclipse插件的时候,时常需要对已经存在的视图做一些扩展,例如在project explorer中增加一个右键菜单,或者需要获取outline中当前选中项,等等。而这些 *** 作的前提,是获取这些视图的id,然后通过获取视图的语句获取到视图,并进行下一步 *** 作。

例如:如果是在view中:

IViewPartpart=getViewSite()getPage()findView("orgeclipseuiviewsContentOutline");

如果是在action中:

IViewPartpart=PlugingetDefault()getWorkbench()getActiveWorkbenchWindow()getActivePage()findView("orgeclipseuiviewsContentOutline");

可见获取到视图的id是很重要的。如何获取id呢,有很多方法,我觉得比较常用的是以下两种:

1通过手动查找目标视图所在的插件的pluginxml中对改视图的定义,获得视图id。

描述:我觉得这是最保险的办法,因为所有的视图都必定有一个pluginxml定义,但是找到这个pluginxml还是需要一些 *** 作,可能会耗费一些时间。

步骤:

a点击“工具栏”->“Search”->“Search”,或者热键“ctrl+h”。选“ Plugin Search”。

bSearch for 选"Extention Point",Limit to 选“references”,External Scope 选“Enabled Plug-ins only”。

c下面的scope选“Worksapaces”。

d上面的Search String框填入我们要搜索的插件的扩展点的名字,这里我们要找视图插件,所以填入:orgeclipseuiviews

e点击search以后,在底部Search视图内列出很多搜索结果,任意选中一个,双击,可以看到editor内打开了该pluginxml,选中编辑器底部的Extentions,用图形化的方式来查看会更快捷。

f可以看到该插件使用的扩展点已经以列表的形式列出,我们查找的orgeclipseuiviews扩展点也已经选中,展开选中的扩展点,可以看到它实现了哪些view,点击某一个,可以在页面右边看到该视图的详细信息,第一项即是视图的id。

我们无法知道目标视图在搜索结果中的哪个plugin中,所以可能会耗费一些时间,建议在查看搜索结果时,通过对视图的分类分析,确定一个大概范围再进行查看。

同时,用这种方法也可以查找其他扩展点的实现插件。

2通过代码直接读出该视图的id。

描述:通过这种方法,可以直接用鼠标点击某个你想知道的视图,控制台会打印出该视图的id和所属插件的id。

步骤:

a通过插件向导新建一个插件,并使用Available Templates中的Plugin with a view模板,点finish。

b对自动创建的SampleView代码进行修改,修改结果如下。其中主要步骤有三个:实现IPartListener2接口,编写isActivePart()方法,调用isActivePart()方法。

packagecomraullearnsampleviewviews;

importorgeclipseswtwidgetsComposite;

importorgeclipseuipart;

importorgeclipsejfaceviewers;

importorgeclipseswtgraphicsImage;

importorgeclipsejfaceaction;

importorgeclipsejfacedialogsMessageDialog;

importorgeclipseui;

importorgeclipseswtwidgetsMenu;

importorgeclipseswtSWT;

importcomraullearnsampleviewActivator;

/

Thissampleclassdemonstrateshowtoplug-inanew

workbenchviewTheviewshowsdataobtainedfromthe

modelThesamplecreatesadummymodelonthefly,

butarealimplementationwouldconnecttothemodel

availableeitherinthisoranotherplug-in(egtheworkspace)

Theviewisconnectedtothemodelusingacontentprovider

<p>

Theviewusesalabelprovidertodefinehowmodel

objectsshouldbepresentedintheviewEach

viewcanpresentthesamemodelobjectsusing

differentlabelsandicons,ifneededAlternatively,

asinglelabelprovidercanbesharedbetweenviews

inordertoensurethatobjectsofthesametypeare

presentedinthesamewayeverywhere

<p>

/

publicclassSampleViewextendsViewPartimplementsIPartListener2{

privateTableViewerviewer;

privateActionaction1;

privateActionaction2;

privateActiondoubleClickAction;

/

Thecontentproviderclassisresponsiblefor

providingobjectstotheviewItcanwrap

existingobjectsinadaptersorsimplyreturn

objectsas-isTheseobjectsmaybesensitive

tothecurrentinputoftheview,orignore

itandalwaysshowthesamecontent

(likeTaskList,forexample)

/

classViewContentProviderimplementsIStructuredContentProvider{

publicvoidinputChanged(Viewerv,ObjectoldInput,ObjectnewInput){

}

publicvoiddispose(){

}

publicObject[]getElements(Objectparent){

returnnewString[]{"One","Two","Three"};

}

}

classViewLabelProviderextendsLabelProviderimplementsITableLabelProvider{

publicStringgetColumnText(Objectobj,intindex){

returngetText(obj);

}

publicImagegetColumnImage(Objectobj,intindex){

returngetImage(obj);

}

publicImagegetImage(Objectobj){

returnPlatformUIgetWorkbench()

getSharedImages()getImage(ISharedImagesIMG_OBJ_ELEMENT);

}

}

classNameSorterextendsViewerSorter{

}

/

Theconstructor

/

publicSampleView(){

ActivatorgetDefault()getWorkbench()getActiveWorkbenchWindow()

getActivePage()addPartListener(this);

}

@Override

publicvoiddispose(){

//TODOAuto-generatedmethodstub

ActivatorgetDefault()getWorkbench()getActiveWorkbenchWindow()

getActivePage()removePartListener(this);

superdispose();

}

/

Thisisacallbackthatwillallowus

tocreatetheviewerandinitializeit

/

publicvoidcreatePartControl(Compositeparent){

viewer=newTableViewer(parent,SWTMULTI|SWTH_SCROLL|SWTV_SCROLL);

viewersetContentProvider(newViewContentProvider());

viewersetLabelProvider(newViewLabelProvider());

viewersetSorter(newNameSorter());

viewersetInput(getViewSite());

makeActions();

hookContextMenu();

hookDoubleClickAction();

contributeToActionBars();

}

privatevoidhookContextMenu(){

MenuManagermenuMgr=newMenuManager("#PopupMenu");

menuMgrsetRemoveAllWhenShown(true);

menuMgraddMenuListener(newIMenuListener(){

publicvoidmenuAboutToShow(IMenuManagermanager){

SampleViewthisfillContextMenu(manager);

}

});

Menumenu=menuMgrcreateContextMenu(viewergetControl());

viewergetControl()setMenu(menu);

getSite()registerContextMenu(menuMgr,viewer);

}

privatevoidcontributeToActionBars(){

IActionBarsbars=getViewSite()getActionBars();

fillLocalPullDown(barsgetMenuManager());

fillLocalToolBar(barsgetToolBarManager());

}

privatevoidfillLocalPullDown(IMenuManagermanager){

manageradd(action1);

manageradd(newSeparator());

manageradd(action2);

}

privatevoidfillContextMenu(IMenuManagermanager){

manageradd(action1);

manageradd(action2);

//Otherplug-inscancontributethereactionshere

manageradd(newSeparator(IWorkbenchActionConstantsMB_ADDITIONS));

}

privatevoidfillLocalToolBar(IToolBarManagermanager){

manageradd(action1);

manageradd(action2);

}

@Override

publicvoidpartBroughtToTop(IWorkbenchPartReferencepartRef){

//TODOAuto-generatedmethodstub

}

@Override

publicvoidpartClosed(IWorkbenchPartReferencepartRef){

//TODOAuto-generatedmethodstub

}

@Override

publicvoidpartDeactivated(IWorkbenchPartReferencepartRef){

//TODOAuto-generatedmethodstub

}

@Override

publicvoidpartHidden(IWorkbenchPartReferencepartRef){

//TODOAuto-generatedmethodstub

}

@Override

publicvoidpartInputChanged(IWorkbenchPartReferencepartRef){

//TODOAuto-generatedmethodstub

}

@Override

publicvoidpartOpened(IWorkbenchPartReferencepartRef){

//TODOAuto-generatedmethodstub

}

privatevoidisActivePart(){

IWorkbenchPartpart=getViewSite()getPage()getActivePart();

//returnpart!=null&&partequals(this);

Systemoutprintln(partgetSite()getId());

partgetSite()getPluginId();

}

}

然后调插件,在运行环境中调出该视图,接着当你用鼠标点击你想知道的视图时,在开发环境中的控制台,就会打印出该视图的id以及所属插件的id。

iview-Upload组件官网链接: >

以上就是关于vue iview checkbox点击事件全部的内容,包括:vue iview checkbox点击事件、vued窗组件出现时,页面结构发生了什么、vue 使用<slot>和v-show 同时使用的问题等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/9665101.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-30
下一篇 2023-04-30

发表评论

登录后才能评论

评论列表(0条)

保存