Thinking In Vue:vue指令的封装

问题和解决

我看到项目中有一些这样的代码,在组件里给dom绑定事件:

     dragmove = new DragMove({
       id: 'groupingeve',
       benchmark: 'right',
       dragdbclick: function() {},
       dragclick: function(e) {},
       dragend: function(e) {}
     })

看到这样的代码很别扭,理想情况下,vue的组件里是不应该感知到dom的存在的,他能感知和操作的只有数据,数据到dom的各种绑定(事件、值)都应该通过指令。也就是说vue处理的输入和输出都是纯粹的数据,模板的输入是数据,输出是vdom。这个绑定事件的逻辑不应该放到组件里,应该移到模板中去。

Thinking In Vue:vue指令的封装_第1张图片

vue指令的定义是:当表达式的值改变时,将其产生的连带影响,响应式地作用于 DOM。这个连带影响可能是dom结构的变更,可能是dom事件的绑定,可能是文本值的变化等。

所以,这个数据到dom的逻辑应该封装到模板语法中的指令里。

于是我这样封装了一下:


import DragMove from 'drag-move';

const install = (Vue) => {
    /**
     * dragmove指令
     * 用法: 
*/ Vue.directive('dragmove', { inserted: (el, binding) => { const options = {...binding.value, id: binding.arg}; new DragMove(options); } }); } module.exports = install;

并且在入口js文件里作为全局资源引入了:

import installDirectives from '@/common/directives';

installDirectives(Vue);

用法是直接在需要处理的元素上加上这个指令,参数为id,值为option:

(这里的id其实我想去掉,但是DragMove本身并不支持传一个元素,所以保留了id。)

我用在了纪律树模块里,对比一下前后的代码
之前:

  this.dragObj = new DragMove({
     id: ele,
     dragClick: dragClickHandler,
     dragend: dragEndHandler
 });

之后:

  

把和dom绑定的过程移到了模板中的指令中。这样的组件会更加的纯粹。
模板负责数据到dom的绑定和同步,组件负责交互、业务逻辑的各种数据处理,一前一后、一个只处理数据、一个只渲染视图,这样的代码,就算我把渲染层换成了原生android或ios、换成了VR,都可以适应,因为组件的纯粹。

不同的代码有不同的封装形式

之前我们讨论过为什么echarts在vue中使用要封装成组件,为什么Lottie和vue结合要封装成组件,为什么mybatis和spring整合要提供SqlSessionFactoryBean。 这些都是因为每种框架或者库都有自己对各类资源的处理思路与流程 : 就像spring对Bean的处理,支持BeanPostProcesser,支持FactoryBean等,就像Vue对模板的处理支持directive、filter、component等,就像javaweb中Servlet、Listener、Filter这些的区别一样。不同的代码应该有不同的封装形式,不同的封装形式也各自的使用方式以及可以用的资源。

当然,如果根本没用到框架对资源的特有处理方式,那么不封装成对应的形式也是可以的。比如spring里面如果就是没有用到spring对bean的管理,那么直接手动new也无可厚非。
如果逻辑特别简单,不是特别值得封装,那么不封装也是可以的。比如有一段逻辑按照vue的思路应该作为filter而存在,但是逻辑特简单,用到的地方也不多,这样可以不封装。

Thinking in vue

在vue里,指令负责的是数据到dom的过程,所以类似的代码应该封装成指令,才能更好的和组件解耦,以及使用vue对指令提供的各种支持。除此以外,各种代码都有对应的封装形式,使用了vue,不能再用jquery的思路去使用,而应该用vue的思路。

总之,希望可以用vue的思路去写vue,用spring的思路去写spring。

Thinking in Vue !

你可能感兴趣的:(Thinking In Vue:vue指令的封装)