1. Advantages of Vue? Vue’s weakness?
Benefits: Progressive, componentized, lightweight, virtual DOM, responsive, single-page routing, data and view separation (MVVM model)
Disadvantages: Single page is not conducive to SEO, does not support Internet Explorer 8 or lower, and takes a long time to load on the first screen
2. What is MVVM? How is it different from MVC?
MVC
- Model: Is responsible for fetching data from the database
- View: The place responsible for displaying data
- Controller: a place where users interact, for example
Click on the event
, etc. - Idea: The Controller displays the Model’s data on the View
MVVM
- VM, or View-Model, does two things to achieve bidirectional binding of data. One is to convert the [Model] into the [View], which is to convert the data passed from the back end into the page you see. This is done by data binding. The second is to transform [view] into [model], that is, to see the page into back-end data. This is done by DOM event listening.
- Idea: Automatic synchronization of View and Model is realized, that is, when the attributes of Model change, we no longer need to manually manipulate Dom elements to change the display of View, but after changing the attributes, the corresponding View layer display will automatically change (corresponding to Vue data-driven idea).
The difference between
Overall, MVVM is much simpler than MVC. It not only simplifies business and interface dependencies, but also solves the problem of frequent data updates, eliminating the need to manipulate DOM elements with selectors. Because in MVVM, the View is unaware of the Existence of the Model, and the Model and ViewModel cannot observe the View, this low-coupling pattern improves code reusability
Is Vue the MVVM framework?
Vue is an MVVM framework, but it is not strictly MVVM compliant because MVVM dictates that the Model and View cannot communicate directly, whereas Vue’s ref does
3. What Vue modifiers are used in Vue?
<el-pagination :total="total" :page-size.sync="pageSize" v-bind="$attrs"/> <el-pagination :total="total" :page-size.sync="pageSize" v-bind="$attrs"/>Copy the code
.sync
The.sync modifier enables bidirectional binding of a child component to its parent, and allows the child component to synchronize the value of the parent component.
<body> <div id="app"> {{dataApp}} <hr> // Use double tags when using multiple components,</> This form can display only one <Child :money.sync="dataApp"> </Child> <! <Child :money="dataApp" V-on: Update :money=" $event"> </Child> </div> </body> <script> Vue.component('Child', { props: ['money'], template: ` <div class="child"> {{ money }} <button @click="$emit('update:money', </button> </div > '}) var vm = new Vue({el: '#app', data: {dataApp: },}) </script> // Note here that our event name is changed to update:money //update: is fixed, is the name part of the vUE conventionCopy the code
‘:’ and ‘@’ in Vue
- : SRC =”url” is short for V-bind: SRC =”url”
- @click = “something” is short for V-on :click = “something”
4. What internal Vue instructions have you used?
5. What are the ways of transferring values between components?
Common usage scenarios can be divided into three categories:
- Parent-child component communication:
props
;$parent
/$children
;provide
/inject
;ref
;$attrs
/$listeners
- Sibling communication:
eventBus
; vuex - Cross-level communication:
eventBus
; Vuex;provide
/inject
、$attrs
/$listeners
<body>
<div id="app">
<father :v1="'value1'" :v2="'value2'" :v3="'value3'"></father>
</div>
</body>
<script>
Vue.component('father', {
// inheritAttrs: false,
props: ['v1'],
template: `
<div>
<p>v1 is {{v1}}</p>
<son v-bind='$attrs'></son>
</div>
`
})
Vue.component('son', {
props: ['v2'],
template: "<div ><p>v2 is {{v2}}</p><grandSon v-bind='$attrs'></grandSon></div>"
})
Vue.component('grandSon', {
props: ['v3'],
template: "<p>v3 is {{v3}}</p>"
})
let vm = new Vue({
el: '#app',
data: {
},
})
</script>
Copy the code
For more information: juejin.cn/post/684490…
6. What does a key in a Vue really do?
Key is the unique ID given to each Vnode. Dom operation can be updated more accurately and quickly by means of diff algorithm based on key. When data changes, setter will be triggered and all subscribers Watcher will be notified through DEP. notify, and they will call patch method
Why do you need the virtual DOM?
The virtual DOM was designed to address browser performance issues. For example, if there are 10 DOM updates in a single operation, the virtual DOM does not immediately manipulate the DOM. Instead, the virtual DOM stores the diff content of the 10 updates to a local JS object, and finally attches the JS object to the DOM tree for subsequent operations to avoid a lot of unnecessary computation. To put it simply, the Virtual DOM can be understood as a simple JS object, and it contains at least three attributes: tag, attrs and children.
As an example, look at the following real DOM:
< ul id = "list" > < li class = "item" > haha < / li > < li class = "item" > haha < / li > < li class = "item" > hey hey < / li > < / ul > duplicate codeCopy the code
The corresponding virtual DOM is:
Let oldVDOM = {// old virtual DOM tagName: 'ul', // props: {// Tag attribute id: 'list'}, children: [// tag child {tagName: 'li', props: {class: 'item'}, children: [' haha ']}, {tagName: 'li', props: {class: 'item'}, children: [' ha ha ']}, {tagName: 'li', props: {class: 'item'}, children: [' hey ']},]}Copy the code
Note: it is not recommended to use index as the key in v-for loop rendering, which will cause nodes that do not need to be updated to update the Diff algorithm: Only Diff between vnodes of the same class, recursively Diff between vnodes of the same class, and finally update the whole DOM tree (breadth-first algorithm).
For more information: juejin.cn/post/699495…
7. Talk about how nextTick works?
The Vue implementation is responsive, not that the DOM changes immediately after the data changes, but that the DOM is updated according to a certain strategy.
For example
When vm.message = ‘changed’ is set, the component does not immediately rerender.
This is where the DOM update strategy is involved in the Vue, which updates the DOM asynchronously. Whenever it listens for data changes, Vue opens an event queue and buffers all data changes that occur in the same event loop. If the same Watcher is fired more than once, it will only be pushed into the event queue once. This removal of duplicate data while buffering is important to avoid unnecessary computation and DOM manipulation. Then, in the next event loop, “TICK,” Vue refreshes the event queue and performs the actual (de-duplicated) work.
In the example above, when we update the data with vm.message = ‘new message’, the component does not immediately rerender. When the event queue is refreshed, the component is re-rendered in the next event loop “TICK”. NextTick (callback) is a callback function that performs operations based on the updated DOM state. This callback will be called after the DOM update is complete.
OK, now you should know what nextTick is, which begs the question, why did Vue design this way? Why update the DOM asynchronously? This brings us to another piece of knowledge: how JS works
For more information: juejin.cn/post/700438…
8. What is the difference between hash mode and history mode in vue-router?
Vue-router is a default hash mode. When you create a project using vue-CLI, Use history mode for router? Use history mode to create routes
Difference between hash mode and history mode
The most obvious difference is that hash has an ugly # in the URL, while history has no #
For a progressive front-end development framework like VUE, in order to build SPA (single-page application), it is necessary to introduce a front-end routing system, which is the significance of vuE-Router. That’s the core of front-end routing — changing the view without making a request to the back end.
To achieve this, browsers currently provide the following two types of support:
- Hash — the # symbol in the URL of the address bar (this hash is not a cryptographic hash). For example, the URL: www.abc.com/#/hello hash value is #/hello.
The trick is that the hash, while present in the URL, is not included in the HTTP request and has no impact on the back end, so changing the hash does not reload the page.
- History – Takes advantage of the new pushState() and replaceState() methods in the HTML5 History Interface. (Browser-specific support required) These two methods apply to the browser’s history stack and provide the ability to modify the history in addition to the existing back, Forward, and Go methods. It’s just that when they make changes that change the current URL, the browser doesn’t immediately send requests to the back end.
Therefore, both hash and history modes are browser features, and vue-Router only uses these two features (by calling the interface provided by the browser) to implement front-end routing.
Usage scenarios
In general, hash and history will work, unless you’re more concerned with the appearance level, and the # symbol does look a little ugly in the URL.
If you don’t want ugly hashes, you can use the history mode of the route, which takes full advantage of the history.pushState API to do URL jumps without reloading the page.
In addition, calling history.pushState() has the following advantages over modifying hash directly, according to Mozilla Develop Network:
-
- PushState () sets the new URL to any URL of the same origin as the current URL; Hash can only change the part after #, so you can only set the URL of the same document as the current URL.
-
- PushState () sets the new URL to be exactly the same as the current URL, which also adds the record to the stack; The new hash value must be different to trigger the action to add the record to the stack;
-
- PushState () uses the stateObject argument to add any type of data to a record; Hash can only add short strings;
-
- PushState () sets the title property in addition for later use.
Of course, history isn’t all good. SPA works fine in a browser, but when it comes to making an HTTP request to the back end of a URL, the difference comes. This is especially true when the user manually enters the URL and hits the press enter, or when the browser is refreshed (or restarted).
conclusion
1 In hash mode, only the content before the hash symbol is included in the request, for example, www.abc.com. Therefore, the back end does not return a 404 error even if the route is not fully covered.
2 In history mode, the URL of the front end must be the same as the ACTUAL URL of the back end. For example, www.abc.com/book/id If the back end does not process /book/ ID routes, a 404 error is displayed. Vue-router Router Router Router Router Router Router Router Router
“But this mode to play well, also need to support the background configuration… So, you add a candidate resource on the server that covers all cases: if the URL doesn’t match any static resource, it should return the same index.html page that your app depends on.”
Examples of back-end configuration with nginx:
location / {
try_files $uri $uri/ /index.html;
}
Copy the code
Nginx configuration steps: www.cnblogs.com/jedi1995/p/…
3 combined with their own examples, for general Web development scenarios in the form of Vue + VUe-Router + Webpack + XXX, use the history mode, just need to do simple routing configuration in the back end (Apache or Nginx). 404 page support with front-end routing.
9. How do I update arrays in VUE?
Array native methods
Array.prototype.splice
Called the most powerful method of arrays, it has delete, add, replace functions, and can be updated with splice
Why can Splice trigger updates?
Vue wraps the change methods on the array (in this case, list) being listened on, so they will also trigger view updates. These covered methods include:
- push()
- pop()
- shift()
- unshift()
- splice()
- sort()
- reverse()
- splice()
No longer array native methods, but Vue overwritten methods
The official API Vue. Set ()
Vue. Set is an official global API, alias vm.$set, used to actively trigger responses
The set method is essentially calling the splice method to trigger the response,
vm.$forceUpdate()
Force the Vue instance to be re-rendered by calling vm.$forceUpdate()
In general, you should avoid this approach and go through the data-driven normal method instead
Try this method when you’re desperate, but don’t overuse it. Think about how you might want to change an array entry, but you might update an entire component
As the website says:
If you find yourself needing a forced update in Vue, 99.9% of the time, you’ve done something wrong.
Deep copy
The rough stuff is done by serializing and deserializing back
You might also encapsulate your own cloneDeep method, which can also trigger responses, but it’s a bit awkward to use a deep copy just to update something
map()
Map is a native method of arrays, used to map arrays, and non-mutable methods such as slice, concat, and filter do not alter the original array, but always return a new array. In Vue, we can update arrays by replacing them
You might think that this would cause Vue to discard the existing DOM and re-render the entire list. Fortunately, Vue does more than enough.
Vue implements some clever heuristics to maximize the reuse of DOM elements, so it is very efficient to replace an array with one containing the same elements. Remember that v-for used in templates must provide a key. Vue can find differences, locate and update them more efficiently based on this key value.
In fact, this method of generating new data based on source data (without affecting external data) conforms to the idea of functional programming. If you have used Redux, map and filter are often used when writing reducer
Array items are objects
This. List [1]. Name = ‘jerry’. If an array item is an object, you can update the properties of the object directly by subscript. It is initialized with the Observer class, adding getters, setter listeners to the object properties
When initializing an Observer class, protoAugment() and observeArray() are normally called if the class is an array. ProtoAugment points the __proto__ of value (array) to arrayMethods, focusing here on observeArray, which calls observe(), observe in each element
summary
As you can see, if the array item is not an object, it returns directly; The array entry is an object, and continues on that object
Observer initializes, then calls walk(), and calls defineReactive() for each property. DefineReactive adds getter, setter listeners to the property via Object.defineProperty, There’s a lot of discussion on the web about why Vue doesn’t make arr[index] = val reactive, and the author answers that, in general, the performance cost is not proportional to the user experience gained. Arr [index] = val is not reactive, but there is an official API to operate on. As a framework, Vue does more than enough. Of course, Vue3 replaces Object.defineProperty with Proxy, so this problem doesn’t exist anymore.
For more information: baijiahao.baidu.com/s?id=168350…
10. Why must the Vue component data be a function?
In the new Vue() instance,data can be an object directly. Why must data be a function in the Vue component?
Because components can be reused, the object in JS is a reference relationship, if the component data is an object, then the data attribute values in the sub-components will pollute each other, causing side effects.
So a component’s data option must be a function, so each instance can maintain a separate copy of the returned object. Instances of new Vue are not reused, so there is no such problem.
11. Talk about the Vue event mechanism, handwritten$on
.$off
.$emit
.$once
?
The Vue event mechanism is essentially an implementation of the observer pattern pattern.
Class Vue {constructor() {this._events = object.create (null); } $on(event, fn) { if (Array.isArray(event)) { event.map(item => { this.$on(item, fn); }); } else { (this._events[event] || (this._events[event] = [])).push(fn); } return this; } $once(event, fn) { function on() { this.$off(event, on); fn.apply(this, arguments); } on.fn = fn; this.$on(event, on); return this; } $off(event, fn) { if (! arguments.length) { this._events = Object.create(null); return this; } if (Array.isArray(event)) { event.map(item => { this.$off(item, fn); }); return this; } const cbs = this._events[event]; if (! cbs) { return this; } if (! fn) { this._events[event] = null; return this; } let cb; let i = cbs.length; while (i--) { cb = cbs[i]; if (cb === fn || cb.fn === fn) { cbs.splice(i, 1); break; } } return this; } $emit(event) { let cbs = this._events[event]; if (cbs) { const args = [].slice.call(arguments, 1); cbs.map(item => { args ? item.apply(this, args) : item.call(this); }); } return this; }}Copy the code