11. Record and summary of Xiaomi's interview questions

Self introduction and internship program

Keep alive principle

nextTick

What is nextTick?

A deferred callback is performed after the end of the next DOM update cycle. Use this method immediately after modifying the data to get the updated dom

The main function of nextTick is to let the callback function act on the updated DOM after updating the data

First understand an attribute
$el: get the DOM element associated with the Vue instance;

<template>
  <div class="home">
    <div id="example" @click="msgClick">{{message}}</div>
    <input type="text">
  </div>
</template>

<script>

export default {
  name: 'home',
  data() {
    return {
      message: '123'
    }
  },
  destroyed() {
    console.log('Component destroyed')
  },
  methods: {
    msgClick() {
      this.message = 'new message' // change data
      console.log(this.$el.innerHTML) // '123'
      this.$nextTick(function () {
      console.log(this.$el.innerHTML) // 'new message'
      })
    }
  }
}
</script>

Bind the click event on message. After the event is triggered, the data changes. At this time, use this n e x t T i c k of front and of after branch other hit print V u e real example shut Couplet of D O M element element of i n n e r H t m l , can with see reach stay send use t h i s . Print the innerHtml of the DOM element associated with the Vue instance before and after nextTick. You can see that this Print the innerHtml of the DOM element associated with the Vue instance before and after nextTick. You can see that this Its DOM has not been updated before nextTick

Why?

What is the update strategy for DOM in vue?

  1. vue updates the dom asynchronously
  2. As long as it listens for data changes, vue will open a new event queue and buffer all data changes in the same event loop
  3. If the same watcher is triggered multiple times, it will only be pushed into the event queue once
  4. Then, in the next event loop, vue refreshes the event queue and performs the actual work

In the above example

  1. We passed this Message = 'new message' update data
  2. But it won't re render immediately
  3. When the actual queue is refreshed, the component will be re rendered in the next event loop tick
  4. When we finish updating the data, we need to do something based on updating the dom state
    Vue.nextTick(callback)
  5. Put the operations required based on the updated dom state into the callback function, so that the callback function will be called after the dom update is completed

All right, here we go, vue What does nexttick (callback) do? Why should vue be set like this? Why should it be updated asynchronously

The operating mechanism of JS.

js execution is single threaded and based on event loops

An event loop is a process:

  1. Therefore, synchronization tasks run on the main thread to form an execution stack
  2. In addition to the main thread, there is also a task queue. As long as the asynchronous task has running results, an event will be placed in the task queue. Once all synchronous tasks in the execution stack have been executed, the system will read the task queue
  3. Those corresponding asynchronous tasks end the waiting state, enter the execution stack and start execution

The main thread repeats the above three steps continuously

The message queue stores tasks one by one. In the specification, tasks are divided into two categories: macro tasks and micro tasks. After each macro task is executed, all micro tasks in the micro task queue corresponding to the macro task must be emptied. Their execution order is as follows:

for (macroTask of macroTaskQueue) {
    // 1. Process the current macro task
    handleMacroTask();
      
    // 2. Process all corresponding micro tasks
    for (microTask of microTaskQueue) {
        handleMicroTask(microTask);
    }
}

In the browser environment, common

Macro tasks include setTimeout, MessageChannel, postMessage and setImmediate;
Micro tasks include mutationobserver and promise then.

The MutationObserver interface provides the ability to monitor changes to the DOM tree

nextTick source code analysis

nextTick source code is mainly divided into two parts:

  • Capability test
  • The callback queue is executed in different ways according to the capability detection

Vue internally attempts to use native promise. Com for asynchronous queues Then, MutationObserver and setImmediate. If the execution environment does not support it, setTimeout(fn, 0) will be used instead.

For the implementation of macro task, priority should be given to checking whether it supports native setImmediate, which is a feature only supported by higher versions of IE and Edge,
If not, check whether the native MessageChannel is supported,
If it is not supported, it will be downgraded to setTimeout 0;
For the implementation of micro task, check whether the browser supports Promise natively. If not, directly point to the implementation of macro task.
promise MutationObserver setImmediate setTimeout(flushCallbacks, 0)

if (typeof Promise !== 'undefined' && isNative(Promise)) {
  const p = Promise.resolve()
  timerFunc = () => {
    p.then(flushCallbacks)
    if (isIOS) setTimeout(noop)
  }
  isUsingMicroTask = true 
} else if (!isIE && typeof MutationObserver !== 'undefined' && (
  isNative(MutationObserver) ||
  MutationObserver.toString() === '[object MutationObserverConstructor]'
)) {
  let counter = 1
  const observer = new MutationObserver(flushCallbacks) 
  const textNode = document.createTextNode(String(counter))
  observer.observe(textNode, {
    characterData: true
  })
  timerFunc = () => {
    counter = (counter + 1) % 2
    textNode.data = String(counter)
  }
  isUsingMicroTask = true 
} else if (typeof setImmediate !== 'undefined' && isNative(setImmediate)) {
  timerFunc = () => {
    setImmediate(flushCallbacks)
  }
} else {
  timerFunc = () => {
    setTimeout(flushCallbacks, 0)
  }
}

nextTick

const callbacks = [] // Callback queue
let pending = false // Asynchronous lock

// Execute each callback in the queue
function flushCallbacks () {
  pending = false // Reset asynchronous lock
  // To prevent problems when nextTick occurs, copy and backup in advance and empty the callback function queue before executing the callback function queue
  const copies = callbacks.slice(0)
  callbacks.length = 0
  // Execute callback function queue
  for (let i = 0; i < copies.length; i++) {
    copies[i]()
  }
}

export function nextTick(cb?: Function, ctx?: Object) {
  let _resolve
  callbacks.push(() => {
    // Push callback function into callback queue
    if (cb) {
      try {
        cb.call(ctx)
      } catch (e) {
        handleError(e, ctx, 'nextTick')
      }
    } else if (_resolve) {
      _resolve(ctx)
    }
  })
    // If the asynchronous lock is not locked, lock the asynchronous lock, call the asynchronous function, and prepare to execute the callback function queue after the synchronous function is executed
  if (!pending) {
    pending = true
    timerFunc()
  }
  // $flow-disable-line
    // If no callback is provided and Promise is supported, a Promise is returned
  if (!cb && typeof Promise !== 'undefined') {
    return new Promise(resolve => {
      _resolve = resolve
    })
  }
}

How to ensure that asynchronous methods are executed only when the first callback function is received?

The concept of asynchronous lock is used in the nextTick source code, that is, when receiving the first callback function, close the lock first and execute the asynchronous method. At this point, the browser is waiting to execute asynchronous code after executing synchronous code.

Why do I need to back up the callback queue when I execute the flushCallbacks function? Is the callback function queue of backup also executed?

Because, there will be such a situation: nextTick is also used in the callback function of nextTick. If flushCallbacks does not do special processing and directly circulates the callback function, the callback function in nextTick will enter the callback queue.

When the a tag is switched to the b tag, the dom has not been updated, and then I re assign the value. At this time, vue may think that I have refreshed, and then stop on the b tag all the time.

Using nextTick means that after the dom of b tag is updated, I can change to a tag, and then I can.

How to realize login and registration

  • Registration:
  1. The front end makes a registration page first
  2. The front end needs to obtain the data after the user submits the data
  3. The front end sends the data obtained in the previous step to the server through a post request
  4. The back-end receives the request from the front-end and reads the required information (such as the mailbox password)
    Because when the client sends a post request to the server to transmit data, it is actually transmitted section by section, so the data cannot be obtained directly
  5. After receiving the data, the back-end performs a simple data verification. After an error occurs, the error information is returned to the front-end, which explains and displays it to the user. When the user submits without filling in the information, the front end needs to verify. In this case, the user should be prompted to fill in the information without sending a request to the back end again:
  6. After successful registration, the user data will be transferred to the database
  7. Backend verification: whether the mailbox is registered
  • Sign in:
  1. Write a login page at the front end
  2. The front end needs to get the login information written by the user and transfer it to the database, so it needs to do simple verification
  3. The backend validates user information from the database
  4. Back end setting cookie s
  5. The backend wants the corresponding user information through cookie s

Web storage cannot be used to store login information because it does not participate in the communication between client and server.

How many field properties do cookie s know

{
'name': 'QCARJSESSIONID', 
'value': 'DgH6ctvRhc1DGVvf0wp2x1pTLlV6Ltl8sgVQGhnCnNG32BFxnpP1!1426878101', 
'path': '/', 
'domain': 'qcar.apiins.com', 
'secure': False,    // Field to set whether this cookie can only be passed through https
'httpOnly': True
}

The SameSite property of cookies is used to restrict third-party cookies, thereby reducing security risks.

It can set three values.

