InitProxy Initializes the proxy

In the SRC/core/instance/proxy. Js to find the source code

MakeMap, allowedGlobals

Let’s take a look at the makeMap method and see what it does:

/* The makeMap function, STR arguments are accepted as strings, expectercase arguments need to be lowercase */
 function makeMap(str, expectsLowerCase ) {
  /* Create an object */
  var map = Object.create(null);
  /* Splits the string into arrays */
  var list = str.split(', ');
  /* Traverses the array */
  for (var i = 0; i < list.length; i++) {
     /* Set each key to true*/
     map[list[i]] = true;
  }
  /* Finally returns, depending on whether the parameter Settings need to convert case */
  return expectsLowerCase
       ? function (val) {
          return map[val.toLowerCase()];
       }
       : function (val) {
          returnmap[val]; }}Copy the code

Then give some js built-in global methods to do the corresponding processing:

var allowedGlobals = makeMap(
    'Infinity,undefined,NaN,isFinite,isNaN,' +
    'parseFloat,parseInt,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,' +
    'Math,Number,Date,Array,Object,Boolean,String,RegExp,Map,Set,JSON,Intl,' +
    'require' // for Webpack/Browserify
);
Copy the code

The makeMap function converts these global apis into the following form,

{
    Infinity:true.undefined:true
}
Copy the code

isNative

How does the source code check to see if native methods are supported

export function isNative (Ctor: any) :boolean {
  return typeof Ctor === 'function' && /native code/.test(Ctor.toString())
}
Copy the code

warnNonPresent

This method means that there is no undefined attribute, and the method is used to give a warning. Let’s look at an example:

<! DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, "> <title>Document</title> </head> <body> <script SRC =".. /vue.js"></script> <div id="app"> <p> {{msg}} </p> </div> <script> const vm = new Vue({ el: '#app', }) console.log(vm) </script> </body> </html>Copy the code

The above example uses the MSG variable directly in the magic board, but it is not defined in data. In this case, warnNonPresent will handle the warning as shown in the figure

warnReservedPrefix

The source code is as follows:

const warnReservedPrefix = (target, key) = > {
    warn(
      `Property "${key}" must be accessed with "$data.${key}" because ` +
      'properties starting with "$" or "_" are not proxied in the Vue instance to ' +
      'prevent conflicts with Vue internals. ' +
      'See: https://vuejs.org/v2/api/#data',
      target
    )
  }
Copy the code

The declaration method used to check whether the key attribute starts with $or _, and if so, will give a warning. Here’s a simple example:

<! DOCTYPEhtml>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="Width = device - width, initial - scale = 1.0">
    <title>Document</title>
</head>

<body>
    <script src=".. /vue.js"></script>
    <div id="app">
        <p>
            {{$hhh}}
            {{_dddd}}
        </p>
    </div>
    <script>
        const vm = new Vue({
            el: '#app'.data() {
                return {
                    $hhh: 'ddd'._dddd: 'ffff'}}})console.log(vm)
    </script>
</body>

</html>
Copy the code

hasHandler

var hasHandler = {
    /*target Specifies the object to proide. Key specifies the property to access when operating externally
    has: function has(target, key) {
        /*key in target returns true or false*/
        var has = key in target;
        /* In the template engine, there are attributes that the VM does not delegate, but can use, such as Number,Object, etc. */
        var isAllowed = allowedGlobals(key) ||
            (typeof key === 'string' && key.charAt(0) = = ='_' && !(key in target.$data));
        /* When has and isAllowed are false above */
        if(! has && ! isAllowed) {if (key in target.$data) {
                warnReservedPrefix(target, key);
            }
            /* The warnNonPresent function will report an error */ when accessing attributes that do not exist on the VM instance
            else{ warnNonPresent(target, key); }}/ * has or isAllowed * /
        returnhas || ! isAllowed } };Copy the code

HasHandler is only configured with the HAS hook function, which is triggered when propKey in proxy in or with() is performed

When a hasHandler looks for a key, it looks in three directions

  • The agent’s target object passes through the IN operator
  • The global object API allowedGlobals function
  • Typeof key === ‘string’ && key.charat (0) === ‘_’ typeof Key === ‘string’ && key.charat (0) === ‘_’

HasHandler, first to check whether the vm instance has this property, the following code on the VM instance can see test

new Vue({
   el:"#app".template:"<div>{{test}}</div>".data:{
       test
   }
})
Copy the code

If it is not found on the VM instance, then check whether it is some global object, such as Number, etc. Number is provided by the language and can be used in the template

new Vue({
   el:"#app"./*Number belongs to the global API provided by the language */
   template:"<div> {{ Number(test) +1 }}</div>".data:{
       test
   }
})
Copy the code

getHandler

const getHandler = {
    get(target, key) {
      if (typeof key === 'string' && !(key in target)) {
        // Check whether data is the attribute key and whether it starts with $,_
        if (key in target.$data) warnReservedPrefix(target, key)
        else warnNonPresent(target, key)
      }
      return target[key]
    }
}
Copy the code

initProxy

initProxy = function initProxy(vm) {
/*hasProxy determines whether the current environment supports Proxy*/ provided by ES
if (hasProxy) {
   // determine which proxy handler to use
   var options = vm.$options;
   Handlers, getHandler or hasHandler */
   var handlers = options.render && options.render._withStripped
       ? getHandler
       : hasHandler;
   /* Proxy VM instance */
   vm._renderProxy = new Proxy(vm, handlers);
} else{ vm._renderProxy = vm; }};Copy the code