Home >Web Front-end >JS Tutorial >Vue practice summary mvvm learning
MVVM is the abbreviation of Model-View-ViewModel. Microsoft's WPF brings a new technology experience. This article mainly shares with you a summary of vue practice and mvvm learning, hoping to help everyone.
1 mvvm learning
The implementation principle of the mvvm class framework is not complicated and is roughly as follows:
Template analysis Obtain dependent attributes
Monitor these dependent attributes through some kind of change monitoring method
When the attributes change, the corresponding directive is triggered Just process the logic
#In fact, the processing logic of the directive is not necessarily to operate the view, such as reporting. However, under the idea of mv, it is recommended that all operations on views be concentrated in directives
From the core point of view, the idea of mv is just a specific extension of the observer pattern. That’s all
Template analysis is relatively basic. Everything related to views will basically involve templates. This is Original material, the key point here is the issue of template source, in fact, it should be any string
This implies that the framework needs a template parser, no matter whether the parser is complex or simple, it is A pattern: [Input–> Template Engine–> Output]
So, the characteristics of mvvm’s template parser are as follows:
Input: any character that matches the rules String
Output: data.attr, directive, filter that need to be monitored
When designing a framework, if you want to have better For scalability, the
input should be flexible enough. In terms of source, the template can be someDomHere.html() or dynamic input, which is more applicable; in terms of content, If the engine can recognize higher-level syntax, it will be more functional.
The output should be convergent enough. Convergence means limited and regular. Like the mvvm framework, only directives and filters come out in the end. The specific processing is Concentrate on these two concepts, and only extend these two concepts to expand the system
In many mvvm class frameworks, there are 3 implementations of change monitoring Type:
Facade method setter, getter: such as knockout, q. Limit the entrances that can be changed, and let the user decide how to use the entrance.
Use defineProperty: such as vue, avalon. In essence, it is also a setter and getter, but the right to use the entrance is not left to the user to decide.
dirty check: such as angular. There is enough research on Angular, so I won’t go into details here.
##1234567891011 |
2 3 4 5 6 7 8 9 10 11 12 13 14 ##+ src |
+ -- common + -- vue.js +-- index.js +-- vue.ext.js +-- xxx.mixin.js |
vue的扩展非常方便,与vue相关的资源都放置在src/common/vue/下面,比如coms(组件),directive,filter
src/common/vue/vue.ext.js是对vue进行全局公共的扩展,对于所有页面共有的扩展放在这个文件下面,内容如下:
可以看到,扩展vue库本身有4个扩展点:
扩展Vue库的全局方法/属性,方式:Vue.xxx = …
扩展Vue实例的方法/属性,方式:Vue.prototype = …
扩展directive,方式:Vue.directive(‘directiveName’, options);
扩展filter,方式:Vue.filter(‘filterName’, function(){});
对于页面单独需要的扩展,集中在src/pages/pageName/vue.ext.js里面,形式与全局的vue.ext.js一样
在实例化Vue的过程中也有许多可以扩展与优化的地方,在实践过程中只是应用了mixin功能,其他的可以慢慢深入
mixin的作用是在实例化Vue的时候混入一些功能,它可以混入许多特性,格式与实例化Vue时用到的option格式一样,比如index页面的mixin.js的内容如下:
这个mixin混入了两个方法,多个Vue实例共享的options可以放置到mixin中,从而避免了代码重,比如在实例化Vue的时候这样使用mixin:
可以看到mixin是个数组,因此可以同时使用多个mixin
实际上这里的mixin主要不是为了避免代码重复(实践的时候只是这样用),mixin是一种模式,一个mixin内聚了实现一项功能的方法/属性集合,在定义/生成实例的时候,通过混入mixin就可以让该实例拥有某项功能,归根结底是组合vs继承问题的产物
对于首屏的vue组件,直接把模板放在主页面中即可,初始化的时候只需要把el参数传入,Vue就会用el的html作为模板来初始化Vue实例:
这里需要注意的是在模板中不能使用{{}},否则在还没初始化之前,页面会显示奇怪的东西,比如:
1 2 3 4 5 6 7 |
<p>hello, {{name}}</p> <!--初始化前,页面会直接展示hello, {{name}}--> <img src=<span class="s tring">"{{imgSrc}}"</span> /> <!--初始化前,会报错,can not find http:<span class="comment">//xxx.com/{{imgSrc}}--></span> <!--正确的写法:--> <p v-text=<span class="string">"'hello, '+name"</span>>hello</p> <img v-attr=<span class="string">"src: imgSrc"</span> />
|
{{}} 只是一个语法糖,不建议使用
对于非首屏的组件,使用vue的方式和原始方式差不多,先生成节点,然后append,譬如:
el参数可以接收query string,也可以直接是一个dom节点,如果是dom节点则直接编译dom的内容。如果dom节点不在文档树中,则利用vueObj.$appendTo方法将vue实例的根节点插入到文档树中
上面这种方式是在页面中没有组件的【坑】的情况下使用的,如果页面为组件留了【坑】,比如:
1 2 |
0510d38451755f656b967a56ae76d68aclass54bdf357c58b8a65c66d7c19c8e4d114=e7b5d65d577098ec09191daa17885c87"hotRecord"54bdf357c58b8a65c66d7c19c8e4d114 id=e7b5d65d577098ec09191daa17885c87"js-hotRecord"54bdf357c58b8a65c66d7c19c8e4d114>4d7ab0de9a42de71c682b0860bad1410
|
那么,我们可以这样初始化vue实例:
利用template参数传入模板,并指定el,那么vue实例在初始化之后就会自动把内容插入到el中
通过vue实现组件的主要核心也就这些,更方便的组件写法也只是对这些进行封装
在vue中自定义directive是非常简单明了的,要自定义一个directive,可以注册3个钩子函数:
bind:仅调用一次,当指令第一次绑定元素的时候。
update:第一次调用是在 bind之后,用的是初始值;以后每当绑定的值发生变化就会被调用,新值与旧值作为参数。
unbind:仅调用一次,当指令解绑元素的时候。
下面简单介绍一个自定义directive——lazyload:
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 |
<span class="keyword">function</span> addSrc(){} <span class="keyword">function</span> load(){} module.exports = { bind: <span class="keyword">function</span>() { <span class="keyword">if</span> (!hasBind) { <span class="comment">//全局事件只绑定一次</span> hasBind = <span class="keyword">true</span>; (document.querySelector(<span class="string">'.z-scroller'</span>) || window).addEventListener(<span class="string">'scroll'</span>, T.debounce(load, <span class="number">100</span>), <span class="keyword">false</span>); } <span class="comment">//这里也可以使用data属性来获取</span> <span class="keyword">var</span> defaultSrc = <span class="keyword">this</span>.el.getAttribute(<span class="string">'data-defaultsrc'</span>); <span class="keyword">if</span> (defaultSrc) addSrc(<span class="keyword">this</span>.el, defaultSrc); <span class="comment">//先使用默认图片</span> }, update: <span class="keyword">function</span>(src) { <span class="comment">//directive初始化时,会调用一次bind和update,bind没有传入src,只有update才会传入src</span> <span class="comment">//因此只能在update这里拿到需要lazyload的src</span> <span class="comment">//lazyload不允许修改src,这里限制只会执行一次update,防止src被修改造成的影响</span> <span class="comment">//注:接受src改变可以实现,只是需要一些复杂的处理,这里为了简单起见不让src改变</span> <span class="keyword">if</span> (<span class="keyword">this</span>.init) <span class="keyword">return</span>; <span class="keyword">this</span>.init = <span class="keyword">true</span>; <span class="comment">//如果图片已经加载了,就不需要注册了,这里也可以使用data属性来区分</span> <span class="keyword">var</span> isLoad = parseInt(<span class="keyword">this</span>.el.getAttribute(<span class="string">'data-isload'</span>)); <span class="keyword">if</span> (isLoad) <span class="keyword">return</span>; <span class="comment">//注册需要lazyload的图片</span> <span class="keyword">list</span>[index++] = <span class="keyword">this</span>; <span class="keyword">list</span>[index++] = src; } <span class="comment">//这里有一个最大的问题:由于有local的存在,会创建两个一模一样的lazyload directive</span> <span class="comment">//按理说应该定义一个unbind,但是在unbind中找到并除掉local创建出来的lazyload directive会比较麻烦</span> <span class="comment">//因此在load函数里面做了一个处理:如果发现需要lazyload的节点不在文档树中,则剔除掉这个lazyload</span> <span class="comment">//通过这个直接省掉了unbind函数</span> };
|
Customizing the filter is also very simple. It just defines a processing function. I won’t introduce it here.
I am used to using event proxies, and it will be a bit uncomfortable to suddenly lose them. But looking back, is the event proxy really important? Or are we just used to event proxies?
It is not troublesome to register the same event through vue. Another problem is that as long as there are not many events, no more than 50 or 100, it will not consume a lot of memory, so sometimes there is really no need for an event agent. If you really need it, just implement a contain method
It will be really strange when you first see the following code
1 2 3 |
##2b3ffebfe4fa2a05dc1f7448b6b7c948if54bdf357c58b8a65c66d7c19c8e4d114=fab9ab63db7b134c286b50796f2abfe1"hasTitle"54bdf357c58b8a65c66d7c19c8e4d114>xxx39528cedfa926ea0c01e69ef5b2ea9b0a2416441a4809ad4aa10cebcb3d99644if54bdf357c58b8a65c66d7c19c8e4d114=fab9ab63db7b134c286b50796f2abfe1"!hasTitle"54bdf357c58b8a65c66d7c19c8e4d114>xxx94b3e26ee717c64999d7867364b1b4a3 |
123456789 | ##89e7ad2b99889e4d86b051f40860f447//common/vue/vue.ext.js Look back For an introduction to this file, you can see this sentence54bdf357c58b8a65c66d7c19c8e4d114
Vue.noopVue = bd51fd4180b618149e9b74046b0a37ednew54bdf357c58b8a65c66d7c19c8e4d114 Vue({});
89e7ad2b99889e4d86b051f40860f447//a.js54bdf357c58b8a65c66d7c19c8e4d114 Vue.noopVue.d9df1c7814ea394f861c6a0ed66fe7ab$on494c0df226525cc046cf4930a65bbd6f(fab9ab63db7b134c286b50796f2abfe1'someEvent'54bdf357c58b8a65c66d7c19c8e4d114, bd51fd4180b618149e9b74046b0a37edfunction54bdf357c58b8a65c66d7c19c8e4d114() {});
89e7ad2b99889e4d86b051f40860f447//b.js54bdf357c58b8a65c66d7c19c8e4d114 Vue.noopVue.d9df1c7814ea394f861c6a0ed66fe7ab$emit |
The above is the detailed content of Vue practice summary mvvm learning. For more information, please follow other related articles on the PHP Chinese website!