The expansion of the Vue

1, Vue is how to achieve two-way data binding

1.1, two-way binding basic principles

vue achieve two-way data binding is mainly used data hijacking combination publisher - subscriber mode approach.

Data is hijacked by Object.defineProperty () implementation, this function adds setter for each property, getter method, when data changes setter method will be triggered, and then publish messages to subscribers, triggering the appropriate listener callback. When the object is passed to a common Javascript Vue instance as its data option, Vue will traverse its properties, add setter, getter Object.defineProperty the method for each attribute.

vue two-way data binding is accomplished by three main modules: the observer Observer, subscribers Watcher, Compile command parsing template.

(1) Observer monitor changes in the data model, if there are changes, notify subscribers

(2) the initial page rendering, the node binding function: Compile by scanning and parsing instructions each associated node, replaces the variables into the template data, and render the page view of the initial data. And the function of each instruction corresponding node binding function, once view interactive binding is triggered, then the trigger setter method, subscribers will be notified.

(3) watcher put up a bridge of communication between the observer and Compile, to achieve data changes -> View update, view interactive changes (input) -> two-way binding effect change data model occurs.

var vm = new Vue({ 
  data: { 
    obj: { a: 1 } 
  }, 
  created: function () { 
    console.log(this.obj); 
  }
 });

Vue print data in the instance of a certain attribute data, we can see that the property contains a setter, getter method, which can be learned, each property have been added setter, getter method.

 

Mvvm achieved mainly consists of two aspects, the data update changes the view, the view changes to update the data:

view update data through an event listener that is, such as input label listen 'input' events can be achieved. The key point is how to update the View data, when the data changes, how to update the view. Focusing on how to know the data has changed, and this can be achieved by the Observer, by Object.defineProperty () on the property of a set function, when the data will be changed to trigger this function, then as long as the methods need to be updated in view of this can be achieved inside view of the updated data.

 

1.2, observe implementation

 Use Obeject.defineProperty () to add a setter for each property, getter methods achieve listen properties change. The need to observe the data objects recursively traverse, including sub-properties of the object attributes, plus both setter and getter, so, assign a value to this object, it will trigger setter, so you can listen to the data changes. Sample code:

 

var Data = { 
    name: 'kindeng' 
  }; 
  the observe (Data); 
  data.name = 'DMQ'; // ha, listening to a value changed kindeng -> DMQ 
  function the observe (Data) {
     IF (Data |! | typeof ! Data == 'Object' ) {
       return ; 
    } 
    // remove all attributes traverse 
    Object.keys (Data) .forEach ( function (Key) { 
      defineReactive (Data, Key, Data [Key]); 
    }); 
  } ; 

  function defineReactive (Data, Key, Val) { 
    the observe (Val); // monitor sub-attribute
    Object.defineProperty (Data, Key, { 
      Enumerable: to true , // enumerable 
      Configurable: to false , // no longer DEFINE 
      GET: function () {
         return Val; 
      }, 
      SET: function (newVal) { 
        the console.log ( ' ha, to monitor the changes in value of ', Val,' -> ' , newVal); 
        Val = newVal; 
      } 
    }); 
  }

Listen can be achieved for each attribute by the above code.

 

 1.3, to achieve a simple two-way binding by JS

<body>
    <div id="app">
    <input type="text" id="txt">
    <p id="show"></p>
</div>
</body>
<script type="text/javascript">
    var obj = {}
    Object.defineProperty(obj, 'txt', {
        get: function () {
            return obj
        },
        set: function (newValue) {
            document.getElementById('txt').value = newValue
            document.getElementById('show').innerHTML = newValue
        }
    })
    document.addEventListener('keyup', function (e) {
        obj.txt = e.target.value
    })
</script>

In the above code, is first added defineProperty getter, setter methods for each property, when the data changes, the setter method is invoked, the view is also changed. setter inside the command execution can be seen as a subscriber Watcher, connect and view data up. Code for the lowermost node binding action can be seen as a method of Compile, instruction node binding method, when the view interaction occurs, the function is triggered, the data is changed, Watcher notified, the view will change.

 

 2, the browser page rendering process

 

(Browser rendering engine rendering process)

2.1, rendering critical path

The key rendering path refers to HTML, CSS, javascript and other resources from the first browser request is received, and then parse tree building, rendering the layout, drawing, and finally presented to interface the customer can see the whole process.

So the browser's rendering process includes the following steps:

  1. Parsing HTML DOM tree is generated.
  2. CSS parsing rule generating CSSOM tree.
  3. The DOM tree to tree CSSOM rules are combined to generate the render tree.
  4. Render tree traversal starts layout calculates the position information of each node size.
  5. Each node will render tree drawn to the screen.

 

 3, JS real cost of operating the DOM!

When using our traditional development model, native JS JQ operation or DOM, the browser will start again from beginning to end execution flow generated from the DOM tree. In one operation, I need to update the DOM node 10, after receiving the first browser DOM requests do not know 9 update operation, and therefore the implementation process immediately and eventually executed 10 times. For example, the first complete calculation, followed by a DOM next update request, the node coordinate values ​​had changed, the previous evaluation time is wasted effort. Calculating coordinate values ​​are all DOM node performance wasted. Even if the computer hardware has been an iterative update, manipulate the DOM price is still expensive, frequent operation or page will appear Caton, affecting the user experience.

 

4、虚拟DOM的作用

虚拟DOM就是为了解决浏览器性能问题而被设计出来的。假如像上面所说的,若一次操作中有10次更新DOM的动作,会生成一个新的虚拟DOM,将新的虚拟DOM和旧的进行比较,然后将10次更新的 diff 内容保存到一个JS对象中,最终通过这个JS对象来更新真实DOM,由此只进行了一次操作真实DOM,避免大量无谓的计算量。所以,虚拟DOM的作用是将多个DOM操作合并成一个,并且将DOM操作先全部反映在JS对象中(操作内存中的JS对象比操作DOM的速度要更快),再将最终的JS对象映射成真实的DOM,交由浏览器去绘制。

 

5、实现虚拟DOM

虚拟DOM就是是用JS对象来代表节点,每次渲染都会生成一个VNode。当数据发生改变时,生成一个新的的VNode,通过 diff 算法和上一次渲染时用的VNode进行对比,生成一个对象记录差异,然后根据该对象来更新真实的DOM。原本要操作的DOM在vue这边还是要操作的,不过是统一计算出所有变化后统一更新一次DOM,进行浏览器DOM的一次性更新。

 

 参考:https://baijiahao.baidu.com/s?id=1593097105869520145&wfr=spider&for=pchttps://www.jianshu.com/p/af0b398602bc

 

6、Vue 中路由的hash模式和history模式

Vue 中路由有 hash 模式和 history 模式,hash 模式带 # 号,history 没有这个 # 号,就是普通的 url 。可以通过在 router 中配置 mode 选项来切换模式。

Vue 中的路由是怎么实现的可以参考:https://segmentfault.com/a/1190000011967786

Vue 中路由的实现是通过监听 url 的改变,然后通过解析 url ,匹配上对应的组件进行渲染实现的。

在 hash 模式下,跳转路由导致后面 hash 值的变化,但这并不会导致浏览器向服务器发出请求。另外每次 hash 值的变化,还会触发 hashchange 这个事件,通过监听这个事件就能知道 hash 值的改变,并能解析出 url。在 hash 模式下,刷新页面和直接输入链接都不会导致浏览器发出请求。

history 模式的实现原理是通过HTML5中的两个方法:pushState 和 replaceState,这两个方法可以改变 url 地址且不会发送请求,由此可以跳转路由而不刷新页面,不发出请求。但是在 history 模式下,用户如果直接输入链接或者手动刷新时,浏览器还是会发出请求,而会导致服务器寻找该 url 路径下的对应的文件,而该路径下的文件往往不存在,所以会返回 404。为了避免这种情况,在使用 history 模式时,需要后端进行配合使用,配置在URL 匹配不到任何静态资源返回什么东西,比如可以配置在找不到文件时返回项目的主页面。

 参考:https://segmentfault.com/a/1190000011967786https://www.cnblogs.com/xufeimei/p/10745353.html

 

Guess you like

Origin www.cnblogs.com/wenxuehai/p/11300621.html