Vue実践まとめmvvm学習

小云云
リリース: 2018-03-12 16:37:14
オリジナル
1320 人が閲覧しました

MVVMはModel-View-ViewModelの略称です。 Microsoft の WPF は、新しいテクノロジー エクスペリエンスをもたらします。この記事は主に vue の実践と mvvm の学習についてまとめたもので、皆様のお役に立てれば幸いです。

1 mvvm の学習

1.1 実装原理

mvvm クラス フレームワークの実装原理は複雑ではなく、おおよそ次のとおりです:

  • 依存属性を取得するためのテンプレート分析

  • 何らかの変更を通じてこれらの依存属性を監視する監視メソッド

  • 属性が変更されたとき、対応するディレクティブ処理ロジックをトリガーするだけです

実際、ディレクティブ処理ロジックはレポートなどのビューを操作する必要はありません。ただし、mv の考え方では、ビューに対するすべての操作をディレクティブに集中することが推奨されます

コアの観点から見ると、mv の考え方は、オブザーバー パターンの特定のアプリケーション拡張にすぎません

1.2 主要な技術ポイント

1.2.1 テンプレート分析

ビューに関連するすべての作業には、基本的にテンプレートが含まれます。実際、ここで重要なのは、テンプレートのソースです。任意の文字列である必要があります

これは、パーサーが複雑か単純かに関係なく、フレームワークが [入力 –> テンプレート エンジン –> 出力] のモードにあることを意味します。 mvvmのテンプレートパーサーの特徴は以下の通りです :

    入力:ルールに従った任意の文字列
  • 出力:監視が必要なdata.attr、ディレクティブ、フィルター
  • フレームワークを設計する際に、より優れたスケーラビリティが必要な場合は、

入力が十分に柔軟である必要があります。ソースに関しては、エンジンがより高度なものを認識できる場合、テンプレートは someDomHere.html() または動的入力にすることができます。構文を使用すると、より機能的になります

出力は十分に収束する必要があります。収束とは、mvvm フレームワークと同様に、最後に現れるのはディレクティブとフィルターのみです。これら 2 つの概念は拡張され、概念を使用してシステムを拡張できます

1.2.2 変更監視

多くの mvvm クラス フレームワークでは、次の 3 種類の変更監視があります:

    Facade メソッド setter、getter: などノックアウト、Q.変更できる出入り口を限定し、出入り口の使い方はユーザーに決めてもらいます。
  1. defineProperty: vue、avalon などを使用します。本質的には、セッターとゲッターでもありますが、入り口を使用する権利はユーザーの決定に委ねられません。
  2. ダーティチェック:角度など。 Angular については十分な研究があるため、ここでは詳しく説明しません。
1

1.2.3 概要と拡張

ある種の複雑で一般的な問題が、実際に広く認識されると、モデルが形成されます。これは、必ずしも mvvm モードと呼ばれるものではありません。このモードの核心については、システムが設定に従って特定のデータ ソースに対して特定の処理ルールを取得し、データ ソースが変更されるとそれがトリガーされるということを作成者は理解しています。対応する処理ルール。スキーマの拡張は双方向であり、これはシステム実装によって決定され、特定のルールが満たされると、データ ソースを更新できます。

ビューの概念から脱却し、Lenovo の監視システムを実装しました。実際、このモデルは監視システムでの使用に非常に適しています。

一般的な監視システムの処理ロジックは、収集元が監視データを収集・整理し、データベースに格納する監視システムがデータソースをリアルタイムで監視し、リアルタイムのグラフを描画します(フィードバック)。データ ソースが特定のルールを満たした場合、これらのルールが変更されると、アラームなどの対応するアクションがトリガーされます。

このシステムを実装し、システムをよりスケーラブルにする方法は? mvvm モードを参照すると、次のようになります。

収集システムは監視システムから独立しており、異なるため、今のところ心配する必要はありません。監視システムは、特定の構成ファイルを通じて監視する必要のあるデータ ソースと対応する処理ロジック ルールを取得し、データ ソースが変更されたときに対応する処理をトリガーします。