Strict
Lax
None

Set it to None. However, the premise is that the Secure attribute must be set at the same time (cookies can only be sent through HTTPS protocol), otherwise it is invalid.

Parent to child (multi-layer) method

  • vuex

  • eventBus
    Based on a message center, subscribe and publish messages and publish subscriber mode
    on('name ', fn) subscription Name: the name of the subscribed message, fn: the subscribed message
    emit('name,arg) publish message, name: publish message name, args: publish message
    Implement a publish subscribe pattern

class Bus {
    constructor() {
        this.callback = {}
    }
    on(name, fn) {
        this.callback[name] = this.callback[name] || []
        this.callback[name].push(fn)
    }
    emit(name, args) {
        if (this.callback[name]) {
            this.callback[name].forEach(cb => cb(args));
        }
    }
}

const EventBus = new Bus()
EventBus.on('f1', function (msg) {
    console.log(`The subscribed message is: ${msg}`)
})
EventBus.emit('f1','Hello, family')
  • provide inject
    Parent:
 provide: {
    // The parent component uses provide to provide parameters
    uname: "Passed by parent component uname",
  },

Sub:

<template>
  <div>
    Data received by subcomponents:{{uname}}
    <child2></child2>
  </div>
</template>
<script>
import child2 from "./child2";

export default {
  name: "childInject1",
  components: {
    child2,
  },
  data() {
    return {};
  },
  inject: ["uname"]
};
</script>

Sun:

<template>
  <div>
    Data received by grandson component:{{foo}}
    <p>{{arr}}-{{typeof(arr)}}</p>
  </div>
</template>
<script>
export default {
  name: "childInject2",
  data() {
    return {
      // uname:this.uname
    };
  },
  inject: {
    foo: {
      //You can change your name
      from: "uname", //The property name obtained from its parent component
      default: "foo", //2.5.0 + you can use default. Just like props, you can set the default value and make it optional
    },
    arr: {
      from: "arr", //Display default value if not received
      default: () => [1, 2, 3, 4, 5],
    },
  }
};
</script>

Prototype chain inheritance

Disadvantages of instanceof detection

Strong cache and negotiation cache

  • cache
  1. After obtaining the resource for the first time, tell how to cache the resource according to the returned information
  • The strong cache does not contain http requests
    The first request time of the cache control resource and the validity period set by cache control calculate a resource expiration time, and then compare the expiration time with the current request time. If the request time is before the expiration time, it can hit the cache, otherwise it will not work
    No cache: negotiation is used instead of local cache
    Store: direct cache prohibited
    public: all browsers can
    private: only terminal browsers can
    expires an event point

Both exist: cache control

  • If there is no name clearing cache in the negotiation cache 304, the browser will send a request to the server

Determine whether resources are available
Response header from the server: last modified Etag

  • last-modified if-modified-since
  1. The browser requests a resource from the server for the first time. When the server returns the resource, it adds the last modified header to the corresponding header. This header indicates the last modification time of the resource on the server

  2. When the browser requests this resource from the server again, add the if modified since header to the request header. The value of this header is the last modified value returned in the last request

  3. When the server receives the resource request again, it determines whether the resource has changed according to the if modified since transmitted by the browser and the last modification time of the resource on the server. If there is no change, 304 Not Modified is returned, but the resource content will not be returned; If there is any change, the resource content is returned normally. When the server returns a 304 Not Modified response, the last modified header will not be added to the response header, because since the resources have not changed, the last modified header will not change. This is the response header when the server returns 304

  4. After the browser receives the response from 304, it will load resources from the cache

  5. If the negotiation cache fails to hit, when the browser loads resources directly from the server, the last modified Header will be updated when it is reloaded. If modified since will enable the last modified value returned the next time

  • etag if-none-match
    As long as resources change, this value will change;
    If it hits, the server returns a new response header information to update the corresponding header information in the cache, but does not return the resource content. It will tell the browser that it can get it directly from the cache; Otherwise, the latest resource content is returned

Last modified and ETag can be used together. The server will first verify the ETag. If it is consistent, the comparison will continue. Finally, it will decide whether to return 304.

  • How to avoid the change of server-side resources during strong cache period

By updating the resource path referenced in the page, the browser can actively abandon the cache and load new resources.

Temporary deadband of let

The sum of two numbers cannot be solved violently

Keywords: Front-end Interview

Added by s_r_elliott on Sat, 15 Jan 2022 09:39:32 +0200