Home>Article>Web Front-end> [Hematemesis] Summary of Vue.js interview questions and analysis of answers (come and collect them)
This article summarizes and shares some Vue interview questions (with answer analysis) to help you sort out basic knowledge and enhance your Vue knowledge reserve. It is worth collecting, come and take a look!
(Learning video sharing:vue video tutorial)
##Core implementation class:Observer: Its function is to add getters and setters to the properties of the object for dependency collection and dispatch updates
Dep: used to collect dependencies of the current responsive object. Each responsive object including sub-objects has a Dep instance ( (subs inside is an array of Watcher instances). When the data changes, each watcher will be notified through dep.notify().
Watcher: Observer object, instances are divided into three types: rendering watcher (render watcher), calculated property watcher (computed watcher), and listener watcher (user watcher)
The relationship between Watcher and Dep:Dep is instantiated in watcher and subscribers are added to dep.subs. dep notifies each watcher update through notify traversing dep.subs.
Dependency collection:During initState, when the computed attribute is initialized, the computed watcher dependency collection is triggered
When initState, when the listening attribute is initialized, the user watcher dependency collection is triggered
The process of render() triggers the render watcher dependency collection
When re-rendering, vm.render() is executed again, and the subscriptions of watcher in all subs will be removed and reassigned.
Dispatch update:The response data is modified in the component, triggering the logic of the setter
Call dep.notify()
Traverse all subs (Watcher instances), Call the update method of each watcher.
Principle:When creating a Vue instance, vue will traverse the properties of the data option, and use Object.defineProperty to add getters and setters to the properties to hijack the reading of data (getters are used to rely on Collection, setter is used to dispatch updates), and internally tracks dependencies, notifying changes when properties are accessed and modified.
Each component instance will have a corresponding watcher instance, which will record all the data attributes of the dependency during the component rendering process (dependency collection, as well as computed watcher and user watcher instances). When the dependency is changed later, the setter The method will notify the watcher instance that depends on this data to recalculate (dispatch updates), thereby re-rendering its associated components.
Summary in one sentence:vue.js uses data hijacking combined with publish-subscribe mode, and uses Object.defineproperty to
hijack the setters and getters of each property, and publish messages when the data changes. To the subscriber, trigger the response listening callback
Easy to use: Simple, easy to learn, Get started quicklyFlexible: (Progressive) A thriving ecosystem that can scale freely between a library and a complete framework.
Efficient: 20kB min gzip running size; ultra-fast virtual DOM; most worry-free optimization
Two-way binding: high development efficiency
Component-based code sharing
Web project engineering, increasing readability stability and maintainability
Vue.js 2.0 adopts data hijacking (Proxy mode) Combined with the publisher-subscriber mode (PubSub mode), Object.defineProperty() is used to hijack the setters and getters of each property, publish messages to subscribers when the data changes, and trigger corresponding listening callbacks.Vue.js 3.0, abandoned Object.defineProperty and used the faster ES6 native Proxy (access object interceptor, also called proxy) Steps:Each component instance has a corresponding watcher program instance. It will record the properties as dependencies during the rendering process of the component. Later, when the setter of the dependency is called, the watcher will be notified to recalculate, causing its associated The component is updated.
1. The data object that needs to be observed is traversed recursively, including the attributes of the sub-attribute object, and setters and getters are added. If a value is assigned to this object, the setter will be triggered, then it can Detected data changes
2.compile parses the template instructions, replaces the variables in the template with data, then initializes the rendering page view, binds the node corresponding to each instruction to the update function, and adds a subscriber to monitor the data. Once When the data changes, receive a notification and update the view
3. Watcher subscribers are the bridge of communication between Observer and Compile. The main things they do are: ① Add themselves to the attribute subscriber (dep) when they are instantiated. ② It must have an update() method. ③ When notified by dep.notice() of attribute changes, it can call its own update() method and trigger the callback bound in Compile, then it will be successful and retired.
4. As the entrance to data binding, MVVM integrates Observer, Compile and Watcher. It uses Observer to monitor changes in its own model data, uses Compile to parse and compile template instructions, and finally uses Watcher to bridge the gap between Observer and Compile. A communication bridge to achieve the two-way binding effect of data changes -> view updates; view interactive changes (input) -> data model changes.
For example, we now need to monitor the changes in obj.a in data. You can monitor changes in object attributes in Vue like this:
watch: { obj: { handler (newValue, oldValue) { console.log('obj changed') }, deep: true }
The deep attribute represents deep traversal, but writing this way will monitor all attribute changes of obj, which is not the effect we want, so make some modifications:
watch: { 'obj.a': { handler (newName, oldName) { console.log('obj.a changed') } } }
There is another method, which can be implemented through computed. You only need to:
computed: { a1 () { return this.obj.a } }
Use the characteristics of calculated properties to achieve it. When the dependency changes, a new value will be recalculated.
Object.defineProperty defects
1. Monitor the array When the target changes, the overhead is high. So Vue.js gave up the detection of subscript changes;
2.Object.defineProperty can only hijack the properties of the object, while Proxy is a direct proxy object. 3.Object.defineProperty needs to traverse each property of the object. If the property value is also an object, it requires deep traversal. Proxy directly proxies objects and does not require traversal operations.
4. Object.defineProperty needs to be manually observed for new properties. vue2 needs to use vm.$set to ensure that the newly added properties are also responsive
5.Proxy supports 13 kinds of interception operations, which defineProperty does not have
6.Proxy is a new standard, in the long run, The JS engine will continue to optimize Proxy, but getters and setters will basically no longer be optimized in a targeted manner
The view is not refreshed. This is because when the Vue instance is created, the new properties are not declared, so they are not converted into responsive properties by Vue, and naturally the update of the view will not be triggered. In this case, you need to use Vue's global api $set():
this.$set(this.obj, 'new_property', 'new_value')
Computed computed properties:Depends on other property values, and computed The value is cached, and only if the attribute value it depends on changes, the computed value will be recalculated the next time the computed value is obtained.
watch listener:It is more of an observation function, without caching, similar to the monitoring callback of certain data. Whenever the monitored data changes, the callback will be executed for subsequent operations.
Application scenarios:
1. When we need to perform numerical calculations and depend on other data, computed should be used because the cache feature of computed can be used to avoid Each time a value is obtained, it is recalculated.
2. When we need to perform asynchronous or expensive operations when data changes, we should use watch. Using the watch option allows us to perform asynchronous operations (access an API), limit the frequency with which we perform the operation, and Before we get the final result, we set up intermediate states. These are things that computed properties cannot do.
3. If multiple factors affect one display, use Computed; if a change in one factor affects multiple other factors and displays, use Watch;
1.computed: Computed properties are cached based on their dependencies, and will only be re-evaluated when its related dependencies change. For methods, whenever re-rendering occurs,
2.Method call will always execute the function
1. Let us not directly operate the DOM elements, but only operate the data to re-render the page
2 .Virtual DOM is designed to solve browser performance problems
When operating data, the changed DOM elements are cached, and after calculation, they are mapped to the real DOM tree through comparison
3. The diff algorithm compares the old and new virtual DOM. If the node types are the same, compare the data and modify the data; if the nodes are different, directly delete the node and all child nodes, and insert a new node; if a unique key is set for each node, you can accurately find what needs to be changed. , otherwise there will be a situation where modifying one place will cause changes in other places. For example, A-B-C-D, if I want to insert a new node A-B-M-C-D, C and D will actually be changed. But after setting the key, you can accurately find B C and insert
1. It has cross-platform advantages
2. It is slow to operate DOM, but js runs efficiently. We can put the DOM comparison operation on the JS layer to improve efficiency.
3. Improve rendering performance
Use filters in Vue to filter (format) Data, filters will not modify the data, but filter (format) the data and change the output seen by the user (computed attributes, methods, all process the output display of the data format by modifying the data.
Usage scenarios: For example Need to process the display format of time, numbers, etc.;
1)
.stop
: Equivalent to event.stopPropagation() in JavaScript, preventing events from bubbling;
2).prevent
: Equivalent to event.preventDefault() in JavaScript, preventing the execution of pre- Set the behavior (if the event can be canceled, cancel the event without stopping the further propagation of the event);
3).capture
: When the element bubbles, first trigger with this modification symbol element. If there are multiple modifiers, they will be triggered from outside to inside. For example, if p1 is nested in p2, p3 is nested in p4.capture is nested in p4, then the execution sequence is: p3=》p4=》p2=》p1
4).self
: It will only trigger itself Events within the scope, excluding child elements;
5).once
: Will only be triggered once.
v-showOnly controls the display mode of the element, switch the display attribute back and forth betweenblock and none; and v-if will control The existence or absence of thisDOM node. When we need to frequently switch the display/hide of an element, using v-show will save more performance overhead; when we only need to show or hide it once, using v-if is more reasonable.
It acts on form elements and v-model="message" is equivalent to v-bind:value="message" v-on:input="message=e v e n t . t a r g e t . v a l u e " acts on the component. It is essentially a syntax sugar for parent-child component communication, implemented through prop and .emit, which is equivalent to:value="message" @input=" $emit('input', $event.target.value)"
Objects in JavaScript are reference type data. When multiple instances refer to the same object, as long as one instance operates on this object, the data in other instances will also change.
In Vue, we want to reuse components more, so each component needs to have its own data so that the components will not interfere with each other.
Therefore, the data of the component cannot be written in the form of objects, but must be written in the form of functions. Data is defined in the form of function return values, so that every time we reuse a component, a new data will be returned. That is to say, each component has its own private data space, and they each maintain their own data. Can interfere with the normal operation of other components.
1. Call the parse method to convert the template into ast (abstract syntax tree, abstract syntax tree )
2. Optimize static nodes. If they are static nodes, the DOM they generate will never change, which greatly optimizes runtime template updates.
3. Generate a rendering function. The return value of rendering is VNode. VNode is Vue’s virtual DOM node, which contains (label name, child node, text, etc.)
Call the parse method to convert the template into ast (abstract syntax tree)
Optimize static nodes. If they are static nodes, the DOM they generate will never change, which greatly optimizes runtime template updates.
Generate rendering function. The return value of rendering is VNode. VNode is Vue’s virtual DOM node, which contains (label name, child node, text, etc.)
易用、简洁且高效的http库, 支持node端和浏览器端,支持Promise,支持拦截器等高级配置。
sass是一种CSS预编译语言安装和使用步骤如下。
1.用npm安装加载程序( sass-loader、 css-loader等加载程序)。
2.在 webpack.config.js中配置sass加载程序。
Vue. js提供了一个v-cloak
指令,该指令一直保持在元素上,直到关联实例结束编译。当和CSS一起使用时,这个指令可以隐藏未编译的标签,直到实例编译结束。用法如下
在开发业务时,经常会岀现异步获取数据的情况,有时数据层次比较深,如以下代码:, 可以使用vm.$set手动定义一层数据:
vm.$set("demo",a.b.c.d)
config/ index.js内对 proxyTable项配置代理。
Vue 在修改数据后,视图不会立刻更新,而是等同一事件循环中的所有数据变化完成之后,再统一进行视图更新。
换句话说,只要观察到数据变化,就会自动开启一个队列,并缓冲在同一个事件循环中发生的所以数据改变。在缓冲时会去除重复数据,从而避免不必要的计算和 DOM 操作。
1.vue 用异步队列的方式来控制 DOM 更新和 nextTick 回调先后执行
2.microtask 因为其高优先级特性,能确保队列中的微任务在一次事件循环前被执行完毕
因为组件是可以复用的,JS 里对象是引用关系,如果组件 data 是一个对象,那么子组件中的 data 属性值会互相污染。
所以一个组件的 data 选项必须是一个函数,因此每个实例可以维护一份被返回对象的独立的拷贝。
由于v-for的优先级比v-if高,所以导致每循环一次就会去v-if一次,而v-if是通过创建和销毁dom元素来控制元素的显示与隐藏,所以就会不停的去创建和销毁元素,造成页面卡顿,性能下降。
解决办法:
1.在v-for的外层或内层包裹一个元素来使用v-if
2.用computed处理
1.v-model 多用于表单元素实现双向数据绑定(同angular中的ng-model)
2.v-bind 动态绑定 作用: 及时对页面的数据进行更改
3.v-on:click 给标签绑定函数,可以缩写为@,例如绑定一个点击函数 函数必须写在methods里面
4.v-for 格式: v-for=“字段名 in(of) 数组json” 循环数组或json(同angular中的ng-repeat)
5.v-show 显示内容 (同angular中的ng-show)
6.v-hide 隐藏内容(同angular中的ng-hide)
7.v-if 显示与隐藏 (dom元素的删除添加 同angular中的ng-if 默认值为false)
8.v-else-if 必须和v-if连用
9.v-else 必须和v-if连用 不能单独使用 否则报错 模板编译错误
10.v-text 解析文本
11.v-html 解析html标签
12.v-bind:class 三种绑定方法 1、对象型 ‘{red:isred}’ 2、三元型 ‘isred?“red”:“blue”’ 3、数组型 ‘[{red:“isred”},{blue:“isblue”}]’
13.v-once 进入页面时 只渲染一次 不在进行渲染
14.v-cloak 防止闪烁
15.v-pre 把标签内部的元素原位输出
1.父传子:子组件通过props[‘xx’] 来接收父组件传递的属性 xx 的值
2.子传父:子组件通过 this.$emit(‘fnName’,value) 来传递,父组件通过接收 fnName 事件方法来接收回调
3.其他方式:通过创建一个bus,进行传值
4.使用Vuex
当 Vue.js 用 v-for 正在更新已渲染过的元素列表时,它默认用“就地复用”策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序, 而是简单复用此处每个元素,并且确保它在特定索引下显示已被渲染过的每个元素。key的作用主要是为了高效的更新虚拟DOM
Object.defineProperty
本身有一定的监控到数组下标变化的能力,但是在 Vue 中,从性能/体验的性价比考虑,尤大大就弃用了这个特性(Vue 为什么不能检测数组变动 )。为了解决这个问题,经过 vue 内部处理后可以使用以下几种方法来监听数组
push();
pop();
shift();
unshift();
splice();
sort();
reverse();
由于只针对了以上 7 种方法进行了 hack 处理,所以其他数组的属性也是检测不到的,还是具有一定的局限性。
Object.defineProperty 只能劫持对象的属性,因此我们需要对每个对象的每个属性进行遍历。Vue 2.x 里,是通过 递归 + 遍历 data 对象来实现对数据的监控的,如果属性值也是对象那么需要深度遍历,显然如果能劫持一个完整的对象是才是更好的选择。
Proxy 可以劫持整个对象,并返回一个新的对象。Proxy 不仅可以代理对象,还可以代理数组。还可以代理动态增加的属性。
JS 运行机制
JS 执行是单线程的,它是基于事件循环的。事件循环大致分为以下几个步骤:
所有同步任务都在主线程上执行,形成一个执行栈(execution context stack)。
主线程之外,还存在一个"任务队列"(task queue)。只要异步任务有了运行结果,就在"任务队列"之中放置一个事件。
一旦"执行栈"中的所有同步任务执行完毕,系统就会读取"任务队列",看看里面有哪些事件。那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。
主线程不断重复上面的第三步。
主线程的执行过程就是一个 tick,而所有的异步结果都是通过 “任务队列” 来调度。 消息队列中存放的是一个个的任务(task)。 规范中规定 task 分为两大类,分别是 macro task 和 micro task,并且每个 macro task 结束后,都要清空所有的 micro task。
for (macroTask of macroTaskQueue) { // 1. Handle current MACRO-TASK handleMacroTask(); // 2. Handle all MICRO-TASK for (microTask of microTaskQueue) { handleMicroTask(microTask); }}
在浏览器环境中 :
常见的 macro task 有setTimeout、MessageChannel、postMessage、setImmediate
常见的 micro task 有MutationObsever 和 Promise.then
异步更新队列
可能你还没有注意到,Vue 在更新 DOM 时是异步执行的。只要侦听到数据变化,Vue 将开启一个队列,并缓冲在同一事件循环中发生的所有数据变更。
如果同一个 watcher 被多次触发,只会被推入到队列中一次。这种在缓冲时去除重复数据对于避免不必要的计算和 DOM 操作是非常重要的。
然后,在下一个的事件循环“tick”中,Vue 刷新队列并执行实际 (已去重的) 工作。
Vue 在内部对异步队列尝试使用原生的 Promise.then、MutationObserver 和 setImmediate,如果执行环境不支持,则会采用 setTimeout(fn, 0) 代替。
在 vue2.5 的源码中,macrotask 降级的方案依次是:setImmediate、MessageChannel、setTimeout
vue 的 nextTick 方法的实现原理:
vue 用异步队列的方式来控制 DOM 更新和 nextTick 回调先后执行
microtask 因为其高优先级特性,能确保队列中的微任务在一次事件循环前被执行完毕
考虑兼容问题,vue 做了 microtask 向 macrotask 的降级方案
Vue 事件机制 本质上就是 一个 发布-订阅 模式的实现。
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; }}
三种:
一种是全局导航钩子:router.beforeEach(to,from,next),作用:跳转前进行判断拦截。第二种:组件内的钩子;第三种:单独路由独享组件
vue框架中状态管理。在main.js引入store,注入。新建了一个目录store,…… export 。
场景有:单页应用中,组件之间的状态。音乐播放、登录状态、加入购物车
MVVM and MVC are both design ideas. The main thing is that the Controller in MVC evolves into a ViewModel. MVVM mainly displays the view layer through data instead of operating nodes, which solves the problem in MVC. A large number of DOM operations reduce page rendering performance and slow loading speed, affecting user experience. Mainly used in scenarios with a lot of data operations.
Scenarios: Scenarios with a lot of data operations, more convenient
In short, it is converted into an AST tree first, and then the resulting rendering function returns VNODE (Vue company's virtual DOM node)
Detailed steps:
First, pass The compiler compiles the template into an AST syntax tree (an abstract syntax tree is a tree representation of the abstract syntax structure of the source code). Compilation is the return value of createCompiler, which is used to create the compiler. Responsible for merging options.
Then, the AST will be generated (the process of converting the AST syntax tree into a rendering function string) to obtain the rendering function. The return value of the rendering is VNode. VNode is the virtual DOM node of Vue, which contains (label name, child node , text, etc.)
Answer: When wrapping dynamic components, inactive component instances will be cached, mainly used to retain component state or avoid re-rendering;
Use: simple page
Cache:
Do not cache:
The same points: both encourage componentization, both have the concept of 'props', and each has its own Construction tools, Reat and Vue only have the skeleton of the framework, and other functions such as routing, state management, etc. are components separated from the framework.
Differences: React: one-way data flow, syntax - JSX, in React you need to use the setState() method to update the state. Vue: two-way data binding, syntax – HTML, state object is not required, data is managed in the Vue object by the data attribute. Suitable for small applications, but not suitable for large applications.
Refer to the master’s article: vue notes - the second learning and understanding of the life cycle
beforeCreate
is triggered after new Vue() For the first hook, the data and methods on data, methods, computed and watch cannot be accessed in the current stage.
created
Occurs after the instance is created. Data observation has been completed at the current stage, that is, the data can be used and changed. Changing the data here will not trigger the updated function. You can do some initial data acquisition. You cannot interact with the Dom at the current stage. If you have to, you can access the Dom through vm.$nextTick.
beforeMount
Occurs before mounting, before which the template template has been imported and compiled with rendering functions. At the current stage, the virtual Dom has been created and is about to start rendering. Changes to the data can also be made at this time, and updated will not be triggered.
mounted
Occurs after the mounting is completed. At the current stage, the real Dom is mounted, the data is bidirectionally bound, the Dom node can be accessed, and the Dom can be accessed using the $refs attribute. operate.
beforeUpdate occurs before the update, that is, the responsive data is updated and the virtual dom is triggered before re-rendering. You can change the data in the current stage without causing re-rendering.
updated
Occurs after the update is completed, and the component Dom in the current stage has been updated. Be careful to avoid changing data during this period as this may result in an infinite loop of updates.
beforeDestroy
Occurs before the instance is destroyed. The instance can be fully used at the current stage. We can perform post-processing finishing work at this time, such as clearing the timer.
destroyed
Occurs after the instance is destroyed. At this time, only the dom shell is left. The component has been disassembled, the data binding has been removed, the listener has been removed, and all child instances have been destroyed.
In short, the diff algorithm has the following process
1. Compare the same level, and then compare the child nodes
2. First determine whether one party has child nodes and the other does not (if the new children have no child nodes, remove the old child nodes)
3. Compare the situation where there are child nodes (core diff)
3. Recursively compare child nodes
The time complexity of normal Diff between two trees isO(n^3)
, but in actual situations we rarely move the DOM across levels, so Vue performs Diff Optimization, fromO(n^3) -> O(n)
, only when the old and new children are multiple child nodes, the core Diff algorithm needs to be used for same-level comparison.
Vue2's core Diff algorithm uses a double-end comparison algorithm. At the same time, it compares from both ends of the old and new children, uses the key value to find the reusable node, and then performs related operations. Compared with React's Diff algorithm, under the same circumstances, it can reduce the number of mobile nodes, reduce unnecessary performance losses, and is more elegant.
Vue3.x draws on the
ivi algorithm and the inferno algorithm
The type of VNode is determined when creating it, and bit operations are used to determine the value of a VNode during the mount/patch process. Type, combined with the core Diff algorithm on this basis, improves performance compared to Vue2.x. (The actual implementation can be viewed in conjunction with the Vue3.x source code.)
This algorithm also uses the idea of dynamic programming to solve the longest recursive subsequence.
Encoding phase
1. Try to reduce the data in the data. The data in the data will add getters and setters, and the corresponding 2.watcher
3 will be collected. .v-if and v-for cannot be used together
4. If you need to use v-for to bind events to each element, use an event proxy
5. The SPA page uses the keep-alive caching component
6. In more cases, use v-if instead of v-show
7. Key is guaranteed to be unique
8. Use routing for lazy loading and asynchronous components
9. Anti-shake and throttling
10. Import third-party modules on demand
11. Scroll long lists to the visible area for dynamic loading
12. Lazy loading of images
SEO optimization
1. Pre-rendering
2. Server-side rendering SSR
Packaging optimization
1. Compression code
2.Tree Shaking/Scope Hoisting
3. Use cdn to load third-party modules
4. Multi-threaded packaging happypack
5.splitChunks to extract public files
6.SourceMap optimization
User experience
1. Skeleton screen
2.PWA
You can also use cache (client cache, server cache) optimization, enable gzip compression on the server, etc.
location.hash
is actually the thing after # in the URL.
history
is actually implemented using the API provided in HTML5, mainlyhistory.pushState()
andhistory.replaceState()
.
SPA (single-page application) only loads the corresponding HTML when the Web page is initialized. , JavaScript and CSS
Once the page is loaded, SPA will not reload or jump the page due to user operations
Instead, it uses the routing mechanism to realize the transformation of HTML content and the interaction between UI and users to avoid Page reloading
Advantages:
1. The user experience is good and fast. Changes in content do not require reloading the entire page, avoiding unnecessary jumps and repeated renderings
2 , Based on the above point, SPA has relatively little pressure on the server
3. The front-end and back-end responsibilities are separated and the architecture is clear. The front-end performs interactive logic and the back-end is responsible for data processing
Disadvantages:
1. The initial loading takes a long time: In order to realize the single-page Web application function and display effect,
JavaScript and CSS need to be loaded uniformly when loading the page, and some pages are loaded on demand
2. Go forward Back routing management: Since single-page applications display all content on one page,
so you cannot use the browser's forward and backward functions, and all page switching requires your own stack management
3. SEO is difficult: due to All content is dynamically replaced and displayed on one page, so it has a natural weakness in SEO
The first step: Create your component file (indexPage.vue) in the components directory. The script must be
export default {}
The second step: Import into the required page (component):import indexPage from '@/components/indexPage.vue'
Step 3: Inject into the components attribute of the sub-component of vue,components:{indexPage}
Step 4: Use it in the template view,
For example, if it is named indexPage, when using it, it will be index-page
require.ensure()
is provided in webpack to achieve on-demand loading. In the past, routes were introduced through import, but now they are introduced through const definition.
The introduction method without on-demand loading of pages:import home from '../../common/home.vue'
The introduction method of on-demand loading of pages:const home = r => require.ensure( [], () => r (require('../../common/home.vue')))
以组件功能命名
只负责ui的展示和交互动画,不要在组件里与服务器打交道(获取异步数据等)
可复用组件不会因组件使用的位置、场景而变化。尽量减少对外部条件的依赖。
在每一个Vue.js组件中都可以定义各自的CSS、 JavaScript代码。如果希望组件内写的CSS只对当前组件起作用,只需要在Style标签添加Scoped属性即可
如果需要在组件切换的时候,保存一些组件的状态防止多次渲染,就可以使用 keep-alive 组件包裹需要保存的组件。
两个重要属性,include 缓存组件名称,exclude 不需要缓存的组件名称。
对“src”属性插值将导致404请求错误。应使用 v-bind:src (简写:src)格式代替。
加载渲染过程:
父beforeCreate->父created->父beforeMount->子beforeCreate->子created->子beforeMount->子mounted->父mounted
子组件更新过程:父beforeUpdate->子beforeUpdate->子updated->父updated
父组件更新过程:父beforeUpdate->父updated
销毁过程:父beforeDestroy->子beforeDestroy->子destroyed->父destroyed
1.state => 基本数据
2.getters => 从基本数据派生的数据
3.mutations => 修改数据,同步
4.actions => 修改数据,异步 (Action 提交的是 mutation,而不是直接变更状态)
5.modules => 模块化Vuex
Vuex 是一个专为 Vue.js 应用程序开发的状态管理器,采用集中式存储管理应用的所有组件的状态,主要是为了多页面、多组件之间的通信。
Vuex有5个重要的属性,分别是 State、Getter、Mutation、Action、Module,由 view 层发起一个 Action 给 Mutation,在 Mutation 中修改状态,返回新的状态,通过 Getter暴露给 view层的组件或者页面,页面监测到状态改变于是更新页面。如果你的项目很简单,最好不要使用 Vuex,对于大型项目,Vuex 能够更好的帮助我们管理组件外部的状态,一般可以运用在购物车、登录状态、播放等场景中。
1.公共的数据部分可以提升至和他们最近的父组件,由父组件派发
2.公共数据可以放到vuex中统一管理,各组件分别获取
1.如果请求来的数据是不是要被其他组件公用,仅仅在请求的组件内使用,就不需要放入vuex 的state里。
2.如果被其他地方复用,这个很大几率上是需要的,如果需要,请将请求放入action里,方便复用,并包装成promise返回,在调用处用async await处理返回的数据。如果不要复用这个请求,那么直接写在vue文件里很方便
actions与mutations作用类似,都是可以对状态进行修改。不同的是actions是异步操作的。
actions是可以调用Mutations里的方法的。
const actions={ addActions(context){ context.commit('add',10);//调用mutations中的方法 setTimeout(()=>{context.commit('reduce')},5000) // setTimeOut(()=>{context.commit('reduce')},3000); console.log('我比reduce提前执行'); }, reduceActions({commit}){ commit('reduce'); }}
Mutation 更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。Vuex 中的 mutation 非常类似于事件:每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数
const store = new Vuex.Store({ state: { count: 1 }, mutations: { increment (state) { // 变更状态 state.count++ } }})
Action Action 类似于 mutation,不同在于:
Action 提交的是 mutation,而不是直接变更状态。
Action 可以包含任意异步操作
const store = new Vuex.Store({ state: { count: 0 }, mutations: { increment (state) { state.count++ } }, actions: { increment (context) { context.commit('increment') } }})
使用mapState
辅助函数, 利用对象展开运算符将state混入computed对象中
import {mapState} from 'vuex' export default{ computed:{ ...mapState(['price','number']) } }
对象是引用类型,复制后改变属性还是会影响原始数据,这样会改变state里面的状态,是不允许,所以先用深度克隆复制对象,再修改。
1.Hash: 使用 URL 的 hash 值来作为路由。支持所有浏览器。 带#。如:http://localhost:8080/#/pageA。改变hash,浏览器本身不会有任何请求服务器动作的,但是页面状态和url已经关联起来了。
2.History: 以来 HTML5 History API 和服务器配置。参考官网中 HTML5 History 模式,不带#, 如:http://localhost:8080/ 正常的而路径,并没有#。基于HTML5的 pushState、replaceState实现
3.Abstract: 支持所有 javascript 运行模式。如果发现没有浏览器的 API,路由会自动强制进入这个模式。
通过children 数组:
const router = new VueRouter({ routes: [ { path: "/parentPage", component: testPage, children: [ { path: "/childrenA", component: childrenComponentA, }, { path: "/childrenB", component: childrenComponentB, }, ], }, { // 其他和parentPage平级的路由 }, ],});
1.全局导航钩子:
router.beforeEach(to,from,next)
2.组件内的钩子beforeRouteEnter (to, from, next) beforeRouteUpdate (to, from, next) beforeRouteLeave (to, from, next)
3.单独路由独享组件beforeEnter: (to, from, next)
参数:有to(去的那个路由)、from(离开的路由)、next(一定要用这个函数才能去到下一个路由,如果不用就拦截)最常用就这几种
1、$route
是“路由信息对象”,包括path,params,hash,query,fullPath,matched,name
等路由信息参数。
1.
$route.path
字符串,对应当前路由的路径,总是解析为绝对路径如"/foo/bar"。
2.$route.params
一个 key/value 对象,包含了 动态片段 和 全匹配片段, 如果没有路由参数,就是一个空对象。
3.$route.query
一个 key/value 对象,表示 URL 查询参数。 例如,对于路径/foo?user=1
,则有$route.query.user == 1
, 如果没有查询参数,则是个空对象
4.$route.hash
当前路由的hash值 (不带#) ,如果没有 hash 值,则为空字符串
5.$route.fullPath
完成解析后的 URL,包含查询参数和hash的完整路径。
6.$route.matched
数组,包含当前匹配的路径中所包含的所有片段所对应的配置参数对象。
7.$route.name
当前路径名字
8.$ route.meta
路由元信息
2、$router
是“路由实例”对象包括了路由的跳转方法,钩子函数等
实例方法:
1)、push
1.字符串
this.$router.push('home')
2. 对象this.$router.push({path:'home'})
3. 命名的路由this.$router.push({name:'user',params:{userId:123}})
4.带查询参数,变成/register?plan=123this.$router.push({path:'register',query:{plan:'123'}})
push方法其实和是等同的。
注意:push方法的跳转会向 history 栈添加一个新的记录,当我们点击浏览器的返回按钮时可以看到之前的页面。
2)、go
页面路由跳转
前进或者后退this.$router.go(-1)
// 后退
3)、replace
push方法会向 history 栈添加一个新的记录,而replace方法是替换当前的页面,
不会向 history 栈添加一个新的记录
1.声明式(标签跳转)
2.编程式( js跳转)
vue-router 模块 的router-link组件
把不同路由对应的组件分割成不同的代码块,然后当路由被访问时才加载对应的组件即为路由的懒加载,可以加快项目的加载速度,提高效率
const router = new VueRouter({ routes: [ { path: '/home', name: 'Home', component:() = import('../views/home') } ]})
在router目录下的index.js文件中,对path属性加上/:id
使用router对象的params id
面试官:我难道问不倒这小子了?(面试官持续懵逼中) 对大家有帮助的话三连呀~ 持续更新
[Related video tutorial recommendations:vuejs entry tutorial,web front-end entry]
The above is the detailed content of [Hematemesis] Summary of Vue.js interview questions and analysis of answers (come and collect them). For more information, please follow other related articles on the PHP Chinese website!