The difference between Map and Object
ES6 provides a Map class, which is a new data structure, which is a bit like Object
the difference:
Object is essentially a collection of key-value pairs in a hash structure. It can only use simple data types such as strings, numbers, or symbols as keys , which brings great limitations.
The Map class inherits Object and has made some extensions to Object functions. The key of Map can be any data type.
The difference between the two mainly has the following points:
Collision of the same name
We know that the object actually opens up a piece of memory on the heap, and the key of the Map actually stores the address of this piece of memory. As long as the addresses are different, they are two different keys, which solves the collision problem of properties with the same name, which is obviously impossible for traditional Objects.
Iterable
Map implements iterators, which can be traversed with for...of, but Object cannot.
length
Map can get the length directly, but Object cannot.
orderliness
The elements filled in the Map will maintain the original order, but Object cannot.
expandable
Map can be expanded using ellipsis syntax, but Object cannot.
The difference between Map and Set
== Map == is a structure of a set of key-value pairs, with extremely fast search speed. Initializing Map requires a two-dimensional array, or directly initializing an empty Map.
Map has the following methods:
var m = new Map(); // 空Map m.set('Adam', 67); // 添加新的key-value m.set('Bob', 59); m.has('Adam'); // 是否存在key 'Adam': true m.get('Adam'); // 67 m.delete('Adam'); // 删除key 'Adam' m.get('Adam'); // undefined
Since a key can only correspond to one value, a value is placed in a key multiple times,Subsequent values will overwrite previous values:
var m = new Map(); m.set('Adam', 67); m.set('Adam', 88); m.get('Adam'); // 88
== Set == is also a set of keys, similar to Map. But the difference is that Set does not store value, and its key cannot be repeated . To create a Set, you need to provide an Array as input, or create an empty Set directly:
var s1 = new Set(); // 空Set var s2 = new Set([1, 2, 3]); // 含1, 2, 3
Duplicate elements will be automatically filtered in the Set** (Note: The number 3 and the string '3' are different elements)**:
var s = new Set([1, 2, 3, 3, '3']); s; // Set {1, 2, 3, "3"}
Set has the following methods:
//通过add(key)方法可以添加元素到Set中,可以重复添加,但不会有效果 s.add(4); s; // Set {1, 2, 3, 4} s.add(4); s; // 仍然是 Set {1, 2, 3, 4} //通过delete(key)方法可以删除元素 var s = new Set([1, 2, 3]); s; // Set {1, 2, 3} s.delete(3); s; // Set {1, 2} add(value):添加某个值,返回Set结构本身。 delete(value):删除某个值,返回一个布尔值,表示删除是否成功。 has(value):返回一个布尔值,表示该值是否为Set的成员。 clear():清除所有成员,没有返回值。
Summarize:
1. A Map object is a collection of key-value pairs, similar to a JSON object, but the key can be not only a string but also various other types of values, including objects, which can become the key of a Map. The methods are: set get has delete
var map = new Map(); var obj = { name: '小缘', age: 14 }; map.set(obj, '小缘喵'); map.get(obj); // 小缘喵 map.has(obj); // true map.delete(obj) ;// true map.has(obj); // false
2. The Set object is similar to an array, and the values of its members are unique
What are the functions of filter, every, and flat of the array
The role of filter
A new array is created with all elements that meet the criteria
the role of every
Query whether the elements in the array meet the requirements, return true if they are all satisfied, otherwise return false
the role of some
Query whether there are elements in the array that meet the requirements, if they are satisfied, return true and do not continue to execute, otherwise return false
The role of flat
Flatten arrays, such as converting two-dimensional arrays to one-dimensional arrays, and three-dimensional arrays to one-dimensional and two-dimensional arrays. It accepts a parameter, if not passed in, the default is 1, which means the number of layers to be flattened.
ES6 new features
1.let keyword
The let keyword is used to declare variables. Variables declared using let have several characteristics:
- Duplicate statement not allowed
- block scope
- There is no variable hoisting (cannot be used before undefined)
- does not affect the scope chain
2. const keyword
The const keyword is used to declare constants. The const declaration has the following characteristics:
- declaration must assign an initial value
- Identifiers are generally uppercase
- Duplicate statement not allowed
- Value does not allow modification
- block scope
3. Variable deconstruction assignment
ES6 allows to extract values from arrays and objects and assign values to variables according to a certain pattern, which is called destructuring assignment.
//1. 数组的结构
const Hua = ['小花','刘花','赵花','宋花'];
let [xiao, liu, zhao, song] = Hua;
// 结构赋值完,可以直接使用
console.log(xiao);
console.log(liu);
console.log(zhao);
console.log(song);
//2. 对象的解构
const zhao = {
name: '赵本山',
age: '不详',
xiaopin: function(){
console.log("我可以演小品");
}
};
let {
name, age, xiaopin} = zhao;
console.log(name);
console.log(age);
console.log(xiaopin);
xiaopin();
let {
xiaopin} = zhao;
xiaopin();
4. Template strings
The template string (template string) is an enhanced version of the string, identified by backticks (`), features:
- Newline characters can appear in the string
- Variables can be output in the form of ${xxx}
5. Simplify object writing
ES6 allows variables and functions to be written directly inside curly braces as properties and methods of objects. This writing is more concise.
6. Arrow functions
ES6 allows the use of "arrows" (=>) to define functions. There are only two ways to write arrow functions, omitting parentheses and omitting braces. (note: it does not have its own this)
Points to note about arrow functions:
- If there is only one formal parameter, parentheses can be omitted (omit parentheses)
- If the function body has only one statement, the curly braces can be omitted, and the return value of the function is the execution result of the statement (the curly braces are omitted)
- Arrow function this points to the value of this in the scope where it was declared
- Arrow functions cannot be instantiated as constructors
- Cannot use arguments
7.Symbol
- Symbol basically uses
ES6 to introduce a new primitive data type Symbol, which represents a unique value. It is the seventh data type of the JavaScript language and is a data type similar to strings.
Symbol usage scenario: Add properties and methods to objects
Symbol features:
The value of Symbol is unique, which is used to solve the problem of naming conflicts.
Symbol value cannot be operated with other data.
The object properties defined by Symbol cannot be traversed by for...in loop, but you can use Reflect.ownKeys to get all the key names of the object.
注: 遇到唯一性的场景时要想到 Symbol
USONB you are so niubility(JavaScript七种数据类型)
U undefined
S string symbol
O object
N null number
B boolean
8.Promise
Promises are a new solution to asynchronous programming introduced by ES6. Syntactically, Promise is a constructor that encapsulates an asynchronous operation and can obtain its success or failure result.
Promise constructor: Promise (excutor) {}
Promise.prototype.then method
Promise.prototype.catch Exclusive guard:
//实例化 Promise 对象,成功是resolve,失败是reject
const p = new Promise(function(resolve, reject){
setTimeout(function(){
// let data = '数据库中的用户数据';
// resolve(data);
let err = '数据读取失败';
reject(err);
}, 1000);
});
//调用 promise 对象的 then 方法
p.then(function(value){
console.log(value);
}, function(reason){
console.error(reason);
})
// 发送ajax请求,接口地址: https://api.apiopen.top/getJoke
const p = new Promise((resolve, reject) => {
//1. 创建对象
const xhr = new XMLHttpRequest();
//2. 初始化
xhr.open("GET", "https://api.apiopen.top/getJ");
//3. 发送
xhr.send();
//4. 绑定事件, 处理响应结果
xhr.onreadystatechange = function () {
//判断
if (xhr.readyState === 4) {
//判断响应状态码 200-299
if (xhr.status >= 200 && xhr.status < 300) {
//表示成功
resolve(xhr.response);
} else {
//如果失败
reject(xhr.status);
}
}
}
})
//指定回调
p.then(function(value){
console.log(value);
}, function(reason){
console.error(reason);
});
Common Promise Interview Questions
- What problem does Promise solve?
- What are the industry implementations of Promise?
- What are the commonly used APIs for Promise?
- Can you write a Promise that conforms to the Promise/A+ specification?
- What is the execution process of Promise in the event loop?
- What's wrong with Promises, and how can they be fixed?
What problems did you encounter in the project? how to solve it
-
process token
-
Data-driven views are not immediate (components are not rendered asynchronously to get DOM elements)
Solution: use the updated hook function
this.$nextTick()
setTimeOut()
Want to manipulate DOM immediately Vue is updated asynchronously
After the data is updated, because the view update is asynchronous, a call is required
this.$nextTick(()=>{可以拿到更新之后的DOM})
Note: If there is a v-if, it cannot be used
-
Regarding the problem of large numbers of data returned by the backend
The problem of large numbers in js: (beyond the range of js safe integers)
The backend returned some id values, and then I used the id value to request the response data, but found that the request was not available, and coordinated with the backend, and found that the id I converted into a numeric value did not match the string id given by the backend
I have never been able to figure out what caused it. Later, I went to Baidu and found that it was because js could not accurately represent the data exceeding 2 to the 53rd power.
I went to the backend again and asked him to modify the id, but the backend said it couldn’t be changed
I can only find a solution by myself, and later found a plug-in to solve this problem:
npm i json-bigint
①Import
import jsonBig from 'json-bigint'
②Convert to value:
const obj =jsonBig.parse(JSON数据)
obj.property name.toString() —>valueLarge numbers of data to JSON data use
JSON.stringify(JSONBig.parse(jsonStr))
----->JSON data ----->pass to the backend
The difference and use of Promise.all and Promise.race
Promise.all
For example, when P1 and P2 in the array are all executed, the page is displayed.
It is worth noting that the order of the returned array results will not change , even if the return of P2 is faster than the return of P1, the order is still P1, P2
Promise.all returns success array successfully ,
Failed to return failed data, once failed, it will not continue to go down
let p1 = Promise.resolve('aaa') let p2 = Promise.resolve('bbb') let p3 = Promise.reject('ccc') let p4 = Promise.resolve('ddd') Promise.all([p1, p2, p3, p4]).then(res => { console.log(res); //返回数组 }).catch(err => { console.log(err); })
promise.race()
Promise.race means race, that is to say, whichever result in Promise.race([p1, p2, p3]) is obtained quickly will return the result, regardless of whether the result itself is success or failure
scenes to be used:
When we do an operation, we may
同时
need the data returned by different interfaces. In order to consider the order of the returned data, we can usePromise.all
Several servers provide several interfaces
同样的服务
. We don’t know which interface is faster, so we can use itPromise.race
. Which interface’s data comes back first, we will use which interface’s data.
What is the essence (principle) of v-mode
v-model
The essence is the syntactic sugar of v-bind:value="" and @input eventWhen there are value attributes and input custom events on a component at the same time, and the operation is the same variable, you can use v-model to simplify
How to modify the default rule attributes customized by v-model by
model
modifyingmodel: { prop: 'isFollowed', event: 'changed' }
knowledge points
Less syntax: @import ' ';must be quoted
Introduce import in main.js, only comments are allowed between imports and no other statements are allowed
import import rules:
1. The downloaded third-party package: import: 'package name' (go to node_modules to find the index.js file)
2. Manual import: import: './filename'
Push commit:
The meaning of git push -u origin master:
Complete writing: git push --set-upstream origin master:master
Parse:
master: master is to submit the local master to the remote warehouse master branch master
–set-upstream is for each latest or successfully pushed branch, add upstream (tracking) reference abbreviated as -u (simple understanding is to remember this submission information, you can directly git push the next submission)
origin: is the added remote warehouse address
Create an instance:
const request = axios.create ({})
==Advantages: == You can request different servers according to different paths, if written in main.js, the code will appear bloated or this: the axios.defaults.baseURL:
path will be directly written to death
Lazy loading:
Benefits: Increase the speed of the first screen Vue is a single page (only one html)
How to improve loading speed?
If the original import method is used, webpack will package all components into a js file when packaging, and load the js when the page is just refreshed
Lazy loading: webpack will package the lazy-loaded components individually into js files one by one, which will be loaded when the user jumps to the corresponding component
Named slots:
New syntax: v-slot must be wrapped with a template tag: the name is abbreviated as #name
Old syntax: slot="name" in specific tags
example:<i slot="名字"></i>
JSON data:
The format of double quotes: attributes and values are double quotes
json data does not support undefined and functions
Objects and arrays are converted to json data: JSON.stringfly()
the opposite is:JSON.parse
Deep copy:
- Positive and deserialization (disadvantage: cannot contain undefined and function data)
- Deep copy through recursion
Encapsulation request parameter passing requirements:
- If it is directly written as follows in data ①, the parameter passing in the encapsulated function should be ②
//①
data(){
return {
a:'',
b:''
}
}
//②
export const login = (tel,code) => {
return request({
method: 'POST',
url: '/v1_0/authorizations',
data:{
mobile:tel,
code:code
}
})
}
- Shorthand:
Write an object in data and write data to the object as follows:
data () {
return {
user: {
mobile: '',
code: ''
}
}
},
//
export const login = data => {
return request({
method: 'POST',
url: '/v1_0/authorizations',
data
})
}
Token value related knowledge points:
After the first successful login, the server returns the token value
In order to prevent the loss of the refresh token value, the data needs to be backed up to local storagewindow.localStorage.setItem('仓库名字',JSON.stringify())
Notice:Local storage can only store string format JSON.stringify()
serialization
That is, serialize when storingJSON.stringify()
Deserialize when fetchingJSON.parse
The difference between vuex and local storage:
vuex: ① vuex is responsive data ② temporary storage
local storage:
sessionStorage: life cycle - the browser closes the data disappears, refreshes the data does not disappear, the data is shared by the current page, the memory is 5M, and the stored data is JSON data
localStorage: lifecycle-permanent, same browser data sharing (same domain name, must be same host name), memory size 20M, stored data is JSON data
How is the token stored in your project?
1. Save vuex first 2. Save local storage
The destructured attribute name must be the same as the attribute name in the response {data}
Password encryption (md5.js)
If the backend needs password encryption, you need to download this plugin
How to do aging processing of local storage?
①Save token—>additional timestamp ( timer: +new Date() )
②When using token, first get the current timestamp - timestamp in storage / 1000 / 60 (minutes) > time difference
③If it times out, jump to the page to let the user log in again. If there is no timeout, use the token normally
css in vue uses image path:background: url("~@/assets/banner.png");
Routing jump:
Both name and path are routing jumps, but name is better maintained
Click on the login to jump to another page Programmatically: @click="$router.push('/login')"
this is the shorthand method
Specifically written:
this.$router.push({
path:'/login',
...需要传递的参数
})
You need to go back to another page after the jump: $router.back()
or: $router.go(-1)
-1 to go back once
There is no need to write this in the difference expression
What is a Single Page Application (SPA):
One of the core ideas of Single Page Application (SPA) is to update the view without re-requesting the page. Simply put, when loading the page, it will not load the entire page, but only update the content in a specified container. For most single-page applications, the officially supported vue-router is recommended.
Among them, NetEase Music uses a single-page application
Vue's routing implementation mode: hash mode and history mode
hash mode:
Vue-router defaults to hash mode, which uses the hash of the URL to simulate a complete URL. When the URL changes, the page will not reload. # is the hash symbol, the Chinese name is the hash symbol or anchor point, and the value after the hash symbol is called the hash value.
The hash mode of the route is realized by using the window to listen to the onhashchange event, that is to say, the hash value is used to guide the browser's actions and has no effect on the server. The HTTP request will not include the hash value, and each time the hash is changed Value, will add a record in the browser's access history, use the "Back" button, you can return to the previous position. Therefore, the hash mode changes according to the hash value, and renders different data at the specified DOM position according to different values.
history mode:
The URL in the hash mode will have a # sign, which affects the appearance of the URL, but the # sign will not appear in the history mode. This mode makes full use of history.pushState() to complete the URL jump without reloading the page.When using the history mode, you need to add mode:'history' to the routing rule configuration, the example code is as follows:
// main.js 文件
const router = new VueRouter ({
mode:'history',
routes: [...]
})
There are two new APIs for history in HTML5, namely history.pushState()
andhistory.replaceState()
Can modify the browser history stack, and popState
event listeners to state changes.
They all receive 3 parameters, namely state object (state object), title (title) and address (URL). Below we briefly introduce the meaning of these three parameters.
(1) State object (state object): A JavaScript object associated with a new history entry created with the pushState() method.
(2) title (title): FireFox browser currently ignores this parameter. For security reasons, it is recommended to pass an empty string. Alternatively, a short title can be passed in, indicating the state to enter.
(3) Address (URL): the address of the new history entry.
What is the vue family bucket? What are there?
Vue family bucket generally refers to scaffolding vue-cli, routing vue-Router, state management mode vuex, Axios, elementUI and other ui frameworks and packaging tools webpack
command package:
npm i -g nrm — switch mirror sources
npm ls view
npm i package
or npm i -g cnpm
How to access vuex data in js file?
Import the store of the vuex warehouse
Request interceptor:
Function: uniformly inject the request header token into the authorized interface
Add a judgment condition:
If the user is not logged in, the token value is null and an error is reported, so add a judgment condition if(user && user.token){} === if(null && null.token)
and if it is null, exit the judgment condition
Add the headers request header in the config configuration item
After adding headers to the request interceptor, you can comment out the headers in api/user.js
Insensitive refresh (response interceptor)
Short token: used to send requests, carried in the request header, usually expires in two hours
refresh_token
: The long token is used to obtain a new short token, which usually expires in 14 days
Can the expiration time of the short token be extended, such as 14 days?
Answer: No, because it involves security issues, to prevent the token from being stolen (only if the two are stolen together will the information be leaked) we can encrypt the login password—md5.js encryption, (MD5 encryption is essentially a plug-in, calling his method The encrypted code can be generated) We need to cooperate with the backend (backend decryption)
Ideas for using long tokens:
-
When the user sends a request, the backend returns 401, indicating that the token expires. At this time, the 401 code returned by the backend should be uniformly monitored.
-
When a 401 error is detected,
refresh_token
send a request with a long token to obtain the latest token -
Automatically resend the request sent by the user last time
-
Add response interceptor
- main effect:
- Refresh without feeling
- Unified processing of the data returned by the backend
- Unified processing of back-end data errors
- main effect:
Ideas for using long tokens (specific steps):
-
When the user sends a request, if the backend returns 401, it means that the token has expired. At this time, we need to uniformly monitor the 401 code returned by the backend.
-
We need to add a response interceptor, and monitor and judge whether the token expires in the error reporting function in the interceptor. The code is as follows:
if (error.response.status === 401) { console.log('token过期') }
-
-
When a 401 error is detected,
refresh_token
send a request with a long token to obtain the latest token-
Note: you can’t use request to send,
会死循环
because the request is set with a request interceptor, and the old token will be injected (provided that you encapsulate the request yourself). The code example is as follows:// 用axios发请求 const { data } = await axios({ url: 'http://toutiao.itheima.net/v1_0/authorizations', method: 'PUT', headers: { Authorization: `Bearer ${ store.state.token.refresh_token}` /* 怎么拿refresh_token */ } })
-
-
Then use the new token to save it in vuex and save it to local storage. You cannot use auxiliary functions in the js file, and use destructuring assignment to overwrite the old token. The code is as follows:
store.commit('setUser', { ...store.state.token, token: data.data.token })
-
Automatically resend the request sent by the user last time
return request(error.config)
The complete code is as follows:
// 添加响应拦截器
request.interceptors.response.use(function (response) {
// 2xx 范围内的状态码都会触发该函数。
// 对响应数据做点什么
return response
}, async function (error) {
/* //监测token过期 */
if (error.response.status === 401) {
// console.log('token过期')
// 发请求,刷新token
// 注意:不能用request发,会死循环,因为request设置了请求拦截器,会注入老token
// 用axios发请求
const {
data } = await axios({
url: 'http://toutiao.itheima.net/v1_0/authorizations',
method: 'PUT',
headers: {
Authorization: `Bearer ${
store.state.token.refresh_token}` /* //怎么拿refresh_token */
}
})
// 新token存到vuex中,存到本地存储,在js文件中不能用辅助函数
// 利用解构赋值覆盖旧token
store.commit('setUser', {
...store.state.token, token: data.data.token })
// 再发一次上次发送过得请求(error里有上一次发送的地址和错误的token)
return request(error.config)
}
// 超出 2xx 范围的状态码都会触发该函数。
// 对响应错误做点什么
return Promise.reject(error)
})
To modify the global foreign component style in the component, you need to add /deep/ (must be less syntax) (use ::v-deep in scss syntax)
JSON.parse() is deserialization, which converts a string in json format into an object (the string in json format must be in double quotes, and its attributes and values are wrapped in double quotes) JSON.parse('sfdsfsa')
. The quotation marks are the wrong json format and an error will be reported
Why do list scrolls affect each other?
Because they are not scrolling within themselves, but the entire body page is scrolling.
Remember the scroll position of the list:
Method:
Let each label content article list generate its own scrolling container, so that it will not affect each other
How to generate your own scrolling container for the article list:
set a fixed height, height: xxx; (if there is no effect, you can consider using the viewport unit vh, vw, they are not affected by the parent)
.article-list {
height: xxx ;
overflow-y:auto; //垂直溢出滚动
}
Add data using destructuring:
this.list = [...this.list, ...data.data.results]
Append new data to the end
Add height tips to label content
Set the height for partial content, which can be adapted to any device
height: calc(100vh - 274px); overflow-y: auto;
How are filters used globally and locally?
After configuring the global dayjs, you must export it if you want to use it globally
Pulling down to refresh the data will encounter blank space:
This is because the data is not enough, the data cannot support the height of the content
Solution: Need to fill the height of the content with the data
How to handle relative time
Day.js (opens new window) is a lightweight JavaScript library for handling time and date, and the API design of Moment.js (opens new window) remains exactly the same
- Install
npm i dayjs
- Create utils/dayjs.js
import Vue from 'vue' import dayjs from 'dayjs' // 加载中文语言包 import 'dayjs/locale/zh-cn' import relativeTime from 'dayjs/plugin/relativeTime' // 配置使用处理相对时间的插件 dayjs.extend(relativeTime) // 配置使用中文语言包 dayjs.locale('zh-cn') // 全局过滤器:处理相对时间 Vue.filter('relativeTime', value => { return dayjs().to(dayjs(value)) })
- Load initialization in main.js
import './utils/dayjs'
- use
<span>{ { article.pubdate | relativeTime }}</span>
expandHow to use locally in components
First of all, the configured dayjsexport by default:
export default dayjs
Then import it in the component:
// 组件内使用过滤时间的插件 import dayjs from '@/utils/dayjs'
Then define the function that handles relative time in methods:
methods: { relativeTime (value) { // value就是管道符前面的数据 return dayjs().to(dayjs(value)) //to为多少年前 } }
Finally use relative time functions where needed:
<span>{ { article.pubdate | relativeTime }}</span>
Computed property:
Computed properties will observe changes in internal dependent data, and if the dependent data changes, the calculated properties will be re-executed
Modify the data of the parent component with the sync modifier
Subassembly:
Modify the data of the parent component with the sync modifier
this.$emit('update:active', index)
parent component:
:actives.sync="active"
Note:
update
The attribute
this.$parent:
All data and methods of the parent component can be accessed in the current set
Expand knowledge points:
- .sync modifier: When the data is passed from parent to child, the child component can modify the data of the parent component. Parent
component: :property name.sync = "basic data type" Subcomponent: ①props: {property name} Receive ②Modify the corresponding data of the parent componentthis.$emit('update:属性名', 要修改的值)
(NoticeYou cannot use sync to operate complex data types, such as: arrays, objects)- this.$parent can access all the data of the parent component in the current component, including methods, and can implement the function of modifying the data of the parent component in the child component, and can also call the method of the parent component
- this.$children is an array, you can get all parent-child components of the current component
- this.$refs ① can take DOM elements ② can also take components
What optimization needs to be done for the search box?
- Anti-shake: continuous output event, only executed once (last time), core timer, each event triggers 1 to clear the previous timer
- Search history optimization: The searched content is saved to the local storage. Every time the user searches, the searched keyword is first checked from the local storage. If there is a keyword, it is directly accessed from the local storage. If not, a request is made to render the data.
The post and get request methods with parameters of axios are quite different.
The GET request with parameters isparams
The POST request with parameters isdata
PATCH toodata
PUT is alsodata
adaptation:
adaptive, responsive
Adaptive Technology:
1. Switch html font-size + rem through media query
Disadvantages: to write a lot of media queries, cumbersome
2. Mobile Taobao flexible.js + rem flexible.js monitors the screen size change through js (via the onresize event), **core algorithm: **html font-size=screen width/10
3. vw/vh adaptive screen width height viewport width/10 (viewport unit)
Use postcss-pxtorem (opens new window) to convert px to rem:will not convert inline styles
rem calculation principle: (element pixel)px / root font size=rem
rem adaptation principle (important)
Target:Realize the equal scaling effect of web page element sizes on devices with different widths
rem unit size
- Set different HTML tag font sizes according to viewport width
- Write the code, the size is rem unit
- Determine the font size of the HTML tag (basic root font size) of the device corresponding to the design draft
- Check the width of the design draft → determine the reference device width (viewport width) → determine the reference root font size (1/10 viewport width)
- Dimensions in rem units (N is rem)
- N * 37.5 = 68 → N = 68 / 37.5
- The size of rem unit = px unit value / base root font size
- The size of the rem unit = px unit value / base root font size (the result takes 3 decimal places)
(The design draft is 750px. Divide a line into 10 parts, and 1 part is 75. Generally speaking, the design draft of 750 should be divided by 2 to be 375 and then divided by 10. One part is 37.5)
Principle of Vue
1. Component basis => (MVVM model)
Traditional components, knowledge static rendering, update depends on manipulating DOM.
The core concept of Vue is the concept of data-driven, the so-called data-driven concept: when the data changes, the user interface will also change accordingly, and developers do not need to manually modify the dom.
advantage:
不需要在代码中去频繁的操作dom了,这样提高了开发的效率,同时也避免了在操作Dom的时候出现的错误。
The data drive of Vue.js is realized through the framework of MVVM. The MVVM framework mainly includes three parts: Model, View, ViewMode
Data Driven View - Vue MVVM
MVVM is the abbreviation of Model-View-ViewModel, which is to evolve the Controller in MVC into ViewModel. Model represents the data model, View represents the UI component,ViewModel is the bridge between the View and Model layers. Data will be bound to the ViewModel layer and automatically render the data to the page. When the view changes, the viewModel layer is notified to update the data.
2. Responsive principle of Vue
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 the dependencies of the current responsive object, each responsive object including sub-objects has a Dep instance (in which subs is an array of Watcher instances), when the data changes, each will be notified through dep.notify() watcher.
Watcher: Observer object, instance is divided into rendering watcher (render watcher), calculated attribute watcher (computed watcher), listener watcher (user watcher) three kinds of
relationship between Watcher and Dep,
dep is instantiated in watcher and sent to dep.subs Subscribers are added, and dep traverses dep.subs through notify to notify each watcher of updates.
When relying on collection (getter)
initState, when the computed attribute is initialized, the computed watcher is
triggered. When relying on collection initState, when the listener attribute is initialized,
the process of user watcher dependency collection render() is triggered, and when the render watcher dependency collection
re-render is triggered, When vm.render() is executed again, the subscription of watcher in all subs will be removed and reassigned.
The dispatch update (setter)
component modifies the response data, triggers the logic of the setter,
calls dep.notify()
to traverse all subs (Watcher instances), and calls the update method of each watcher.
principle:
当创建 Vue 实例时,vue 会遍历 data 选项的属性,利用 Object.defineProperty 为属性添加 getter 和 setter 对数据的读取进行劫持(getter 用来依赖收集,setter 用来派发更新),并且在内部追踪依赖,在属性被访问和修改时通知变化。
每个组件实例会有相应的 watcher 实例,会在组件渲染的过程中记录依赖的所有数据属性(进行依赖收集,还有 computed watcher,user watcher 实例),之后依赖项被改动时,setter 方法会通知依赖与此 data 的 watcher 实例重新计算(派发更新),从而使它关联的组件重新渲染。
Object.defineProperty implements responsiveness
Listener object, listener array
complex object, deep listener
const obj = {
};
const data = {
};
const name = 'zhangsan';
Object.defineProperty(data, 'name', {
get: function () {
console.log('get');
return name;
},
set: function (newVal) {
console.log('set');
obj.name = newVal;
}
})
console.log(data.name);
data.name = 'lisi';
console.log(obj.name);
Disadvantages of Object.defineProperty
In-depth monitoring needs to be recursive to the end, and the amount of calculation is large at one time.
It is impossible to monitor new attributes and delete attributes (use Vue.set Vue.delete)
and cannot natively monitor arrays, which requires special processing [Rewrite the method of the array, ['push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse'] These methods only change the array in a responsive manner, directly changing the index will not change in a responsive manner]
Summarize:
Vue双向数据绑定的原理:
vue.js 采用数据劫持结合发布-订阅模式,通过 Object.defineproperty 来劫持各个属性的 setter,getter,在数据变动时发布消息给订阅者,触发响应的监听回调。
The principle of Vue two-way data binding(important)
We all know that
Vue
it is a framework for two-way binding of data, and two-way binding consists of three important parts
- Data layer (Model): application data and business logic
- View layer (View): the display effect of the application, various UI components
- Business logic layer (ViewModel): the core of framework encapsulation, which is responsible for associating data with views
The above layered architecture solution can be called in a professional term: the
MVVM
core function of the control layer here is "two-way data binding". Naturally, we only need to understand what it is to learn more about the principle of data bindingUnderstanding ViewModels
Its main responsibilities are:
- Update view after data changes
- Update data after view changes
Of course, it also has two main parts
- Listener (Observer): monitor the properties of all data
- Parser (Compiler): scan and parse the instruction of each element node, replace the data according to the instruction template, and bind the corresponding update function
Vue implements two-way data binding by usingData hijacking and the publisher-subscriber pattern. Data hijacking is to use the ES5
Object.defineProperty(obj,key,val)
method to hijack the getter and setter of each attribute in the data option, and publish a message to the subscriber when the data changes, thereby triggering the corresponding callback to update the viewIn short, when creating a Vue instance, data hijacks the incoming data. At the same time, when the view is compiled, create a Watcher object for the place where the data in the data is used, and then add it to the publisher object in the getter of the data hijacking , when the hijacked data changes, it will notify all observers to operate the DOM to update through the publish-subscribe mode and callback function, thereby realizing the two-way binding of data.
/** * 对Object.defineProperty()进行封装 */ function defineReactive(obj, key, value) { //递归 - 对象的属性仍是对象 observe(value); //变化侦测 Object.defineProperty(obj, key, { get() { return value; }, set(newVal) { if (newVal !== value) { updateView(); value = newVal; observe(newVal) } } }) } /** * 对一个对象所有属性的变化侦测 */ function observe(target) { //非对象,直接返回 if (typeof target !== 'object') { return target; } //将每个属性转换为getter和setter形式 for (let key in target) { defineReactive(target, key, target[key]) } } //模拟更新视图的方法 function updateView() { console.log("更新视图"); }
Detect changes in object properties by calling observe directly
existing problems
- poor performance
- Added property on object cannot be detected
- Changing the length property of an array cannot be detected
When creating a Vue instance, Vue will traverse the properties of the data option, use Object.defineProperty to add getters and setters to the properties to hijack the reading of data (getters are used to collect dependencies, setters are used to dispatch updates), and track dependencies internally , notifies changes when properties are accessed and modified.
Each component instance will have a corresponding watcher instance, which will record all dependent data attributes during component rendering (dependency collection, as well as computed watcher, user watcher instance), and then when the dependency is changed, the setter method will notify The watcher instance that depends on this data is recalculated (dispatches updates), so that its associated components are re-rendered.
Record mouse scroll position
The first-level route jump will be destroyed and rebuilt. It is necessary to App.vue
package the cache component for the first-level route <keep-alive>
. Two hook functions will be triggered, namely activated
anddeactivated
Can be guarded by navigation within the componentbeforeRouteLeave
// 离开这个组件的路由导航守卫
beforeRouteLeave (to, from, next) {
// 跳走的时候获取组件的滚动位置
this.top = this.$refs.article[this.active].$el.scrollTop
next()
},
// 缓存组件激活触发的钩子函数
activated () {
if (this.$refs.article) {
this.$refs.article[this.active].$el.scrollTop = this.top
}
}
The browser's event loop (the execution mechanism of JS)
The event loop in the browser involves the concept of a task queue . After all asynchronous tasks are executed, the corresponding callback functions will be placed in the task queue , and queued for sequential processing . The task queue is divided into a macro task queue and a micro task queue , and only when the call stack of the main thread is cleared, the tasks in the task queue will be executed , which is the so-called JavaScript operating mechanism .
Browser macro tasks mainly include setTimeout() and setInterval() .
Browser microtasks mainly include Promise.then() , requestAnimationFrame(), process.nextTick .And microtasks have higher priority than macrotasks . When the main thread call stack is idle , it will detect whether there are tasks to be executed in the task queue . First, check whether there are tasks to be executed in the microtask queue. If so, execute the tasks in the microtask queue until the microtask queue is emptied. , and then start to execute the tasks in the macro task queue. After the macro task is cleared, it will then check whether there are tasks in the micro task queue, and so on and so forth to formevent loop。
The first event loop
- First judge whether JS is synchronous or asynchronous, synchronously enters the main thread, and asynchronously enters the event table (in the host environment)
- The asynchronous task registers the function in the event table, and when the trigger condition is met, it is pushed into the event queue (task queue)
- After the synchronous task enters the main thread, it will be executed until the main thread is idle, and then it will go to the event queue to check whether there is an executable asynchronous task, and if there is, it will be pushed into the main thread
The above three steps are executed in a loop, which is the event loop
The second type of event loop
setTimeout(function(){ console.log('A') }); new Promise(function(resolve){ console.log('B'); for(var i = 0; i < 10000; i++){ i == 99 && resolve(); } }).then(function(){ console.log('C') }); console.log('D');
The result of the above code execution is:B D C A
Analyze the reason why the execution sequence is like this?
This is because asynchronous tasks are divided into macro tasks and micro tasks
- macro-task (macro task): including the overall code script, setTimeout, setInterval
- micro-task (micro-task): Promise.then, process.nextTick
- According to this classification method: the execution mechanism of JS is:
- Execute a macro task, if a micro task is encountered during the process, put it in the [event queue] of the micro task
- After the current macro task is executed, it will check the [Event Queue] of the micro task, and execute all the micro tasks in it sequentially
Repeat the above 2 steps, combined with event loop(1) event loop(2), it is more accurateJS execution mechanismup.
The specific execution process is analyzed as follows:
首先执行script下的宏任务,遇到setTimeout,将其放到宏任务的【队列】里 遇到 new Promise直接执行,打印"B" 遇到then方法,是微任务,将其放到微任务的【队列里】 遇到同步任务console.log('D') 直接打印 "D" 本轮宏任务执行完毕,查看本轮的微任务,发现有一个then方法里的函数, 打印"C" 到此,本轮的event loop 全部完成。 下一轮的循环里,先执行一个宏任务,发现宏任务的【队列】里有一个 setTimeout里的函数,执行打印"A"
So the execution result is:B D C A
Consider a complex example:
console.log('1');
setTimeout(function() {
console.log('2');
process.nextTick(function() {
console.log('3');
})
new Promise(function(resolve) {
console.log('4');
resolve();
}).then(function() {
console.log('5')
})
})
//1 2 4 3 5
Implementation process:
1. Macro task synchronization code console.log('1')
2. setTimeout, add macro task Event Queue, no micro task is found, the first round of event loop is finished
3. The second round of event loop starts, the macro task is executed first, and the callback function of setTimeout is read from the macro task Event Queue
4. Synchronize code console.log('2'), find process.nextTick, add microtask Event Queue
5. New Promise, execute console.log('4') synchronously, find then, add microtask Event Queue
6. After the macro task is executed, the micro task is executed next, first execute process.nextTick, and then execute Promise.then
7. After the microtask is executed, the second round of event loop is completed, no macrotask is found, and the event loop ends
Summarize
The event loop executes the macrotask first, and the synchronous task is executed immediately, the asynchronous task is loaded into the corresponding Event Queue, and the microtask is also loaded into the corresponding Event Queue of the microtask. After all the synchronous microtasks are executed, if the microtask is found There are unfinished tasks in the Event Queue, and executing them first is considered to complete a round of event loop. Next, check whether there is asynchronous code in the queue of the macro task, and if so, execute the second round of the event loop, and so on.
SQL basic syntax
-- SELECT * FROM my_db_01.users; -- 1.查询整个表所有的数据 -- select * from users -- 2.查询具体的字段名字 -- select username,password from users -- 3.查询id是1的这个字段 查询的条件写在where后面 -- select * from users where id=1 -- 4.查询users表里username这个字段 模糊查询 Z%表示以z开头的 %Z写在后面后面表示以z结尾的 -- select * from users where username like 'Z%' -- 5.条件查询 -- select username,password from users where id>1 and status=0 -- 6.排序 desc(降序) asc(升序) -- select * from users order by id desc -- select * from users order by id asc -- 7.添加 -- insert into users(username,password,status) values('zl',111,1) -- 8.删除 -- delete from users where id=3 -- 9.修改(更新)update 表明 set 字段属性(多个字段用英文逗号隔开) where (修改的字段对应的id) 如果没有where 将修改整个表 -- update users set username='zs',password=555 where id=1 -- 10.函数count(*) -- select count(*) from users where status=0
What is the difference between watch, methods and computed?
From the mechanism of action:
- methods, watch and computed are all function-based, but each is different
- Both watch and computed are based on Vue's dependency tracking mechanismYes, when a certain data changes, all "related" data that depends on this data will "automatically" change, that is, automatically call related functions to realize the data change
- For methods: methods are used to define functions, which need to be called manually to be executed. Unlike watch and computed, which "automatically execute" pre-defined functions, compared to watch/computed, methods do not process data logic relationships, but only provide callable functions
In nature:
- The functions defined in methods still need to be called.
- Computed is a computed attribute , in fact, it is of the same type (used) as the data attribute in the data object.
- **watch: **similar to listening mechanism + event mechanism
The difference between watch and computed
- Functionally: computed is a computed attribute, watch is to monitor a value change, and then execute the corresponding callback.
- Whether to call the cache: the attributes on which the functions in computed depend have not changed, so when the current function is called, it will be read from the cache, and the watch will execute the callback every time the monitored value changes.
- Whether to call return: the function in computed must use return to return , the function in watch does not have to use return
- Scenarios that watch is good at handling: one data affects multiple data-------search box.
- Scenarios that computed is good at handling: one data is affected by multiple data – usage scenarios: when a value is affected by multiple attributes -------- shopping cart product settlement
**watch: ** attribute monitoring
- The function name in watch must be consistent with the attribute name in data, because watch depends on the attribute in data, when the attribute in data changes, the function in watch will be executed.
- The function in watch has two parameters, the former is newVal and the latter is oldVal.
- The functions in watch do not need to be called.
- watch will only monitor whether the value of the data changes, but not whether the address of the data changes. That is to say, if watch wants to monitor the changes of reference type data, it needs to perform in-depth monitoring. "obj.name"(){}------If obj has too many attributes, the efficiency of this method is very low, obj:{handler(newVal){},deep:true}------ Use the handler+deep method for in-depth monitoring.
- In special cases, the watch cannot monitor changes in the array. In special cases, when the data in the array is changed, the array has changed, but the view has not been updated. To change an array, you must use splice() or set. this . arr . splice ( 0 , 1 , 100 ) − − − − − Modify the data starting from item 0 in arr to 100, this . set. this.arr.splice(0,1,100)-----Modify the data starting from item 0 in arr to 100, this.set。this.arr.splice(0,1,100)−−−−−Modify the 1 data starting from item 0 in a r r to 1 0 0 , t h i s .set ( this.arr , 0,100)-----modify the value of item 0 in arr to 100.
- immediate: true Do a listener when the page is first loaded.
- One data affects multiple data - application scenarios: search box, form input, asynchronous update, animation
- If you are listening to complex data types, you need to enable deep monitoring
deep:true
computed: computed properties
- Cached calculations are performed according to dependencies and updated only when needed.
- A computed property can complete various complex logics and finally return a result; a computed property can depend on the data of multiple vue instances, as long as any one of the data changes, the computed property will be re-executed and the view will be updated. In addition to this, computed properties can depend on other computed properties and data from other instances
- One piece of data is affected by multiple pieces of data - the settlement of the shopping cart is affected by the quantity of the unit price and whether it is selected
The difference between HTTP and HTTPS (must)
Many people always think that http is https. In fact, there is a big difference between http and https. Let's take a look at the difference between https and http.
One: Let me talk about what is https and http
httpsIt is a secure version of http, also known as hypertext secure transmission, with an encrypted transmission protocol channel, and SSL provides a secure encryption basis, which is used for http transmission.
httpIt is an ordinary hypertext transfer protocol. On the Internet, all files must abide by this HTTP protocol, and its function is to realize the mutual request between the client and the server.
Two: Then what is the difference between https and httpthe difference
The difference between https and http:
**1. **The port of https is 443, while the port of http is 80, and the connection methods of the two are different. The connection of http is very simple and stateless; the HTTPS protocol is constructed by the SSL+HTTP protocol and can be encrypted Network protocols for transmission and identity authentication;
**2. **The HTTP protocol sends content in plain text, without any form of data encryption . For example: if a hacker intercepts the transmission message between the web browser and the website server, he can directly read the content in it. Therefore, the HTTP protocol is not suitable for transmitting some sensitive information, such as payment information such as bank card number and password. , in order to solve this defect of the HTTP protocol, HTTPS adds the SSL protocol on the basis of HTTP, and encrypts the communication between the browser and the server. The reason why the HTTPS protocol is secure is that the HTTPS protocol encrypts the transmitted data, and the encryption process is realized by asymmetric encryption.
**3. **HTTPS needs to go to CA to apply for a certificate, but http does not.
What is an SSL certificate? (expand)
Because the HTTP protocol sends content in clear text, it is very unsafe to use the HTTP protocol to transmit private information. In order to ensure that these private data can be encrypted and transmitted, Netscape designed the SSL protocol to encrypt the data transmitted by the HTTP protocol, so that HTTPS was born. where S stands for security. security
An SSL certificate is a type of digital certificate, similar to an electronic copy of our driver's license. Because it is configured on the server, it is also called an SSL server certificate.effectIt is used to protect network transactions, data transmission and login. So SSL has gradually become a specification (just like ECMAscript is the specification of js grammar)
The principle of nextTick
Since the Vue DOM update is performed asynchronously, that is, when the data is modified, the view will not be updated immediately, but will monitor the data change and cache it in the same event loop. After all the data changes in the same data loop are completed, they will be unified. The view updates. In order to ensure that the updated DOM is obtained,
Vue.nextTick()
the method .
There is a special API in vue, nextTick. According to the official documentation, it can execute a callback after the DOM is updated
Although the MVVM framework does not recommend accessing the DOM, sometimes there is such a need, especially when working with third-party plug-ins, DOM operations are unavoidable. And nextTick provides a bridge to ensure that we are operating the updated DOM.
Application scenario:
- The DOM operation performed in the created() hook function of the Vue life cycle must be placed in the callback function of Vue.nextTick()
- **Reason:** is that
created()
the DOM is not actually rendered when the hook function is executed.- When an operation to be performed after the data changes, and this operation needs to use the DOM structure that changes with the data change, this operation should be placed in the
Vue.nextTick()
callback function.
- Reason : Vue performs DOM updates asynchronously. As long as data changes are observed, Vue will open a queue and buffer all data changes that occur in the same event loop. If the same watcher is triggered multiple times, it will only be pushed into the queue once.
Summarize
The above is the implementation principle of vue's nextTick method, and the summary is:
- Vue uses asynchronous queues to control DOM updates and nextTick callbacks to be executed successively
- Due to its high priority feature, microtask can ensure that the microtasks in the queue are executed before an event loop
- Because of compatibility issues, Vue had to do a downgrade from microtask to macrotask
The principle of module drag and drop
The drag and drop function is mainly used to allow users to do some custom actions, such as drag sorting , drag and move pop-up boxes , etc., the effect is quite good. Let's talk about the principle of drag and drop:
1. Drag and drop process action
①Mouse down
②Mouse move
③Mouse releasehere toNotice: The movement event should be written inside the press event
2. Corresponding JS events in the drag and drop process
①When the mouse is pressed, the onmousedown event will be triggered
②Mouse movement will trigger the onmousemove event
③The onmouseup event will be triggered when the mouse is released
3. Explanation of the principle of realization
Drag and drop is actually achieved by obtaining the moving distance of the mouse, that is, calculating the difference between the coordinates (x, y) of the position before the movement and the coordinates (x, y) of the position during the movement.
When the mouse is pressed or the mouse is moved, the current mouse position can be obtained, that is, the position before the movement and the position during the movement.Another point is that the style of the dragged element must be set to an absolute or relative position to have an effect.
Summarize:
①Principle of dragging in the page: press and move the mouse, then release the mouse
②The trigger event is the mouse is pressed
mousedown
, the mouse is moved andmousemove
the mouse is releasedmouseup
③Drag and drop process: During the mouse movement process, the latest value is obtained and assigned to the left and top values of the modal box, so that the modal box can follow the mouse
④The coordinates of the mouse on the page minus the coordinates of the mouse in the box is the real position of the modal box.
⑤When the mouse is pressed, we need to get the coordinates of the mouse in the box.
⑥ When the mouse moves, let the coordinates of the modal box be set to: The coordinates of the mouse on the page minus the coordinates of the box. Note that the movement event is written in the press event .
⑦When the mouse is released, the dragging will stop, which means that the mouse movement event can be canceled
core code
// 鼠标按下获取鼠标在盒子内的坐标 obj.addEventListener('mousedown', function(e) { //获取鼠标在盒子中的坐标=鼠标在页面中的坐标减去盒子在页面中的坐标 var x = e.pageX - box.offsetLeft var y = e.pageY - box.offsetTop // 鼠标移动的时候,把鼠标在页面中的坐标,减去 鼠标在盒子内的坐标就是模态框的left和top值 // 在全局页面中拖拽时要用document,如果用了obj,事件会来不及触发,导致鼠标脱离 document.addEventListener('mousemove', move) function move(e) { box.style.left = e.pageX - x + 'px' box.style.top = e.pageY - y + 'px' } // 鼠标弹起,就让鼠标移动事件移除 document.addEventListener('mouseup', function() { document.removeEventListener('mousemove', move) })
memory leak
What is a memory leak
When the application no longer needs to occupy memory, for some reason, the memory is not reclaimed by the operating system or the available memory pool, which is called a memory leak
Which operations can cause memory leaks
1. Memory leaks caused by global variables
2. Memory leaks caused by closures
3. Forgotten timers or callbacks
4. When the dom is emptied or deleted, memory leaks caused by events not being cleared
5. Repeated rewriting of the same property will cause A large amount of memory is occupied (but the memory will be released after closing IE)6. If the first parameter of setTimeout uses a string instead of a function, it will cause a memory leak
Solutions to JS memory leaks
1. Pay attention to program logic and avoid "dead loop" and the like.
2. Reduce unnecessary global variables, or objects with a long life cycle, and timely garbage collect useless data.
3. Avoid creating too many objects Principle: no Things that have been lost must be returned in time
What exactly does the new operator do?
1. Create an empty object
2. this points to this new object
3. Execute the code in the constructor to add properties and methods to the new object
4. Return a new object: judge the return value, use the returned object, and create it if there is no an object
The difference between heap and stack
- Stack area (stack): automatically allocated and released by the compiler, storing function parameter values, local variable values, etc. its mode of operationSimilar to a stack in a data structure.
- Heap area (heap): generally allocated and released by the programmer. If the programmer does not release it, it may be recycled by the operating system at the end of the program.It is different from the heap in the data organization, the allocation method is similar to a linked list.
their difference
1 How to apply
- Stack: automatically allocated by the system . For example, when declaring a local variable int b of a function, the system automatically creates space for b in the stack.
- Heap: The programmer needs to apply for it by himself and specify the size. In C, use the malloc function; in C++, use the new operator.
2 System response after application
- Stack: As long as the remaining space of the stack is greater than the requested space , the system will provide memory for the program , otherwise an exception will be reported indicating stack overflow.
- Heap: The operating system has a linked list that records the memory address of the space . When the system receives an application from a program, it will traverse the linked list to find the first heap node whose space is larger than the requested space, and then delete the node from the linked list of free memory nodes. And allocate the space of this node to the program .
Summarize:
(1) heap is a heap, and stack is a stack;
(2) The stack space is automatically allocated/released by the operating system, and the space on the heap is manually allocated/released;
(3) The stack space is limited, and the heap is a large free memory area;
(4) The memory space allocated by the malloc function in C is on the heap, and the corresponding new operator in C++.When the program is compiled, memory allocation for variables and functions is performed on the stack, and parameters are passed on the stack when the function is called during memory operation.
堆和栈的概念存在于数据结构中和操作系统内存中。 在数据结构中,栈中数据的存取方式为先进后出。而堆是一个优先队列,是按优先级来进行排序的,优先级可以按照大小来规定。完全二叉树是堆的一种实现方式。 在操作系统中,内存被分为栈区和堆区。 栈区内存由编译器自动分配释放,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。 堆区内存一般由程序员分配释放,若程序员不释放,程序结束时可能由垃圾回收机制回收。 复制代码
How to upload files
Use the getData method to obtain cutting parameters based on server-side cutting
console.log(this.cropper.getData())
Pure client-side cropping uses getCroppedCanvas to get the cropped file object
First look at the interface document
看请求头: 如果接口要求 Content-Type 是 application/json 则传递普通 JavaScript 对象 axios会自动转为json对象 如果接口要求 Content-Type 是 multipart/form-data 则你必须传递 FormData 对象 const formData = new FormData() formData.append('photo', blob)
// 点击完成时间
onConfirm () {
// 基于服务端的裁切使用 getData 方法获取裁切参数
// console.log(this.cropper.getData())
// 纯客户端的裁切使用 getCroppedCanvas 获取裁切的文件对象
this.cropper.getCroppedCanvas().toBlob(async blob => {
// console.log(blob) // 裁剪后的结果信息
// 弹出loading页面
this.$toast.loading({
message: '保存中...',
forbidClick: true, // 禁止背景点击
duration: 0 // 持续展示
})
try {
// 1.创建formData对象
const obj = new FormData()
// 2.给对象obj添加key和value
obj.append('photo', blob)
// 3.发请求
const {
data } = await updateUserPhoto(obj)
// 4.更新父组件对象
this.$emit('update:photo', data.data.photo)
// 5.关闭弹层
this.$emit('update:close', false)
this.$toast.success('修改成功')
} catch (error) {
this.$toast.fail('修改失败')
}
})
}
What is BFC
The Block Formatting Context (BFC) is part of the visual CSS rendering of a web page, and is the area where the layout process for block-level boxes occurs, and where floating elements interact with other elements.
The following methods create a block formatting context:
- root element (
<html>
)- floating element (
float
value is notnone
)- Absolutely positioned elements (
position
values areabsolute
orfixed
)- inline-block element (
display
valueinline-block
)- table_cell (
display
valuetable-cell
, default for HTML table cells)- table_title (
display
valuetable-caption
, HTML table_title default)- Anonymous table cell element (
display
values aretable
,table-row
,table-row-group
,table-header-group
,table-footer-group
(default for HTML table, tr, tbody, thead, tfoot respectively) orinline-table
)overflow
A block element with a value othervisible
thanclip
display
flow-root
elements with valuecontain
an element with a value oflayout
, orcontent
paint
- flex elements (
display
values are direct children offlex
orinline-flex
elements), if they are neither flex , grid nor table containers themselves- Grid elements (
display
valuesgrid
areinline-grid
direct children of the or element), if they are neither flex , grid , nor table containers themselves- multi-column container (
column-count
orcolumn-width
(en-US) value not forauto
, includingcolumn-count
for1
)column-span
Elements with a valueall
of always create a new BFC, even if the element is not wrapped in a multi-column container ( spec change , Chrome bug )
Formatting context affects layout, usually, wewill create new BFCs for positioning and clearing floats, instead of changing the layout, because it will:
- contains inner float
- exclude external floats
- prevents margins from overlapping (the block's margin-top and margin-bottom are sometimes merged (collapsed) into a single margin whose size is the maximum value of the single margin (or if they are equal, only one of them), this behavior is called margin collapse . )
There are three situations in which margins overlap:
- The margins between two adjacent elements overlap unless the latter element is cleared with clear-fix .
- Without content to separate the parent and descendant elements, the outer boundaries of the parent block element and its descendant block elements will overlap, and the overlap will eventually overflow outside the parent block element.
- Empty block-level elements : Border collapse also occurs when the top border of a block element
margin-top
is glued directly to the bottom border of the element .margin-bottom
This happens when a block element has no border set at allborder
, paddingpadding
, heightheight
, minimum heightmin-height
, maximum heightmax-height
, when the content is set to inline or when clear-fix is added.==Note:== Elements with float floating and position=absolute absolute positioning will not produce margin overlapping behavior.
What are the ways of js lazy loading?
The loading, parsing, and execution of js will block the rendering process of the page, so we hope that the js script can be loaded as lazy as possible to improve the rendering speed of the page. A few ways I've learned are:
The first method is that we generally use theput the js script at the bottom of the document, to make the js script load and execute at the end as much as possible.
The second way is to add to the js scriptdefer attribute, this attribute will allow the script to be loaded and parsed synchronously, and then the script file will be executed after the document is parsed, so that the rendering of the page will not be blocked. Multiple scripts with the defer attribute set end up executing sequentially by specification , but this may not be the case in some browsers.
The third way is to add to the js scriptasync attribute, this attribute will make the script load asynchronously , and will not block the parsing process of the page, but execute the js script immediately after the script is loaded. At this time, if the document is not parsed, it will also be blocked. The execution order of scripts with multiple async attributes is unpredictable, and generally will not be executed sequentially in the order of the code .
The fourth way isCreate DOM tags dynamicallyIn this way, we can monitor the loading event of the document , and then dynamically create script tags to import js scripts when the document is loaded.
What is Ajax? How to create one?
My understanding of ajax is that it is a method of asynchronous communication, by directly initiating http communication from the js script to the server, and then updating the corresponding part of the webpage according to the data returned by the server without refreshing the entire page. There are several steps to create an ajax:
The first is to create an XMLHttpRequest object.
Then use the open method on this object to create an http request. The parameters required by the open method are the method of the request, the address of the request, whether it is asynchronous, and the user's authentication information . Before making a request, we can add some information and listener functions to this object. For example, we can add header information to the request through the setRequestHeader method. We can also add a status listener function to this object. An XMLHttpRequest object has a total of 5 states . When its state changes, the onreadystatechange event will be triggered. We can set the listener function to process the result of the successful request. When the readyState of the object changes to 4, it means that the data returned by the server has been received. At this time, we can judge the status of the request. If the status is 2xx or 304, it means the return is normal. At this time, we can update the page through the data in the response. When the object's properties and listener functions are set
Finally, we call the sent method to initiate a request to the server, and parameters can be passed in as the sent data body.
xhr.send(null);
let xhr = new XMLHttpRequest(); // 创建 Http 请求 xhr.open("GET", SERVER_URL, true); // 设置状态监听函数 xhr.onreadystatechange = function() { if (this.readyState !== 4) return; // 当请求成功时 if (this.status === 200) { handle(this.response); } else { console.error(this.statusText); } }; // 设置请求失败时的监听函数 xhr.onerror = function() { console.error(this.statusText); }; // 设置请求头信息 xhr.responseType = "json"; xhr.setRequestHeader("Accept", "application/json"); // 发送 Http 请求 xhr.send(null);
What is anti-shake and throttling?
introduce
In JavaScript, anti-shake and throttling are actually a very important concept. The main application scenarios are events that will be triggered frequently, such as monitoring scrolling and liking functions. It is impossible to send data to the background once you like it. At this time, anti-shake and throttling are required.
The core of anti-shake and throttling is the timer. We need to know a concept of the timer, which is to clear the timer after timing and before it is triggered. This timer method will not be triggered.
The function of the anti-shake function is to control the execution times of the function within a certain period of time. Anti-bounce means that the function will only be executed once (the last time) within N seconds, and if it is triggered again within N seconds, the delay time will be recalculated.
The role of the throttling function is to specify a unit time, and the function execution can only be triggered once at most within this unit time. If the function is triggered multiple times within this unit time, only one time will take effect.
In vue we can use lodash
one of _debounce
Note that the first parameter is the function, and the second parameter is the delay time
pre-parsing
1. Our js engine runs js in two steps: pre-parsing code execution
(1). The pre-parsing js engine will promote all
var
andfunction
to the front of the current scope (2). Code execution is executed from top to bottom in the order in which the code is written
2. Pre-parsing is divided into variable pre-parsing (variable promotion) and function pre-parsing (function promotion)
(1) Variable promotion is to promote all variable declarations to the front of the current scope without promoting assignment operations
(2) Function promotion is to promote all function declarations to the front of the current scope without calling the function
- Notice:
- Global variables cannot access local variables
- Adding the var keyword inside the function is local, and the formal parameters are also local (variable assignment without adding var inside is also a global variable)
- If there is no var keyword or no parameters are passed, a=1 is global
prototype chain
- As long as
__proto__
the prototype points to the prototype object, butObject.prototype.__proto__
it points to an empty (null) Each instance object has a __proto__ attribute, which points to the prototype object of the constructor. The prototype object of the constructor is also an object, and also has the __proto__ attribute, so that it is formed layer by layer.prototype chain。
Constructor instance and prototype object triangle
1. The prototype attribute of the constructor points to the prototype object of the constructor
2. The instance object is created by the constructor, and the __proto__ attribute of the instance object points to the prototype object of the constructor
3. The constructor attribute of the prototype object of the constructor points to Constructor, the constructor attribute of the prototype of the instance object also points to the constructor
Prototype Chain and Member Lookup Mechanism
__proto__
The significance of the object prototype is to provide a direction, or a route, for the object member search mechanism.Any object has a prototype object, that is, the prototype attribute. Any prototype object is also an object, and the object has the __proto__ attribute. In this way, looking up layer by layer, a chain is formed, which we call the prototype chain;
当访问一个对象的属性(包括方法)时,首先查找这个对象自身有没有该属性。 如果没有就查找它的原型(也就是 __proto__指向的 prototype 原型对象)。 如果还没有就查找原型对象的原型(Object的原型对象)。 依此类推一直找到 Object 为止(null)。 查找原则: 实例对象访问属性: 先去本身构造函数上去查找,如果本身没有要查找的属性或者方法,会自动去原型对象去查找 如果原型对象也没有,再去原型对象的原型对象去查找。 如果都没有返回undefined。 如果找到了停止查找 设置原则: 给实例对象设置一个属性,本质上是给实例添加属性,并不会修改原型的内容。