Home >Web Front-end >JS Tutorial >Vue practice summary mvvm learning

Vue practice summary mvvm learning

小云云
小云云Original
2018-03-12 16:37:141325browse

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

1.1 Implementation principle

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

1.2 Core technical points

1.2.1 Template analysis

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

1.2.2 Change monitoring

In many mvvm class frameworks, there are 3 implementations of change monitoring Type:

  1. 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.

  2. 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.

  3. dirty check: such as angular. There is enough research on Angular, so I won’t go into details here.

<span class="comment">//方式1 vs. 方式2</span>
<span class="comment">//方式1:</span>
vm.<span class="variable">$set</span>(aaa, <span class="number">1</span>);    <span class="comment">//会触发变动逻辑</span>
vm._data.aaa = <span class="number">2</span>;   <span class="comment">//不会触发变动逻辑,不过这不是框架希望的操作,可以被hack</span>
vm.<span class="variable">$get</span>(aaa);       <span class="comment">//2</span>
<span class="comment">//方式2:</span>
vm.aaa = <span class="number">1</span>;         <span class="comment">//一定会触发变动逻辑</span>
vm._data.aaa = <span class="number">2</span>;   <span class="comment">//也可以找到内部的data进行修改,但是没用</span>
vm.aaa;             <span class="comment">//1</span>

1.2.3 Summary and Extension

Analyze, decouple and abstract a type of complex and common problems, and gain widespread recognition in the process of practice, then a model is formed, mvvm It is also a mode. It is not necessarily called mvvm mode. This is not something I can decide.

Regarding the core of this mode, I understand the following: the system obtains certain processing rules for certain data sources according to the configuration. , when the data source changes, corresponding processing rules will be triggered. The expansion of the schema is bidirectional, which is determined by the system implementation. When certain rules are met, the data source can be updated.

We break away from the concept of view and Lenovo implements a monitoring system. In fact, this model is very suitable for use in monitoring systems.

The processing logic of the general monitoring system is: the collection source collects and organizes the monitoring data, and then stores it in the database. The monitoring system monitors the data source in real time and draws real-time graphs (feedback). When the data source When changes occur that comply with certain rules, corresponding actions will be triggered, such as alarming.

How to implement this system and make the system more scalable? Referring to the mvvm mode, it can be like this:

The collection system is independent of the monitoring system and is different, so let’s not care about it for now. The monitoring system obtains the data sources that need to be monitored and the corresponding processing logic rules through certain configuration files, and triggers corresponding processing when the data sources change.

Perform some abstractions according to the mvvm mode.

  • The data source is not necessarily limited to the database, it can be anywhere, as long as the system can obtain it through certain configurable rules

  • The processing rules are abstracted to make them easier to expand, such as sending emails, text messages, WeChat, QQ messages, etc.

##corresponds to the front-end mvvm framework, and the template is the configuration File, directive is the processing rule, and data corresponds to the data source.

  • When the system needs to add a new data source, it only needs to update the configuration file and let the system read it to start data monitoring

  • When you need to add a new processing rule, you can expand a new processing rule through a hot-swappable processing rule plug-in system, and then update the configuration file, and the system can accept the new processing rule

2 vue practice

I don’t need an introduction to vue, there are too many resources. Here are some gains from the practice of vue

2.1 Organizational structure

##1

2

3

4

5

6

7

8

9

10

11


##1

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

2.2 Vue扩展

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继承问题的产物

2.3 vue组件插入问题

2.3.1 首屏

对于首屏的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">"&#39;hello, &#39;+name"</span>>hello</p>
<img v-attr=<span class="string">"src: imgSrc"</span> />

 

{{}} 只是一个语法糖,不建议使用

2.3.2 非首屏

对于非首屏的组件,使用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实现组件的主要核心也就这些,更方便的组件写法也只是对这些进行封装

2.4 自定义 directive

在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">&#39;.z-scroller&#39;</span>) || window).addEventListener(<span class="string">&#39;scroll&#39;</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">&#39;data-defaultsrc&#39;</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">&#39;data-isload&#39;</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.

2.5 Pain points and tips in practice

2.5.1 No event proxy

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

2.5.2 The strangeness of not having if-else

It will be really strange when you first see the following code

1

2

3

##2b3ffebfe4fa2a05dc1f7448b6b7c948if54bdf357c58b8a65c66d7c19c8e4d114=fab9ab63db7b134c286b50796f2abfe1"hasTitle"54bdf357c58b8a65c66d7c19c8e4d114>xxx39528cedfa926ea0c01e69ef5b2ea9b0

a2416441a4809ad4aa10cebcb3d99644if54bdf357c58b8a65c66d7c19c8e4d114=fab9ab63db7b134c286b50796f2abfe1"!hasTitle"54bdf357c58b8a65c66d7c19c8e4d114>xxx94b3e26ee717c64999d7867364b1b4a3

2.5.3 Single value

Although vue has a syntax parser, you can use expressions in the value of the directive, but when a complex expression appears , will pollute the template and make the code less readable, or when the expression cannot complete the task.

Therefore, during the practice of mvvm, I deeply discovered that using a single value (at most only one ?: expression) to write templates will make the code clearer, more readable, and increase the number of codes. Maintainability, and this is more in line with the core idea of ​​mvvm: f(state) = view

Some libraries do not even have a grammar parser, such as q, but they can work very well.

So, where are the complex operations placed?

  • For values ​​that will not change, that is, constants, the processing must be completed before initialization

  • For values ​​that will change , put complex operations in the filter. Not only can complex processing be performed in the filter, but it can even be applied to other fields at the same time. This is not completely equivalent to computed attribute

2.5.4 Alternative $(document).on

When using jquery/zepto, I am used to using $(document).on to act as a global event proxy. When using vue, I need to abandon zepto, so I need to solve this problem. Problem

Because the vue instance itself has the event function, the solution here is to create a global empty vue object and use it as the global event proxy:

##89e7ad2b99889e4d86b051f40860f447//common/vue/vue.ext.js Look back For an introduction to this file, you can see this sentence54bdf357c58b8a65c66d7c19c8e4d114


3 Summary

Although in the end we gave up the Vue transformation of existing projects in the cost-output ratio trade-off, this does not prevent us from studying the mvvm class framework

The mvvm model is still worthy of our in-depth study, and in practice, we can also learn a lot

The experience of using a different way of thinking and thinking will also make us look at and deal with problems. There is something gained on the road.

Related recommendations:

How to implement mvvm-style tabs in Angularjs? Case + code

js implementation of a simple MVVM framework example sharing

What is MVVM architecture and data binding?

1

2

3

4

5

6

7

8

9

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!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn