Maison  >  Article  >  interface Web  >  Résumé de la pratique Vue apprentissage mvvm

Résumé de la pratique Vue apprentissage mvvm

小云云
小云云original
2018-03-12 16:37:141229parcourir

MVVM est l'abréviation de Model-View-ViewModel. Le WPF de Microsoft apporte une nouvelle expérience technologique. Cet article partage principalement avec vous un résumé de la pratique de vue et de l'apprentissage de mvvm, dans l'espoir d'aider tout le monde.

1 apprentissage mvvm

1.1 Principe de mise en œuvre

Le principe de mise en œuvre du framework de classe mvvm n'est pas compliqué, à peu près comme suit :

  • Analyse du modèle Obtenir les attributs dépendants

  • Surveiller ces attributs dépendants via une méthode de surveillance des modifications

  • Lorsque les attributs changent, déclencher la directive correspondante Traitez simplement le logique

En fait, la logique de traitement de la directive n'est pas nécessairement d'opérer la vue, comme le reporting. Cependant, sous l'idée de mv, il est recommandé que toutes les opérations sur les vues soient concentrées dans des directives

Du point de vue fondamental, l'idée de mv n'est qu'un extension spécifique du modèle d'observateur. C'est tout

1.2 Points techniques de base

1.2.1 Analyse du modèle

L'analyse du modèle est relativement basique. implique essentiellement des modèles. Il s'agit de matériel original, le point clé ici est la question de la source du modèle, en fait, il devrait s'agir de n'importe quelle chaîne

Cela implique que le framework a besoin d'un analyseur de modèle, que l'analyseur soit ou non. complexe ou simple, il s'agit d'un modèle : [Entrée–> Template Engine–> >Entrée : tout caractère conforme aux règles String

    Sortie : data.attr, directive, filtre qui doivent être surveillés
  • Quand concevoir un framework, si vous voulez avoir une meilleure évolutivité, l'entrée
  • doit être suffisamment flexible en termes de source, le modèle peut être someDomHere.html() ou une entrée dynamique, qui est plus applicable ; En termes de contenu, si le moteur peut reconnaître une syntaxe de niveau supérieur, il sera plus fonctionnel

  • La sortie doit être suffisamment convergente, ce qui signifie des règles limitées et régulières. Comme le framework mvvm, la sortie finale n'est que des directives. et des filtres. Le traitement spécifique se concentre sur ces deux concepts, en étendant uniquement ces deux concepts, le système peut être étendu

1.2.2 Surveillance des modifications

Dans de nombreux frameworks de classes mvvm, il existe 3 implémentations de surveillance des changements Type :

Setter de méthode de façade, getter : tel que knockout, q. Limitez les entrées qui peuvent être modifiées et laissez l'utilisateur décider comment utiliser l'entrée.

    Utilisez DefineProperty : comme vue, avalon. Essentiellement, il s'agit également d'un setter et d'un getter, mais le droit d'utiliser l'entrée n'est pas laissé à l'utilisateur de décider.
  1. chèque sale : tel que angulaire. Il y a suffisamment de recherches sur Angular, je n'entrerai donc pas dans les détails ici.
  2. 1
  3. 2

  4. 3

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

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


    4567891011
    <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> />

    1.2.3 Résumé et extension

    Analyse, découplage, abstraction d'un type de problèmes complexes et courants, et gagnant une large reconnaissance dans la pratique, puis un modèle, mvvm, est formé. C'est aussi un mode, on ne l'appelle pas nécessairement mode mvvm, et ce n'est pas quelque chose que l'auteur peut décider

    Concernant le cœur de ce mode, l'auteur comprend ce qui suit : le système obtient certaines règles de traitement pour certaines sources de données selon le configuration, lorsque la source de données change, les règles de traitement correspondantes seront déclenchées. L'expansion du schéma est bidirectionnelle, déterminée par l'implémentation du système. Lorsque certaines règles sont respectées, la source de données peut être mise à jour.

    Nous rompons avec la notion de vue et Lenovo met en œuvre un système de surveillance. En fait, ce modèle est très adapté à une utilisation dans les systèmes de surveillance.

    La logique de traitement du système de surveillance général est la suivante : les données de surveillance sont collectées et organisées par la source de collecte, puis stockées dans la base de données. Le système de surveillance surveille la source de données en temps réel et dessine en temps réel. graphiques (retour d'informations). Lorsque la source de données Lorsque des changements conformes à certaines règles se produisent, les actions correspondantes seront déclenchées, telles que l'alarme.

    Comment mettre en œuvre ce système et rendre le système plus évolutif ? En ce qui concerne le mode mvvm, cela peut être comme ceci :

    Le système de collecte est indépendant du système de surveillance et est différent, alors ne nous en soucions pas pour l'instant. Le système de surveillance obtient les sources de données qui doivent être surveillées et les règles logiques de traitement correspondantes via certains fichiers de configuration, et déclenche le traitement correspondant lorsque les sources de données changent.

    Suivez le modèle mvvm et faites quelques abstractions.

    • La source de données ne se limite pas nécessairement à la base de données, elle peut être n'importe où, à condition que le système puisse l'obtenir grâce à certaines règles configurables

    • Les règles de traitement sont abstraites pour faciliter leur extension, comme l'envoi d'emails, de SMS, WeChat, les messages QQ, etc.

    correspond au framework front-end mvvm, et le modèle est le fichier de configuration, la directive est la règle de traitement et les données correspondent à la source de données.

    • Lorsque le système doit ajouter une nouvelle source de données, il vous suffit de mettre à jour le fichier de configuration et de laisser le système le lire pour démarrer la surveillance des données

    • Lorsque vous devez ajouter une nouvelle règle de traitement, vous pouvez développer une nouvelle règle de traitement via un système de plug-in de règle de traitement remplaçable à chaud, puis mettre à jour le fichier de configuration, et le système peut accepter la nouvelle règle de traitement

    2 Pratique de Vue

    L'introduction à Vue n'est pas nécessaire, il y a trop de ressources. Voici quelques gains de la pratique de vue

    2.1 Structure organisationnelle

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    + src

    + - - communs

                                                                                         +-- filtres

                                            -- vue.js

                                                                                                                                       vue.ext.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>
    };

     

    La personnalisation du filtre est également très simple. Elle définit simplement une fonction de traitement, je ne la présenterai pas ici

    2.5 Points douloureux et astuces en pratique

    2.5.1 Aucun événement. proxy

    Je suis habitué à utiliser des proxys d'événements, et ce sera un peu inconfortable de les perdre soudainement. Mais avec le recul, le proxy d'événements est-il vraiment important ? Ou sommes-nous simplement habitués aux proxys d’événements ?

    Enregistrer le même événement via vue se fait sans effort. Un autre problème est que tant qu'il n'y a pas beaucoup d'événements, pas plus de 50 ou 100, cela ne consommera pas beaucoup de mémoire, donc parfois il n'y a vraiment pas besoin d'un agent d'événements. Si vous en avez vraiment besoin, implémentez simplement une méthode contain

    2.5.2 L'étrangeté de ne pas avoir if-else

    Quand vous verrez pour la première fois le code suivant, ce sera vraiment étrange

    1

    2

    3

    af5c2ece8ea7a096914f90670424bcf6if54bdf357c58b8a65c66d7c19c8e4d114=e7b5d65d577098ec09191daa17885c87"hasTitle"54bdf357c58b8a65c66d7c19c8e4d114>xxx39528cedfa926ea0c01e69ef5b2ea9b0

    06a275819bf51ee1d38350f8e7d3f19aif54bdf357c58b8a65c66d7c19c8e4d114=e7b5d65d577098ec09191daa17885c87"!hasTitle"54bdf357c58b8a65c66d7c19c8e4d114>xxx94b3e26ee717c64999d7867364b1b4a3

     

    1

    2

    3

    5dcb9448b0bc5ca33008a548eba465c6if54bdf357c58b8a65c66d7c19c8e4d114=fab9ab63db7b134c286b50796f2abfe1"hasTitle"54bdf357c58b8a65c66d7c19c8e4d114>xxx39528cedfa926ea0c01e69ef5b2ea9b0

    3c9ffb8a54c6b20bc57889242f7c8311if54bdf357c58b8a65c66d7c19c8e4d114=fab9ab63db7b134c286b50796f2abfe1"!hasTitle"54bdf357c58b8a65c66d7c19c8e4d114>xxx94b3e26ee717c64999d7867364b1b4a3

    • 2.5.3 Valeur unique

      Bien que Vue dispose d'un analyseur de syntaxe, vous pouvez utiliser des expressions dans la valeur de la directive, mais lorsqu'un Les expressions complexes pollueront le modèle et rendront le code moins lisible, ou l'expression ne pourra pas terminer la tâche.
    • Par conséquent, au cours de la pratique de mvvm, j'ai profondément découvert que l'utilisation d'une seule valeur (une seule ?: expression au maximum) pour écrire des modèles rendra le code plus clair, plus lisible et augmentera la maintenabilité du code, et cela correspond plus à l'idée de base de mvvm : f(state) = view

      Certaines bibliothèques n'ont même pas d'analyseur de grammaire, comme q, mais elles peuvent très bien fonctionner.
    • Alors, où placer les opérations complexes ?

      Pour les valeurs qui ne changeront pas, c'est-à-dire les constantes, le traitement doit être terminé avant l'initialisation

      1

      2

      3

      4

      5

      6

      7

      8

      9

      e63d03b1fe1ef417bff512a2da2d7305//common/vue/vue.ext.js 回头看前面对该文件的介绍可以看到这句54bdf357c58b8a65c66d7c19c8e4d114

      Vue.noopVue = 9b8f193a100df443bb5f942579a9d04cnew54bdf357c58b8a65c66d7c19c8e4d114 Vue({});

       

      e63d03b1fe1ef417bff512a2da2d7305//a.js54bdf357c58b8a65c66d7c19c8e4d114

      Vue.noopVue.5a4944fb39e8a6d067595fa969ab7502$on54bdf357c58b8a65c66d7c19c8e4d114(e7b5d65d577098ec09191daa17885c87'someEvent'54bdf357c58b8a65c66d7c19c8e4d114, 9b8f193a100df443bb5f942579a9d04cfunction54bdf357c58b8a65c66d7c19c8e4d114() {});

       

      e63d03b1fe1ef417bff512a2da2d7305//b.js54bdf357c58b8a65c66d7c19c8e4d114

      Vue.noopVue.5a4944fb39e8a6d067595fa969ab7502$emit54bdf357c58b8a65c66d7c19c8e4d114(e7b5d65d577098ec09191daa17885c87'someEvent'54bdf357c58b8a65c66d7c19c8e4d114, [opts]);

      Pour les valeurs qui va changer, mettre des opérations complexes dans le filtre. Non seulement un traitement complexe peut être effectué dans le filtre, mais il peut même être appliqué à d'autres champs en même temps. Ce n'est pas complètement équivalent à l'attribut calculé<.>2.5.4 Alternative $(document).onLorsque j'utilise jquery/zepto, j'ai l'habitude d'utiliser $(document).on comme proxy d'événement global Lorsque j'utilise vue, j'en ai besoin. pour abandonner zepto, je dois donc résoudre ce problème. Problème Étant donné que l'instance vue elle-même a la fonction d'événement, la solution ici est de créer un objet vue vide global et de l'utiliser comme proxy d'événement global : table>


      3 Résumé

      Bien qu'au final nous ayons abandonné la transformation Vue des projets existants dans le compromis du rapport coût-rendement, cela ne nous empêche pas d'étudier le framework de classe mvvm

      Le modèle mvvm mérite toujours notre étude approfondie, et dans la pratique, nous pouvons aussi apprendre beaucoup

      L'expérience de développer avec un type de pensée et de réflexion différent nous fera également regarder et résoudre les problèmes. Il y a quelque chose de gagné sur la route.

      Recommandations associées :

      Comment Angularjs implémente-t-il les onglets de style mvvm ? Case + code

      implémentation js d'un exemple de partage de framework MVVM simple

      Qu'est-ce que l'architecture MVVM et la liaison de données ?

      12345 67 89 6c71938007c5fec21a98dfbf0a06a1cf//common/vue/vue. ext.js En revenant sur l'introduction précédente de ce fichier, vous pouvez voir cette phrase 54bdf357c58b8a65c66d7c19c8e4d114Vue.noopVue = 4f7b19c6761c6c06e828752a346bc01fnouveau54bdf357c58b8a65c66d7c19c8e4d114 Vue({ }); 89e7ad2b99889e4d86b051f40860f447//a.js54bdf357c58b8a65c66d7c19c8e4d114Vue.noopVue.d7fd1888db37a8127e2d59ebcce5d0f6$on54bdf357c58b8a65c66d7c19c8e4d114(fab9ab63db7b134c286b50796f2abfe1'someEvent'54bdf357c58b8a65c66d7c19c8e4d114, b4d03f3152244853cc41318ec689fb29function54bdf357c58b8a65c66d7c19c8e4d114() {}) ; 89e7ad2b99889e4d86b051f40860f447//b.js54bdf357c58b8a65c66d7c19c8e4d114 Vue.noopVue.88104d7fcb1def03eec3820362570296$emit54bdf357c58b8a65c66d7c19c8e4d114(fab9ab63db7b134c286b50796f2abfe1'someEvent'54bdf357c58b8a65c66d7c19c8e4d114, [opts]); td>

    Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

    Déclaration:
    Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn