vue2 articles

1. What is vue, what is the core concept of vue

  1. Vue is a progressive JS framework for building user interfaces
  2. Progressive: Allows users to start from a simple component and load it on demand until building a complex front-end platform.
  3. The core concept of vue:
    • Componentization
    • MVVM structure, data two-way binding
    • Responsive, virtual DOM
    • life cycle
    • Everything is data-centric and data-driven views.

2. Advantages of vue

  1. Lightweight: As a lightweight front-end framework, vue is only 18-21KB in size, and the project is easy to build.
  2. High performance: Virtual DOM and responsiveness avoid unnecessary global rendering, improve user experience, and make user operations smoother.
  3. Easy to use: Vue's component development idea is easy to understand, and the separated syntax is more friendly to beginners.
  4. Plug-in: Due to the popularity of the vue framework, there are currently many ue-based npm extension packages and development tools (such as vuex). Vue can manage the global use of all external plugins under one file. Plug-in provides a lot of development convenience.
  5. Fast running speed: Compared with other frameworks, Vue has great advantages in terms of performance.
  6. Ease of testing: The idea of ​​componentization is convenient for troubleshooting and can be tracked quickly.
  7. Separation of view, data, and structure: Make data changes easier, without modifying logic codes, and only need to operate data to complete related operations.

3. Installation of vue.js

  1. cdn import<script src=''></script>
  2. download file,<script src='vue.js'></script>
  3. Install globally via npm (or yarn): npm install vue@version --g/-save
  4. Note: You can download the corresponding development environment or production environment according to actual needs

4. MVVM

  1. M: model data model layer, data obtained from network requests.
  2. V: views The view layer, that is, the DOM layer, is used to display the rendering results to the user.
  3. VM: view-model The view model layer is used to connect the view and the model to realize the two-way binding between the two. In this way, if the model is changed, the view will change accordingly. Similarly, if the view is changed, the model data layer will also be automatically updated.

5. Life cycle

  1. Concept: the process of creating, mounting, rendering, updating and destroying a Vue instance
  2. create:
    • beforeCreate: At this time, the vue instance has not been initialized, and the mount element $el and the data object data are both empty
    • Created after creation: At this time, the vue instance has been initialized, but the dom has not been generated, so $el is empty, data exists, and data can be manipulated through methods
  3. mount:
    • beforeMount before mounting: At this time, $el and data are already available, and the template has been edited in memory, but it has not been rendered to the page
    • mounted after mounting: $el has been rendered to the page, and the user can see it
  4. renew:
    • beforeUpdate: At this time, view and model have not realized two-way binding
    • Updated after update: At this point view and model have achieved two-way binding
  5. destroy:
    • beforeDestory before destruction: At this time, the vue instance can still be used
    • Destroyed after destruction: the vue instance has been unbound, and the operation data is invalid, but the dom structure still exists

6. Instructions

  1. v-once
    • The data displayed in the view layer will only be rendered once, and changing the data will not change accordingly
    • Syntax: <h2 v-once>{ {message}} </h2>The message here will only be rendered once
  2. v-html
    • Parse the data in data into html language
    • grammar:<h2 v-html='data'></h2>
  3. v-text
    • Rendering data is similar to { {}} mustache syntax
    • Syntax: <h2 v-text='message'></h2>= <h2>{ {message}} </h2>({ {}} syntax is recommended )
  4. in-for
    • Render the following content without modification
    • Syntax: <h2 v-pre>{ {message}}</h2>
  5. v-clock
    • Solve the problem of page flickering caused by slow initialization
    • Syntax: <h2 v-clock>{ {message}}</h2>
  6. v-bind
    • Dynamic binding, syntactic sugar is ":" v-bind:class<=>:class dynamically binds a class
    • 语法:<h2 :class={‘active’:isActive}>{ {message}}</h2>
  7. v-on
    • Click event, syntactic sugar is "@" v-on:click=@click Bind a click event
    • Syntax: <h2 @click='btn'>{ {message}}</h2>
  8. v-if,v-else,v-else-if,v-show
    • v-if: conditional judgment
    • Syntax: <h2 v-if='条件'>{ {message}} </h2>renders if the condition is true, and does not render if the condition is false
    • The difference between v-if and v-show:
      • When the condition is false, v-if does not render at all, v-show will render, but the rendering result is hidden by display:none
      • v-if is more expensive to render than v-show
      • When you need to switch between display and hide frequently, it is recommended to use v-show
  9. v-for
    • loop through
    • grammar:
      • Traverse the array: <h2 v-for='(book,index) in/of books'>{ {index}}—{ {book.name}}</h2>
      • Traverse objects: <h2 v-for='(value,key,index) in/of books'>{ {index}}—{ {key}}—{ {value}}</h2>
  10. v-model: realizes the two-way binding of label data, which is essentially a syntactic sugar.
<input v-model='test'>`等价于<input :value="test" @input="test = $event.target.value">

7. Components

  1. Component thinking: split a page into small parts, each small part is called a component, complete the independent functions in the component, and then combine these components to form a complete function.
  2. Advantages: Each component is independent of each other, which is convenient for code writing and maintenance.
  3. The use of components (take a single vue file as an example, it is generally not written like this in actual projects)
// 1. 创建组件
const cpn = Vue.extend({
    
    
	// 组件模板
	template:`<div>我是子组件</div>`
})

// 2. 注册组件
// (1)全局注册
Vue.component('my-cpn',cpn)
// (2)局部注册
let app=new Vue({
    
    
    el:'#app',
    data:{
    
    
        message:'你好'
    },
    // 局部注册
    component:{
    
    
        'my-cpn':cpn
    }
})

// 3. 挂载组件
<div id='app'>
    <my-cpn></my-cpn>
</div>
  1. Data in component:
    • data(){}: must be a function, because the component may be referenced on multiple pages, in order to prevent mutual interference between data, data must be a function, and there must be a return
  2. Communication between parent and child components
    • Pass data from parent component to child component
      • Mount the child component in the parent component, and bind the data you want to transmit in the form of v-bind
      • Accept data through props in child components
      • Render different data in subcomponents according to requirements
    • Pass data from child component to parent component
      • In the subcomponent, the data is emitted in the form of $emit(event, value)
      • Accept data through v-on:event='methods' in the parent component
      • Define the method in methods according to requirements
  3. Access between parent and child components
    • The parent component accesses the child component: this.children or this.children or this.c hi l d re n or t hi s . refs
    • Child components access parent components: this.$parent
    • this. c h i l d r e n 和 t h i s . children和this. The difference between c hi l d re n and t hi s . refs
      • This.$children access is an array type, and specific index values ​​need to be used to determine the specific subcomponents accessed
      • this.$refs can determine the subcomponents accessed by binding an id
<!--在子组件中绑定id,在父组件中拿到想要的特定的子组件-->
 <!-- 通过this.$refs.child1可以拿到具体的子组件 -->   
<child_cpn1 ref='child1'></child_cpn1> 
      
 <!-- 通过this.$children[0]索引值可以拿到具体的子组件 -->    
 <child_cpn1></child_cpn1> 
 <child_cpn2></child_cpn1> 
  1. Non-parent-child component communication
    • central event bus
      • Register the central event bus in the mian.js entry file:Vue.prototype.$bus=new Vue()
      • Emit the event where communication is required:this.$bus.$emit('事件名',value)
      • Receive at the corresponding location:this.$bus.$on('发射时候的事件名',callback(value)=>{})
      • Centralized state management mechanism of vuex vue
    • publish-subscribe model

Eight. Slots

  1. <slot></slot>Definition: The part that is wrapped in component development is called a slot.
  2. Function: In componentized development, the same component may be reused multiple times, but only the content is different each time. At this time, you can use the slot placeholder, and then replace the content in the slot according to actual needs.
  3. Category
    (1) Anonymous slots
<!-- 子组件 -->
<div>
  <slot></slot>
</div>

<!-- 父组件 -->
<child>
  <span>我是插槽插入的内容</span>  <!-- 用span标签替换slot插槽 -->
</child>

(2) Named slots

<!-- 子组件 -->
<div>
  <slot name="wangjiajia"></slot>
</div>

<!-- 父组件 -->
<child>
  <span slot="wangjiajia">我是插槽插入的内容</span>  <!-- 用span标签只替换slot名字为wangjiajia的插槽 -->
</child>

(3) Scope slot: Everything in the parent component template will be compiled in the parent scope; everything in the child component template will be compiled in the child scope. However, we can use the slot-scope attribute in the parent component to get data from the child component.

<!-- 子组件 -->
<div>
  <slot :data="data"></slot>
</div>

<!-- 父组件 -->
<child>
  <span slot-scope="data">我是插槽插入的内容</span>
</child>

Nine. Vue scaffolding 1. Application scenario: complex large-scale projects

  1. Application scenario: complex large-scale projects
  2. Scaffold 2:
    • Global installation (recommended): npm install vue/cli-init@version number-g (init acts as a bridge, making it easy to continue using cli2)
    • Installation under the current project: npm install vue/cli-init@version number-save
    • Initialize the project: vue init webpack project (take a project name yourself)
    • View the current version of vue scaffolding: vue -V
  3. Scaffolding 3:
    • Global installation (recommended): npm install vue/cli@versionnumber-g
    • Installation under the current project: npm install vue/cli@version number-save
    • Initialize the project: vue create project (take a project name yourself)
  4. The difference between scaffolding 2 and scaffolding 3:
    • Based on different versions: cli2 is based on webpack3, cli3 is based on webpack4
    • The design principle is different: the design principle of cli3 is 0 configuration, remove the build and config in the root directory of the configuration file
    • cli3 provides vue ui command, provides visual configuration, more convenient and intuitive
    • Remove the static folder, add a new public folder, and move index.html to the public folder

10. Vue modifiers

  1. @click.stop prevents the event from continuing to propagate
  2. @click.prevent prevents label default behavior
  3. @click.capture uses the event capture mode, that is, the event triggered by the element itself is processed here first, and then handed over to the internal element for processing
  4. @click.self triggers the handler only when event.target is the current element itself
  5. @click.once event will only fire once
  6. @click.passive tells the browser that you don't want to prevent the event's default behavior

11. Routing

  1. principle:根据url和ui的映射关系,通过改变url达到更新ui的效果(无需刷新页面)

  2. accomplish:

    • Hash implementation: monitor the change of url through the hashchange event, and use location.hash=xxx to read the attribute, which is essentially changing the href attribute of window.location.
    • History implementation:
      • history.go(0) refresh the current page
      • history.back() === history.go(-1) Return to the previous level
      • history.forward === history.go(1) forward one level
      • history.pushState ( stateObject,' ','url') Change the path part of url without causing page refresh
      • history.repalceState(stateObject,' ',' ') Use url to replace the current route, the browser cannot switch back and forth, and the page will not be refreshed.
    • abstract: supports all JavaScript runtime environments, such as Node.js server-side. Routers are automatically forced into this mode if no browser API is found.
  3. vue-router

    • The three popular frameworks currently have their own routing implementations
      • angular:ngRouter
      • react:ReactRouter
      • view:view-router
    • The role of vue-router: used to access paths and map paths and components.
    • Use of vue-router
      • Installation: npm install vue-router@version number --save
      • Import the routing object and install the routing plugin (in the routing js file)
        • import View from 'view'
        • import VueRouter from “vue-router”
        • Vue.use(VueRouter)
      • Create a routing instance and configure the mapping relationship:const router=new VueRouter({[配置的路由映射,可以提取出来些],mode:'history'})
      • Mount the routing instance in main.js: import router from './router'
      • Use routing in the form of <router-link>or<router-view>
        • <router-link>Built-in components will be rendered as an a tag
        • <router-view>Different components will be rendered dynamically according to the current path
  4. Passing of routing parameters

    • params type: can only be introduced by name
    • query type: can be imported by name or path
  5. Routing jump
    (1) through <router-link :to="{}">
    (2) throughthis.$router.push({})

<!-- query传参 -->
<router-link :to="
	{
    	path:'/user/'+userId,
     	query:{name:"beixi",age:18}
 	}">
</router-link>

<!-- params传参 -->
<router-link :to="
	{
    	name:'/user/'+userId,
     	params:{name:"beixi",age:18}
 	}">
</router-link>
// query传参
this.$router.push({
    
    
     path:'/user/'+userId,
     query:{
    
    name:"beixi",age:18}
})

// params传参
this.$router.push({
    
    
     name:'/user/'+userId,
     params:{
    
    name:"beixi",age:18}
})
  1. The difference between params parameter passing and query parameter passing

    • params类型:只能通过name引入
    • query类型:既能通过name也能通过path引入
    • The query is passed 显示参数(url那里), params传递不显示参数, the parameters are in the request body,params相对于query来说较安全一点。
    • The refreshed data of the query value-passed page is still there, but the data of the params-passed value page disappears
    • The acquisition of routing parameters is different, query: this.$route.query.name, params:this.$route.params.name
  2. $routerand $routethe difference

    • $router: Routing operation object, a write-only object, generally used for routing jumps.
    • $route: Routing information object, a read-only object, generally used to obtain routing parameters.

12. The difference between computed and methods

  1. computed:
    • Computational properties, inside 函数会进行缓存,必须要有返回值, only in 依赖项发生变化的时候会执行, otherwise the value of return will be obtained directly when calling, and will not be executed again.
    • The functions inside are based 对象的属性形式存在on the call 直接使用, for example: { {msg}}.
    • Support get/set operations. Normally we only use getter properties
computed:{
    
    
	result(){
    
    
	    return this.name
	}
}
// 等价于
computed:{
    
    
	result(){
    
    
		get:function(){
    
    
		    return this.name
		},
		set:function(newValue){
    
    
			this.firstName = newValue
		}
	}
}
  1. methods:
    • The method, the function inside 不会进行缓存, will be executed every time it is called,不一定要有返回值。
    • The method inside must 使用函数调用的形式, for example: { {msg()}}
  2. scenes to be used:
    • 当某些依赖项不经常发生变化,仅仅需要取到一些返回值的时候,建议使用computed。
    • 当涉及到复杂运算的时候,建设使用computed

Thirteen. The difference between computed and watch

  1. The same point: they are all listening data里面的变量或者是由父组件传过来的props, and then execute the logic of the response.
  2. difference:
    • The method in computed 必须要有返回值, the method in watch不一定有返回值。
    • computed only executes functions when dependencies change, 具有缓存, 函数以对象的形式存在,使用的时候直接调用;watch在每次监听的值发生变化的时候都会执行回调,不具有缓存。
    • computed默认第一次加载的时候就开始监听;watch默认第一次加载不做监听,If you need to listen for the first loading, add the immediate attribute and set it to true (immediate: true).
    • computed不支持异步,Data changes cannot be monitored when there are asynchronous operations;watch支持异步操作。
    • The attribute in computed is 一对一或者多对一(一个属性受到一个或者多个属性影响), the attribute in watch is一对多(一个属性影响到多个属性)。
  3. scenes to be used
    • When it comes to complex computing scenarios, 一个属性受到多个属性影响such as: shopping cart product settlement, use computed.
    • 当一个属性影响到多个属性的时候, such as: search conditions change, use watch.

fourteen. watch

  1. Description: Detect data changes in the vue instance and execute the corresponding logic. By default, it does not listen when it is loaded for the first time.
  2. Key: It is the thing that needs to be monitored.
  3. value:
    • It can be an execution function with two parameters, one is before the change and the other is after the change. If there is only one, the default is after the change.
    • Can be a function name, must be wrapped in single quotes.
    • It can be an object, and this object has three options:
      (1) handler: a callback function, which should be executed when a change is detected.
      (2) deep: Boolean value, whether to monitor deeply. (Generally, changes in object property values ​​cannot be monitored during monitoring, but changes in arrays can be heard), and true means that deep monitoring is enabled.
      (3) immediate: boolean value, whether to execute the handler function immediately, true means to monitor immediately.
// 1.使用watch监听一个值
watch:{
    
    
	username:function(oldValue,newValue){
    
    
		console.log(newValue)
	}
	// 可以简写为
	username(oldValue,newValue){
    
    
		console.log(newValue)
	}
}

// 2.使用watch监听一个数组
watch:{
    
    
	arr(oldValue,newValue){
    
    
		console.log(newValue)
	}
}

// 3.使用watch监听一个对象

watch:{
    
    
	obj:{
    
    
		handle(oldValue,newValue){
    
    
			console.log(newValue)
		},
		deep: true,   // 开启深度监听
		immediate: true    // 立即监听
	}
}

15. The principle of vue two-way data binding

  1. Vue 双向数据绑定means 数据劫持并结合发布-订阅者模式来实现的。that the data and the view are synchronized. When the data changes, the view changes accordingly; when the view changes, the data changes accordingly.
  2. Data hijacking:vue会遍历data中的所有property(属性),并使用Object.defineProperty(obj,属性值)把这些property全部转化为getter/setter。
  3. Publish-subscriber mode: 每个组件实例都对应一个 watcher 实例,it will be in the process of component rendering “接触”过的数据 property 记录为依赖.之后当依赖项的 setter 触发时,会通知 watcher,从而使它关联的组件重新渲染。
const obj={
    
    
  name:'xiaoming'
}
Object.defineProperty(obj,'xiaoming',{
    
    
  get(){
    
    
    return obj.name
  },
  set(vakue){
    
    
    obj.name = value
  }
})

insert image description here
4. Precautions when detecting changes: Due to 数组和对象the reference type, Vue cannot detect changes in arrays and objects, but some special methods can be used to solve this problem.
(1) 对于对象: Vue cannot detect the addition or removal of properties. Since Vue will perform getter/setter conversion on properties when initializing the instance, the property must exist on the data object in order for Vue to convert it into a responsive one. For example:

var vm = new Vue({
    
    
  data:{
    
    
    a:1	// 响应式
  }
})
vm.b = 2	// 非响应式

// 解决办法: 
// 添加属性:通过Vue.set(obj,'属性名','属性值')或者this.$set()的方式
Vue.set(vm.someObject, 'b', 2) 
this.$set(vm.someObject, 'b', 2)

// 删除属性:
Vue.delete(vm.someObject, 'b') 
this.$delete(vm.someObject, 'b')

// 有时你可能需要为已有对象赋值多个新 property,比如使用 Object.assign() 或 _.extend()。但是,这样添加到对象上的新 property 不会触发更新。在这种情况下,你应该用原对象与要混合进去的对象的 property 一起创建一个新的对象。
Object.assign(this.someObject, {
    
     a: 1, b: 2 })  // 不会触发更新
this.someObject = Object.assign({
    
    }, this.someObject, {
    
     a: 1, b: 2 })

(2) 对于数组: When using the index to directly set an item in the array, or directly modify the length of the array, it will not take effect. For example:

var vm = new Vue({
    
    
  data: {
    
    
    items: ['a', 'b', 'c']
  }
})
vm.items[1] = 'x' // 不是响应性的
vm.items.length = 2 // 不是响应性的

// 修改数组中的某一项:
// 解决办法:
// 方法一:this.$set(array,index,newValue)
this.$set(this.items,0,'x')

// 方法二:array.splice(index,1,newValue)
this.items.splice(0,1,'x')

// 修改数组长度:this.items.splice(newLength)
his.items.splice(2)

For more information about the responsive principle of vue, please refer to the official website

Sixteen. The difference between Object.defineProperty() and Proxy proxy

  1. object.defineProperty() and Proxy() are the methods used in the responsive principle in vue2 and vue3 respectively.
  2. The syntax is different:
// Object.defineProperty()
Object.defineProperty(obj,属性值,{
    
    
	get(){
    
    
		return obj.xxx
	},
	set(value){
    
    
		obj.xxx = value
	}
})

// Proxy():用于创建一个对象的代理,从而实现基本操作的拦截和自定义。
```javascript
const newProxy = new Proxy(target, handler)
// target:要使用 Proxy 包装的目标对象(可以是任何类型的对象,包括原生数组,函数,甚至另一个代理)。
// handler:一个通常以函数作为属性的对象,各属性中的函数分别定义了在执行各种操作时代理 p 的行为。
  1. What Object.defineProperty listens to is 对象的每个属性,需要遍历对象的每个属性,而Proxy监听的是对象本身。(if there are nested objects, Proxy also needs to be proxied recursively, but it can be used as a lazy proxy, that is, when nested objects are used, the corresponding Proxy is created)
  2. Object.defineProperty 无法监听对象的新增属性,无法监听直接通过索引值访问数组, Proxy can.

Seventeen. The life cycle of parent-child components in vue

  1. Rendering process:
    parent beforeCreate->parent created->parent beforeMount->child beforeCreate->child created->child beforeMount->child Mounted->parent Mounted
  2. Child component update:
    parent beforeUpdate->child beforeUpdate->child Update->parent Update
  3. Parent component update:
    parent beforeUpdate->parent Update
  4. Destruction process:
    parent beforeDestory->child beforeDestory->child Destory->parent Destory

Eighteen. diff algorithm

It refers to comparing the old and new virtual nodes, returning a patch object to store the differences between the two nodes, and finally updating the dom node through the recorded information.

Nineteen. The difference between loader and plugin

  1. The loader enables webpack to parse non-js files
  2. Plugin is used to extend the functionality of webpack, and can load many plugins

Twenty. How to collect dependencies in vue

  1. Vue will compile after the instance is initialized and mounted.通过renderFunction生成虚拟DOM。
  2. 通过get()和set()函数对数据劫持更新实现响应式原理。
  3. Each component instance corresponds to one watcher 实例, which will be in the process of component rendering 把“接触”过的数据 property 记录为依赖. Then when the setter of the dependency is triggered, the watcher will be notified, so that its associated component重新渲染。
  4. The specific rendering process is 遍历虚拟DOM节点, 将前后不同之处记录在patch对象中. Finally 根据patch对象中记录的消息去更新DOM树。( 实时更新every time there is a change, it will record and update the DOM tree. React first collects all the differences 统一更改.)

21. How to understand the template compilation principle of vue

  1. core:将templete语法转成render函数。
  2. step:
    • will templete语法转成ast语法树-parserHTML
    • 对静态语法做标记(some nodes don't change)
    • 重新生成代码-codeGen, use the with syntax to wrap strings

22. Use scenarios and principles of mixin

  1. Function: 抽离公共的业务逻辑, when the component is initialized, the mergeOptions method will be called to merge. 如果混入数据和组件本身数据有冲突,采用本身数据为准. (vue3) uses a custom hook.
  2. shortcoming:容易造成命名冲突、数据冲突,数据来源不清晰。

23. Why data must be a function in the component

  1. In new Vue() 单例模式下, there is no merge operation, data里面的数据都是独立so 不存在数据污染it data用一个对象will work.
  2. Involved in the component 组件之间的相互引用, it is easy 造成数据污染possible, data must be a function, so in数据合并的时候会产生两个空间,能够避免数据污染。

24. Please explain the principle of nextTick.

  1. Is a微任务。
  2. The callback in nextTick is on 下次DOM更新循环结束之后执行的延迟回调.
  3. Can be used to get the updated DOM
  4. Data update in vue is asynchronous,使用nextTick可以保证用户定义的逻辑在更新之后执行。

25. Talk about the principle of CSS scoped in Vue

  1. effect:使当前CSS样式只作用于当前组件,避免组件之间样式的相互干扰。
  2. Principle: realized through PostCSS translation,
    • PostCSS给一个组件中的所有dom添加了一个独一无二的动态属性。
    • 给CSS选择器额外添加一个对应的属性选择器来选择该组件中dom。

26. After refreshing the browser, does the Vuex data exist? How to solve?

  1. 不存在了, the data in the store is stored in the running memory,当页面刷新的时候,页面会重新加载vue实例,store里面的数据就会被重新赋值
  2. Solution:
  • A vuex-along plugin essentially stores data in localstorage or sessionStorage
  • 在数据存储在localStorage或者sessionStorage中。

27. hash routing and history routing

  1. hash routing
  • 通过hashchange事件监听url的变化, using location.hash=xxx to read attributes, essentially changing the href attribute of window.location.
  • The hash route looks ugly with # on the URL in the address bar, but the history route will look better without it.
  • hash路由的兼容性好一点。
  • 在浏览器进行回车操作,hash路由会加载到地址栏对应的页面,不会进行http请求,改变hash不会重新加载页面,所以这也是单页面应用的必备。
//监听hash路由
window.addEventListener('hashchange', function(){
    
     
    // 监听hash变化,点击浏览器的前进后退会触发
 })
  1. history route
    • history路由是通过调用history.pushState()或者history.replaceState()方法来进行路由跳转。
    • The history route does not have # on the address bar URL, which looks neat and beautiful
    • history路由的兼容性较hash路由差一点
    • 在浏览器进行回车操作,history路由会进行http请求,因此需要后端数据,否则会报错。
    • The history route uses the browser's history stack, which provides the function of modifying the history. However, when the modification is made, although the current URL is changed, the browser will not immediately send a request to the backend.

Twenty-eight. Vue's page rendering process, what happened during the mounting process

  1. Call init() to initialize when instantiated
  2. Calling $mount() to mount is actually calling mountComponent. In addition to calling some lifecycle hook functions, the most important thing is updateComponent.
  3. updateComponent will be passed to the rendering watcher, and the function will be executed whenever the watcher update is triggered when the data changes.
  4. vm._render creates and returns VNode, and vm._update accepts VNode and converts it into a real node.

29. How to customize the command

  1. Global registration, the first parameter: command name; the second parameter: command function
Vue.directive('focus',{
    
    
  inserted:function(el){
    
    
    el.focus()
  }
})
  1. Local registration: register in the current component
directives:{
    
    
  focus:{
    
    
    inserted:function(el){
    
    
      el.focus()
    }
  }
}
  1. use
<div v-focus />

Thirty. Auxiliary functions of vuex

The state auxiliary function is mapState(), the actions auxiliary function is mapActions(), the mutations auxiliary function is mapMutations(), and the getters auxiliary function is mapGetters().

Thirty-one. Talk about your understanding of keep-alive in your vue

  1. Components wrapped by keep-alive具有缓存效果
  2. It is a built-in component of Vue,能在组件切换过程中将状态保留在内存中,防止重复渲染DOM。
  3. Two parameters:
  • include='component name': specify that only these components will be cached
  • exclude='component name': specify that these components will not be cached, and the remaining components will be cached

32. Is the virtual DOM necessarily faster?

  1. What is DOM: Document Object Model, 文档对象模型, is a set of rules for managing html documents, a DOM tree is a complete html document.
  2. effect:将web网页和编程语言连接起来,通过操作脚本以改变文档的结构、样式和内容。
  3. What is virtual DOM:js对象模拟出来的DOM节点,是一种编程概念,一种模式,他会和真实DOM同步
  4. 虚拟DOM可以提升性能但不一定更快。(Click the button to add one. It is faster to directly operate the real DOM)
  5. 真实DOM在直接操作的时候会引起页面的回流或重绘,会造成性能下降,虚拟DOM通过diff算法更新不同虚拟DOM节点,进而达到重新渲染的目的
  6. advantage:
    • 减少dom操作,提高了性能,更新快
    • 无需手动操作DOM只需要关心view-modal里面的逻辑
    • More convenient cross-platform operations, such as server rendering
  7. shortcoming:
    • 无法进行极致优化, for applications with extremely high performance requirements, the virtual DOM cannot be optimized to the extreme
    • 首次渲染大量dom时,由于多了一层虚拟dom的计算,速度比innerHtml插入慢

Thirty-three. Talk about the understanding of key

  1. Concept: 给每一个节点一个唯一的标识, you can find the corresponding node according to the key value
  2. effect
    • 尽可能的复用DOM更高效的更新虚拟DOM
    • If key is not used: Vue will modify/reuse the algorithm of the same type of elements as much as possible
    • If key is used: the order of elements will be rearranged based on the change of key, and elements whose key does not exist will be removed
  3. Note: If the dom is very simple, using the key may not necessarily improve the diff algorithm
  4. Why do not generally use index as a key: If some deletion and addition operations are performed, some keys will not be matched, resulting in some unnecessary dom updates and low rendering efficiency.

34. Reasons for the slow loading of the first screen

  1. What is the slow loading of the first screen: It takes too long from the time the user enters the URL in the browser to the rendering of the content on the first screen.
  2. Reasons for slow loading:
    • network delay
    • Resource file size is too large
    • Whether the resource sends the request repeatedly
    • When loading the script, the rendering content is blocked
  3. solution
    • Reduce the size of the entry file
    • Static resource local cache
    • Resources are loaded on demand and asynchronously
    • Compression and lazy loading of image resources
    • CSS code is placed in the head, JS code is placed in the tail
    • Enable GZip compression

Thirty-five. Why are v-if and v-for in vue not recommended to be used together?

  1. 在vue2中v-for的优先级高于v-if。When used together, it is necessary to traverse one side before each judgment, wasting performance.
  2. v-for has lower priority than v-if in vue3. When used together, an error will be reported directly.
  3. Solution: 分开写,将v-if写到外层,It can be wrapped with a temple tag.

Thirty-six. The difference between v-show and v-if

  1. The same point: they all control whether the element is displayed on the page
  2. difference:
    • v-show is essentially pass 控制css的display:none属性. Even if it is hidden, the dom structure is still there, 是一种视觉上的隐藏,v-if是真正意义上的删除和添加。
    • v-show doesn't trigger lifecycle hooks, v-if does.
    • v-show consumes less performance, and v-if consumes more performance, so当需要频繁的切换的时候建议使用v-show。

37. Observer model

  1. When Vue is initialized, the listener property is hijacked through observe.
  2. Define update function and watcher.
  3. Generally, there will be multiple watchers, so a housekeeper dep will be used to manage multiple watchers.
  4. When the data in the data changes, the corresponding housekeeper dep will be found to notify all watchers to call the update function to update the dom.

Thirty-eight. Publish subscriber mode

  1. The object that triggers the event is called the publisher
  2. Objects that receive notifications are called subscribers
  3. For example: event binding in js is the publish-subscribe mode

Thirty-nine. How does the parent component monitor the life cycle of the child component

  1. $emit在子组件的生命周期钩子里面用$emit触发事件,父组件里用v-on接收
// 子组件
mounted(){
    
      // 监听子组件的挂载完成
	this.$emit('mounted')
}
// 父组件监听后执行一些相应的操作
<Child @mounted='doSomething' />
methods:{
    
    
	doSomething(){
    
    }
}
  1. @hook
// 子组件
mounted(){
    
    
	console.log('111')
}
// 父组件监听后执行一些相应的操作
<Child @hook:mounted='doSomething'>
methods:{
    
    
	doSomething(){
    
    }
}

40. Vue component communication

  1. 父子组件通信父组件通过v-bind绑定传递的值,子组件中通过props接收。子组件中通过$emit('函数名',传递的值),父组件中通过v-on接收函数并定义。
// 父组件,以下都是部分代码
<div class="box" @click="clickAction">
   我是父组件:{
    
    {
    
    msg}}
</div> 
<Child :count="count" @message="message"/>
data(){
    
    
	return {
    
    
      msg:'你好,我的世界',
      count: 0
	}
},
methods:{
    
    
	// 向子组件传值
 	clickAction(){
    
    
       ++this.count
    },
    // 接收子组件传过来的值
	message(data){
    
    
	   this.msg = data
	}
}

// 子组件
<button @click="clickChild">我是子组件:{
    
    {
    
    count}}</button>
// 通过props接收父组件传过来的值
props: {
    
    
    count: {
    
    
        type:Number,
        default:0
    }
},
data(){
    
    
   return {
    
    
      msg: ''
    }
},
methods:{
    
    
	// 通过$emit向父组件传值
    clickChild(){
    
    
      this.$emit('message','这是我在测试父子组件通信')
    }
}

insert image description hereinsert image description here
2. 祖孙组件之间的通信: Used in conjunction with inheritAttrs: false in the transfer layer v-bind="$attrs" v-on="$listeners".

  • v-bind="$attrs:包含了父组件中不被props所识别的特性绑定,如果当前组件没有声明props则会继承父组件的所有绑定的值。
  • v-on=“$listeners”:包含了父作用域中的(不含.native修饰器的)v-on事件监听器
  • inheritAttrs: false 可以关闭自动挂载到组件根元素上的没有在 props 声明的属性( see also )
// 子组件
<GrandChildA v-bind="$attrs" v-on="$listeners"/>

// 孙子组件
<div @click="clickGrandSonA">这是孙子组件A{
    
    {
    
     $attrs }}</div>
methods:{
    
    
 clickGrandSonA(){
    
    
     this.$emit("message",'这是测试祖孙组件之间的通信');
  }
}

insert image description here
3. 利用provide和inject实现祖孙组件通信
provide: Object | () => Object, which is an object or a function that returns an object.
inject: Array | { [key: string]: string | Symbol | Object }, which is an array of strings or an object whose key is the local binding name.
Specific usage:

// 父组件:
<div class="box" @click="clickAction">
   我是父组件:{
    
    {
    
    msg}} -- {
    
    {
    
     coo }} -- {
    
    {
    
     obj.name }}
</div>
data(){
    
    
   msg:'你好,我的世界',
   count: 0,
   coo: "CSS",
   obj:{
    
    
     name:'wangjiajia'
   }
},
provide(){
    
    
  return {
    
    
    msg:this.msg,   // 方式一:直接传值
    obj:this.obj,   // 方式二:传入一个可以监听的对象
    computedCount:()=>this.count,   // 方式三:通过computed来计算注入的值
    app:this    // 方式四:提供祖先组件的实例,缺点是造成传递过去很多没用的东西,冗余。
  }
},
methods:{
    
    
  clickAction(){
    
    
    ++this.count,
    this.msg = '世界真美好',
    this.obj.name = 'wangtongtong',
    this.coo = '通过app引用'
  },
}

// 子组件
<GrandChildB />   // 只是一个过渡的作用

// 孙子组件
<div @click="clickGrandSonB">
        我是孙子组件B{
    
    {
    
     msg }} -- {
    
    {
    
     count }} -- {
    
    {
    
     this.app.coo }} --{
    
    {
    
       obj.name }}
</div>
computed:{
    
    
 count(){
    
    
   return this.computedCount()
 }
},
inject:['msg','computedCount','app','obj'],
methods:{
    
    
  clickGrandSonB(){
    
    
    this.msg = '测试祖孙组件传值'
    this.obj.name = 'caocongyouren'
    this.app.coo = '你礼貌吗!'
  }
}

insert image description here
insert image description hereinsert image description here
说明:这种方法下要注意,直接传值是不可以实现响应式的,实现数据响应式具体方法有:
* 传入监听对象
* 利用computed计算属性注入
* 传入整个组件实例(缺点是可能传入一些没用的量,造成冗余)

  1. 利用中央事件总线实现任意组件之间的通信
    • Global registration: Vue.prototype.$bus = new Bus() / new Vue()
    • Launch event: this.bus.bus .bus.emit(‘foo’)
    • Receive events: this.bus.bus .bus.on(‘foo’)
// 父组件
mounted(){
    
    
  this.$bus.$on('mooValue',this.receive)
},

methods:{
    
    
  clickAction(){
    
    
    this.$bus.$emit('dooValue',"Vue")
  }
  receive(data){
    
    
  	this.moo = data
  }
}

// 孙子组件
mounted(){
    
    
  this.$bus.$on('dooValue',this.receive)
},
methods:{
    
    
  clickGrandSonB(){
    
    
	this.$bus.$emit('mooValue','React')
  },
  receive(data){
    
    
  	this.doo = data
  }
}

insert image description here

Forty one. vuex

  1. What is vuex, why use vuex
    • vuex是vue官方提供的一种集中式管理vue多组件共享状态数据的插件。
    • vuex可以帮助我们管理共享状态,实现跨组件通信。
    • Suitable for larger types of vue projects
  2. installation method
    • You can choose to install when scaffolding creates a project
    • Install using npm or yarn
      • npm install vuex@next --save
      • yarn add vuex@next --save
  3. configuration
    • Create a store folder and create an index.js file under the folder
    • Introduced in the main.js file and mounted on the vue instance.
import Vue from 'vue
import App from './App.vue'
import store from './store'
new Vue({
    
    
	store,
	render:h=>h(App)
}).$mount('#app')
  1. Core idea

    • State
    • Getters
    • Mutations
    • Actions
    • Modules
  2. Graphical relationship
    insert image description here

  3. State: Provides a unique public data source, and all shared data is stored in the state of the store, similar to data.

    • Method 1: Use directly in the label:<p>{ {$store.state.name}}<p>
    • Method 2: call via this:this.$store.state.name
    • Method 3: Through the helper function: mapState(['name','age','count'])写在当前组件的computed中.
  4. Mutations: the only way to change data, accept state as the first parameter, the second parameter is optional

    • method one:通过commit触发:this.$store.commit('mutations里面定义的函数名字','可选参数')
    • Method Two:通过辅助函数:mapMutations(['函数名']) => this.函数名('可选参数') => 写在methods中。
  5. Actions: Asynchronous operation storage, essentially triggering mutations to change data.

    • method one:使用dispatch触发:this.$store.dispatch("mutations里面定义的函数名字",'可选参数')
    • Method Two:通过辅助函数:mapActions['函数名'] => this.函数名('可选参数') => 写在methods中。
  6. Getters: process data to form new data, with cache

    • method one:在当前组件的computed中定义一个函数,在这个函数中直接使用this.$store.getters.'getters中定义的函数名'
    • Method Two:使用辅助函数:mapGetters(['函数名']),写在当前组件的computed中。
      注意:辅助函数都可以配置别名
  7. Modules: When encountering large-scale projects, the amount of data is more complicated. Write each state in a file, which has its own state, mutations, etc., and then import it in modules,

  8. Look at a specific example to get familiar with the use of vuex

store.js file

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
    
    
  // state: 共享数据,相当于data
  state: {
    
    
    name: 'wangjiajia',
    age: 25,
    count: 0,
    todos: [
      {
    
     id: 1, done: true },
      {
    
     id: 2, done: false },
      {
    
     id: 3, done: false },
    ]
  },
	// getters:对数据进行加工处理形成新的数据,具有缓存
	getters: {
    
    
		// 过滤出done为true的项
	    doneTodos: state => {
    
    
	      return state.todos.filter(item => item.done)
	    },
	    // 传入一个id值,从当前数组中找到第一个id等于传入值的项
	    getTodoById: (state) => (id) => {
    
    
	      return state.todos.find(item => item.id === id)
	    }
 	},
 	// mutations:改变state中数据的唯一办法
 	mutations: {
    
    
 	  // 传入一个值,使得count每次加上这个值
      addCount(state,num){
    
    
        state.count += num
      },
      // 使得count每次自减1
      reduceCount(state){
    
    
        --state.count
      },
      ['ADDCOUNT'](state){
    
      // 可以配置方法别名
      ++state.count
    }
    },
    // actions: 异步操作,本质上也是通过触发mutations从而改变state里面的数据
    actions: {
    
    
	    asyncAdd(context,data){
    
    
	      setTimeout(()=>{
    
    
	        // 可以调用mutation里面的方法
	        context.commit('addCount',data)
	
	        // 可以调用另一个异步
	        // context.dispatch('asyncReduce')
	      },1000)
	    },
	    asyncReduce(context){
    
    
	      setTimeout(()=>{
    
    
	        // 可以调用mutation里面的方法
	        context.commit('reduceCount')
	      },1000)
   	 },
   	 // modules:复杂业务时候,将每一个状态单独写在一个文件中,最后在这里导入
   	 modules:{
    
    
		app,
		cell
    }
  },
})

vue statement:

<button @click="clickAdd">点我增加</button>
    <div class="direct">直接引用:{
    
    {
    
     $store.state.name }} -- {
    
    {
    
     $store.state.age }} -- {
    
    {
    
     $store.state.count }} -- {
    
    {
    
     doneTodos }} -- {
    
    {
    
     getTodoById(2) }}
 </div>
<button @click="clickReduce">点我减少</button>
<div class="direct">通过辅助函数:{
    
    {
    
     name }} -- {
    
    {
    
     age }} -- {
    
    {
    
     count }} -- {
    
    {
    
     doneTodosCount }} -- {
    
    {
    
     doneTodosId }}</div>
<button @click="clickAsync">点我触发一个异步任务</button>

import {
    
     mapActions, mapMutations, mapState,mapGetters } from 'vuex';
export default ({
    
    
	name:'ChildStore',
	computed:{
    
    
    ...mapState(['name','age','count']),  // mapState({name:state=>state.name,age:'age'})
    // 使用辅助函数
    ...mapGetters(['doneTodos','getTodoById']),    // 可以配置别名:mapGetters({doneCount:'doneTodos'})
    doneTodosCount () {
    
    
      return this.$store.getters.doneTodos
    },
    doneTodosId () {
    
    
      return this.$store.getters.getTodoById(2)
    }
  },
  methods:{
    
    
    // 辅助函数
    ...mapMutations(['addCount','reduceCount','ADDCOUNT']),  // 可以配置别名:mapMutations({increment:'addCount'})
    ...mapActions(['asyncAdd','asyncReduce']),    // 可以配置别名:mapActions({increment:'asyncAdd'})
    clickAdd(){
    
    
      this.$store.commit('addCount',5)  // 每次增加5,通过commit
      // this.addCount(5)   // 通过辅助函数
    },
    clickReduce(){
    
    
      // this.$store.commit('reduceCount')  // 每次减少1,通过commit
      this.reduceCount()   // 通过辅助函数
      // this.$store.commit('ADDCOUNT')
      this.ADDCOUNT()  // 方法别名
    },

    //异步操作
    clickAsync(){
    
    
      // this.$store.dispatch('asyncAdd',5)   // 通过dispatch触发一个增加的异步操作
      // this.$store.dispatch('asyncReduce')   // 通过dispatch触发一个减少的异步操作
      this.asyncAdd(5)   // 通过辅助函数
      // this.asyncReduce()   // 通过辅助函数
    }
  }
})

insert image description here
For more information about vuex, please refer to the official website

Guess you like

Origin blog.csdn.net/du_aitiantian/article/details/128400634