> 웹 프론트엔드 > JS 튜토리얼 > Vue 실습 요약 mvvm 학습

Vue 실습 요약 mvvm 학습

小云云
풀어 주다: 2018-03-12 16:37:14
원래의
1321명이 탐색했습니다.

MVVM은 Model-View-ViewModel의 약어입니다. Microsoft의 WPF는 새로운 기술 경험을 제공합니다. 이 기사에서는 주로 vue 연습 및 mvvm 학습 요약을 공유하여 모든 사람에게 도움이 되기를 바랍니다.

1 mvvm 학습

1.1 구현 원리

mvvm 클래스 프레임워크의 구현 원리는 대략 다음과 같이 복잡하지 않습니다.

  • 종속 속성을 얻기 위한 템플릿 분석

  • 일종의 변경을 통해 이러한 종속 속성을 모니터링합니다. 모니터링 방법

  • 속성이 변경되면 해당 지시문 처리 로직을 트리거하기만 하면 됩니다

사실 지시문 처리 로직이 반드시 보고 등의 뷰를 동작시키는 것은 아닙니다. 하지만 mv 아이디어 하에서는 뷰에 대한 모든 작업을 지시문에 집중하는 것이 좋습니다

핵심 관점에서 볼 때 mv 아이디어는 관찰자 패턴의 특정 응용 프로그램 확장일 뿐입니다

1.2 핵심 기술 포인트

1.2.1 템플릿 분석

템플릿 분석은 기본적으로 템플릿과 관련된 것입니다. 임의의 문자여야 합니다.

이는 프레임워크에 템플릿 파서가 필요하다는 것을 의미합니다. 파서가 복잡하든 단순하든 관계없이 [입력 –> 템플릿 엔진 –> 출력]

그래서 mvvm의 템플릿 파서 특징은 다음과 같습니다. :

  • 입력: 규칙을 준수하는 모든 문자열

  • 출력: data.attr, 지시어, 모니터링해야 하는 필터

프레임워크를 설계할 때, if 더 나은 확장성을 원하면

입력은 소스 측면에서 충분히 유연해야 하며, 엔진이 고급 기능을 인식할 수 있는 경우 콘텐츠 측면에서 더 적용 가능한 someDomHere.html()이 될 수 있습니다. 구문을 사용하면 더 기능적입니다

수렴은 제한된 통합 규칙을 의미합니다. mvvm 프레임워크와 마찬가지로 마지막으로 나오는 것은 이 두 가지 개념에만 집중됩니다. 이 두 개념은 시스템을 확장하는 데 사용할 수 있습니다.

1.2.2 변경 모니터링

많은 mvvm 클래스 프레임워크에는 세 가지 유형의 변경 모니터링이 있습니다.

  1. Facade 메서드 setter, getter: 녹아웃, q. 변경할 수 있는 출입구를 제한하고, 출입구 사용 방법은 사용자가 결정하도록 하세요.

  2. defineProperty를 사용하세요: vue, avalon 등. 본질적으로 세터이자 게터이기도 하지만, 입구를 사용할 권한을 사용자에게 결정하도록 맡기지 않습니다.

  3. 더티 검사: 각도 등. Angular에 대한 연구가 충분히 있으므로 여기서는 자세히 다루지 않겠습니다. ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ

    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>
로그인 후 복사

1.2.3 요약 및 확장

일종의 복잡하고 일반적인 문제를 분석하고 분리하고 추상화하면 실제로 널리 인식될 때 mvvm도 모델이 됩니다. , 이는 작성자가 결정할 수 있는 사항이 아니며 이 모드의 핵심과 관련하여 작성자는 다음을 이해합니다. 시스템은 구성에 따라 특정 데이터 소스에 대한 특정 처리 규칙을 얻고 데이터 소스가 변경되면 트리거됩니다. 해당 응답 처리 규칙. 스키마 확장은 시스템 구현에 따라 결정되는 양방향입니다. 특정 규칙이 충족되면 데이터 소스가 업데이트될 수 있습니다.

우리는 뷰의 개념에서 벗어나 레노버의 모니터링 시스템을 구현했습니다. 실제로 이 모델은 모니터링 시스템에 사용하기에 매우 적합합니다.

일반 모니터링 시스템의 처리 로직은 수집 소스가 모니터링 데이터를 수집 및 정리한 후 데이터베이스에 저장하는 것입니다. 모니터링 시스템은 데이터 소스를 실시간으로 모니터링하고 실시간 그래프(피드백)를 작성합니다. 데이터 소스가 특정 규칙을 충족하면 이러한 규칙이 변경되면 경보와 같은 해당 작업이 트리거됩니다.

이 시스템을 구현하고 시스템의 확장성을 높이는 방법은 무엇입니까? mvvm 모드를 언급하면 ​​다음과 같을 수 있습니다.

수집 시스템은 모니터링 시스템과 독립적이며 다르므로 지금은 걱정하지 마세요. 모니터링 시스템은 특정 구성 파일을 통해 모니터링해야 하는 데이터 소스와 해당 처리 논리 규칙을 얻고, 데이터 소스가 변경되면 해당 처리를 트리거합니다.

mvvm 패턴을 따르고 몇 가지 추상화를 만드세요.

    데이터 소스는 반드시 데이터베이스로 제한되지 않고 어디에나 있을 수 있으며 특정 구성 가능한 규칙을 통해서만 시스템에서 가져오면 됩니다.
  • 처리 규칙은 확장하기 쉽도록 추상화됩니다. 이메일 보내기, 문자 메시지 보내기, WeChat 보내기, QQ 메시지 보내기 등
  • 은 프런트 엔드 mvvm 프레임워크에 해당하고 템플릿은 구성 파일, 지시문은 처리 규칙, 데이터는 데이터에 해당합니다. 원천.

    시스템에서 새 데이터 소스를 추가해야 하는 경우 구성 파일을 업데이트하고 시스템에서 이를 읽어 데이터 모니터링을 시작하기만 하면 됩니다.
  • 처리 규칙을 추가해야 하는 경우 다음을 사용할 수 있습니다. 핫 플러그 ​​처리 규칙 플러그인 시스템, 새로운 처리 규칙을 확장한 다음 구성 파일을 업데이트하면 시스템이 새로운 처리 규칙을 수락할 수 있습니다.
  • 2 vue practice

vue 소개는 필요하지 않으며 리소스가 너무 많습니다. 다음은 vue

2.1 조직 구조

1+ src

2

3

4

5

6

7

8

9을 통해 얻은 몇 가지 이점입니다.

10

11

12

13

14

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

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를 통해 동일한 이벤트를 등록하는 것은 쉽습니다. 또 다른 문제는 이벤트가 50개 또는 100개 이하로 많지 않으면 많은 메모리를 소비하지 않으므로 때로는 이벤트 에이전트가 실제로 필요하지 않다는 것입니다. 꼭 필요하다면 콘테이너 메소드만 구현하세요

2.5.2 if-else에는 이상함이 없습니다

다음 코드를 처음 보면 정말 이상할 겁니다

1

2

3

if="hasTitle">xxx

if="!hasTitle">xxx

2.5.3 단일 값

Vue에는 지시문의 값에 표현식을 사용할 수 있는 구문 분석기가 있지만 복잡한 표현식이 나타나면 템플릿을 오염시키고 코드를 읽기 쉽게 만듭니다. 좋지 않거나 표현이 작업을 완료할 수 없는 경우.

따라서 mvvm을 연습하면서 저는 단일 값(최대 1개의 ?: 표현식)을 사용하여 템플릿을 작성하면 코드가 더 명확해지고 가독성이 높아지며 코드의 유지 관리 가능성이 높아진다는 사실을 깊이 발견했습니다. mvvm의 핵심 아이디어인 f(state) = view

에 더 가깝습니다. 일부 라이브러리에는 q와 같은 문법 파서조차 없지만 매우 잘 작동할 수 있습니다.

그럼 복잡한 연산은 어디에 넣어야 할까요?

  • 변경되지 않는 값, 즉 상수에 대해서는 초기화 전에 처리가 완료되어야 합니다.

  • 변경되는 값에 대해서는 복잡한 연산을 필터에 넣을 수 있을 뿐만 아니라. 복잡한 처리를 동시에 다른 필드에 적용할 수도 있습니다. 이는 $(document).on

  • 대신 계산된 속성

2.5.4과 완전히 동일하지 않습니다. $(document).on을 사용하는데 익숙합니다. 전역 이벤트 프록시로 작동하려면 vue를 사용할 때 zepto를 포기해야 하므로 이 문제를 해결해야 합니다

vue 인스턴스 자체에 이벤트 기능이 있기 때문에 해결책은 다음과 같습니다. 여기에는 전역 빈 vue 개체를 만들고 전역 이벤트 프록시로 넣는 것입니다.

Vue.noopVue = new Vue({});

//a.js

Vue.noopVue. $on< /span>('someEvent', 함수

//b.js

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


3 요약

결국 비용 대비 출력 비율 균형을 위해 기존 프로젝트의 Vue 변환을 포기했지만 이것이 mvvm 클래스 프레임워크를 연구하는 데 방해가 되는 것은 아닙니다

mvvm 모드는 여전히 가치가 있습니다

다양한 생각과 생각으로 발전하는 경험은 문제를 바라보고 해결하는 방식에서도 뭔가를 얻게 해줄 것입니다.

관련 권장 사항:

Angularjs에서 mvvm 스타일 탭을 구현하는 방법은 무엇입니까? 케이스 + 코드

js로 구현한 간단한 MVVM 프레임워크 예제 공유

MVVM 아키텍처와 데이터 바인딩이란 무엇인가요?

위 내용은 Vue 실습 요약 mvvm 학습의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