项目用jQuery写的,一些操作dom逻辑混杂在一起,不够清晰,于是重构了一下,把逻辑分离出来,方便以后维护。
实现思路
类似pubsub,监听attr变化,更新dom
而数据处理部分仅仅需要往attr上写数据,不需要关心dom如何渲染
实现代码
稍微展示一下重点代码
看看界面长什么样吧!
未选中状态
选中状态
可以看到,未选中状态需要展示文本“添加自定义图片”,选中状态需要展示图片和删除按钮
若是直接编写代码,采用命令式的方式,需要判断当前状态,然后根据状态来决定如何渲染dom
这会导致状态切换逻辑混杂DOM操作,使代码不够清晰,不利于维护
而采用数据驱动的方式,只需要往attr上写数据,然后监听attr变化,根据attr的值来渲染dom,这样就可以把状态切换逻辑和DOM操作分离开来,使代码更加清晰
这是DOM结构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| <div class="editor-image-choice"> <div class="editor-image--view rounded" style="display: none;"> <img src="" class="image-view__img" /> <div class=" init-text text-gray text-xs image-view__text"> <p>请选择图片</p> <p>支持JPG,PNG,GIF</p> </div> <div class="del-icon image-view__del"> <img src="/edit3d/assets/image/icon/del.png" alt="" > </div> </div> <div class="editor-image--content"> <div class="editor-image--text"> <div class="text text-xs text-gray">建议尺寸:50 x 50</div> </div> <button class="btn btn-primary editor-image--btn choice-logo-image-btn"> <span class="text-sm">添加图片</span> </button> </div> </div>
|
这里是配合该组件的脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
|
export const useImagePicker = (selector, cfg = {}) => { const $container = $(selector) const $viewContainer = $container.find('.editor-image--view') const $viewImg = $container.find('.image-view__img') const $viewText = $container.find('.image-view__text') const $delIcon = $container.find('.image-view__del') const $uploadBtn = $container.find('.editor-image--content .editor-image--btn') function setImageUrl(url) { $container.attr('image-url', url) } function isImgSetted() { return $container.attr('image-url') !== '' } function setError() { $viewContainer.addClass('error') } function removeError() { $viewContainer.removeClass('error') } tools.observeDomAttribute(selector, 'image-url', function (url) { $viewImg.attr('src', tools.urlResolve(url)) if (url === '') { $viewImg.hide() $viewText.show() $delIcon.hide() } else { $viewImg.show() $viewText.hide() $delIcon.show() removeError() } $viewContainer.show() cfg.onChange && cfg.onChange(url) }); setImageUrl(cfg.url || '') $uploadBtn.click(function () { openMediaSourceDialog('image', function (url) { console.log('selected', url) setImageUrl(url) }) }) $delIcon.on('click', function () { setImageUrl('') })
return { setImageUrl, setError, isImgSetted } }
let imgPicker = null async function initImageView() { const imgUrl = await getImgUrl() imgPicker = useImagePicker(".editor-image-choice", { url: imgUrl, onChange(url) { }, }); }
window.onload = function () { initImageView() }
function onSubmit(){ const isImgSet = imgPicker?.isImgSetted() if (!isImgSet) { imgPicker.setError() layer.msg("请上传图片") return; } }
|
基本就是这样,感觉很简单有没有?这就是数据驱动的魅力!