mvvm パターンに従い、いくつかの抽象化を作成します。

    データ ソースは必ずしもデータベースに限定されるわけではなく、どこでもかまいません。システムが特定の構成可能なルールを通じて取得する必要があるだけです
  • 処理ルールは、拡張を容易にするために抽象化されています。電子メールの送信、テキスト メッセージの送信、WeChat の送信、QQ メッセージの送信など。
  • はフロントエンドの mvvm フレームワークに対応し、テンプレートは設定ファイル、ディレクティブは処理ルール、データはデータに対応しますソース。

    システムが新しいデータソースを追加する必要がある場合、構成ファイルを更新し、システムがそれを読み取ってデータ監視を開始するだけです
  • 処理ルールを追加する必要がある場合は、ホットプラグ 処理ルールプラグインシステムで、新しい処理ルールを展開し、構成ファイルを更新すると、システムは新しい処理ルールを受け入れることができます
  • 2 vue の練習

vue 導入は必要ありません、多すぎますリソース。 vue の実践から得られる利点をいくつか挙げます

2.1 組織構造

2

3

4

5

6

7

8

9

10

11

りー


1+src

2

3

4

5

6

7

8

9

10

11

12

13

14

coms

;

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

class="hotRecord" id="js-hotRecord">

那么,我们可以这样初始化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>
};
ログイン後にコピー

 

フィルターのカスタマイズも非常に簡単です。ここでは紹介しません。

2.5 実際の難点とヒント

2.5.1 イベントプロキシには慣れています。突然ですが、イベント プロキシがありません。少し聞き慣れないかもしれませんが、よく考えてみると、イベント エージェントは本当に重要ですか?それとも、単にイベント プロキシに慣れているだけなのでしょうか?

vue 経由で同じイベントを登録するのは簡単です。もう 1 つの問題は、イベントがそれほど多くない (50 または 100 を超えない) 限り、大量のメモリを消費しないため、実際にはイベント エージェントが必要ない場合があることです。本当に必要な場合は、containメソッドを実装してください

2.5.2 if-elseの奇妙さはありません

以下のコードを初めて見たときは、本当に奇妙です

1

if="hasTitle">xxx

if="!hasTitle">xxx

2.5.3 単一値

2

3

Vue にはディレクティブの値に式を使用できる構文パーサーがありますが、複雑な式が出現するとテンプレートが汚染され、コードが読みやすくなります。非常に悪い場合、または式がタスクを完了できない場合。

したがって、mvvm の実践中に、単一の値 (最大でも 1 つの ?: 式) を使用してテンプレートを作成すると、コードがより明確になり、読みやすくなり、コードの保守性が向上することを深く発見しました。これは、mvvm の中心となる概念である f(state) = view とより一致しています

一部のライブラリには、q などの文法パーサーさえありませんが、非常にうまく機能します。

それでは、複雑な操作をどこに配置するのでしょうか?

    変化しない値、つまり定数については、初期化前に処理が完了している必要があります
  • 変化する値については、フィルターに複雑な演算を入れることができるだけでなく。複雑な処理を他のフィールドに同時に適用することもできます。これは、jquery/zepto を使用する場合、$(document).on
  • の代わりに計算された属性

2.5.4 と完全に同等ではありません。 $(document).onの使用には慣れていますが、グローバルイベントプロキシとして機能するには、vueを使用する場合、zeptoを放棄する必要があるため、この問題を解決する必要があります

vueインスタンス自体にイベント機能があるため、解決策ここでは、グローバルな空の vue オブジェクトを作成し、それをグローバル イベント プロキシとして配置します:

1

2

3

4

5

6

7

8

9

Vue.noopVue = new Vue({});

//a.js

Vue.noopVue。 $on< /span>('someEvent', function

//b.js

Vue.noopVue.$emit( 'someEvent', [opts]);


3 まとめ

結局、コストと生産性のトレードオフの関係で既存プロジェクトの Vue 変換を断念しましたが、これによって mvvm クラス フレームワークの研究が妨げられるわけではありません

mvvm モードにはまだ価値があります

異なる種類の考え方や考え方で開発するという経験は、問題の見方や解決の仕方においても何かを得ることができます。

関連する推奨事項:

Angularjs で mvvm スタイルのタブを実装するにはどうすればよいですか? Case + code

シンプルな MVVM フレームワークの js 実装例の共有

MVVM アーキテクチャとデータ バインディングとは何ですか?

以上がVue実践まとめmvvm学習の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート