home page
Statistics
sponsor
Leaving a message.
about
more
Friendly chain
wallpaper
live broadcast
Search
one
Joe - a personal Typecho theme
32055 Reading
two
Joe open source directory program system
11825 Reading
three
Typecho custom background editor function
8237 Reading
four
Joe theme is automatically updated
7507 Reading
five
Joe Theme Custom Matching Color Tutorial
4409 Reading
web front end
CSS
React
Vue 2.0
Vue 3.0
JavaScript
TypeScript
Typecho
Applet
MacCMS
other
life
Sign in
Search
https://78.al
Accumulated writing
seventy-six
Articles
Accumulated receipt
3,721
Comments
home page
column
web front end
CSS
React
Vue 2.0
Vue 3.0
JavaScript
TypeScript
Typecho
Applet
MacCMS
other
life
page
Statistics
sponsor
Leaving a message.
about
Friendly chain
wallpaper
live broadcast
Search to
fourteen
Article and
Vue 2.0
Results for
2021-08-04
Difference between Vue 2 and Vue 3 in the custom component v-model
In the development of vue, a custom component is usually encapsulated, and the v-model bidirectional binding function is implemented. In Vue 2, the parent component<template>
<Child v-model="number"></Child>
</template>
<script>
export default {
data() {
return {
number: 0
}
},
components: {
Child: () => import("./Child.vue")
}
}
</script>subcomponents<template>
<button @click="handleClick">{{ value }}</button>
</template>
<script>
export default {
props: {
value: Number
},
methods: {
handleClick() {
//Realize v-model by sending an input event
this.$emit('input', this.value + 1)
}
}
}
</script>In vue 3, the parent component<template>
<Child v-model="number"></Child>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue';
export default defineComponent({
setup() {
const number = ref(0);
return {
number
};
},
});
</script>subcomponents<template>
<button @click="handleClick">{{ value }}</button>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
export default defineComponent({
props: {
//Replaced with modelValue
modelValue: Number
},
setup(props, { emit }) {
//Close pop-up layer
const handleClick = () => emit('update:modelValue',
props.modelValue + 1);
return { handleClick };
},
});
</script>
August 4, 2021
1177 Reading
14 Comments
20 likes
2021-07-28
Vue.set and this$
Set source code
Vue. set() and this$
In the Vue 2. X project development, sometimes it is necessary to modify the array or add an attribute to the object, but it is found that the page does not update synchronously.
For example: const vm=new Vue ({
data: {
arr: [1, 2],
obj: {
a: 3
}
}
});
vm.$data.arr[0] = 3; //
The page will not change
Vm. $data. obj. b=3;//The page will not change. In this case, Vue. set() or this$
set()。
The two are used in the same way, but one is mounted on Vue and the other on Vue.prototype.//Vue.set
import { set } from '../
observer/index'
Vue.set = set
// this.$
set
import { set } from '../
observer/index'
Vue.prototype. $set=se Use Vue.set or this$
Set to prevent the page from updating: const vm=new Vue ({
data: {
arr: [1, 2],
obj: {
a: 3
}
}
});
//Modify Array
Vue.set(vm.$
data.arr, 0, 3);
vm.$set(vm.$
data.arr, 0, 3);
//Object New Attribute
Vue.set(vm.$
data.obj, 'b', 3);
vm.$set(vm.$
Data. obj, 'b', 3); Source code of set function/
observer/indexfunction set (target: Array<any> | Object, key: any, val: any): any {
//IsUndef (target): used to determine whether the incoming target is undefined or null
//IsPrimitive (target): used to determine whether the incoming target is the original data type
//If it is null or undefined, an exception is thrown
if (process.env.
NODE_ENV !== 'production' &&(isUndef(target) || isPrimitive(target))) {
warn(`Cannot set reactive property on undefined, null, or primitive value: ${(target: any)}`)
}
//If an array is passed in and the key is a valid value of the array
if (Array.isArray(target) && isValidArrayIndex(key)) {
//Used to set the maximum length of an array
//Math.max (target. length, key): get the maximum value of the length and key of the array
target.length = Math.max(target.length, key)
//Directly call the split method on the array. Because the array method is mutated in Vue, the call will trigger dep.notify()
target.splice(key, 1, val)
return val
}
//The next step is to judge the object
//If the incoming key is in the original object, it indicates that it is already responsive. You can modify it directly
if (key in target && !
(key in Object.prototype)) {
target[key] = val
return val
}
//From here to the last code, the object is not on the original object, but is a new attribute value
const ob = (target: any).__
ob__
//If it is a Vue instance object or a root data object, a warning will be thrown
if (target._
isVue || (ob && ob.vmCount)) {
process.env.NODE_ENV !== 'production'
&&
warn(
'Avoid adding reactive properties to a Vue instance or its root $data ' +
'at runtime - declare it upfront in the data option.'
)
return val
}
//If there is no __ob__, it means that the current target is not responsive, then it is assigned directly
if (!
ob) {
target[key] = val
return val
}
//The rest is to add a new key attribute to the responsive object and notify the update
defineReactive(ob.value, key, val)
ob.dep.notify()
return val
}
July 28, 2021
628 Reading
2 Comments
11 likes
2021-07-06
Vue's method of secondary packaging components
Introduce that sometimes when we globally reference the UI framework (similar to ElementUI), we want to re encapsulate some simple components and ensure that the required props and events can be passed. In this case, we need to use two attributes on the vue instance: $attrs and $listeners.
Components of code secondary encapsulation<template>
<!--
V-bind="$attrs": the passed attribute values will be listed here, which can be seen as the {... props} expansion operator in act
V-on="$listeners": the @ event bound by the parent component will be passed here
-->
<el-input v-bind="$attrs" v-on="$listeners"></el-input>
</template>The parent component uses this component<template>
<HelloWorld placeholder="Please input content 111" @ input="handleInput"/>
</template>
<script>
export default {
methods: {
handleInput() {
console.log(1);
}
},
components: {
HelloWorld: () => import('@/components/HelloWorld.vue')
}
};
</script>
July 6, 2021
824 Reading
3 Comments
8 likes
2021-06-28
Performance optimization method of Vue bottom layer judgment tag
In vue, if normal html tags such as div and span are written, vue will parse them into traditional html tags, but when these tags are not written, vue will consider them as a component, such as<Custom></Custom>.
How to make such a judgment? First, make a judgment by yourself const tags='div, span, img, a '. split (",")
function checkTag(tag) {
return tags.some(item => item === tag)
}
console.log(checkTag('Custom')); //
false
console.log(checkTag('div')); //
true
console.log(checkTag('a')); //
True There are many implementation schemes here, such as for, some, forEach, etc., but they are all inseparable from the cycle. Consider such a problem, pass in a,
A is at the last position of the string, so it will cycle 4 times to determine whether it contains a. If there are too many tags on the page, there will even be tens of thousands of cycles to check how Vue implements this. The approximate source code is as follows const tags='div, span, img, a '
function makeMap(str) {
var map = Object.create(null);
var list = str.split(',');
for (var i = 0;
i < list.length; i++) {
map[list[i]] = true;
}
return function (val) {
return map[val];
}
}
const isHtmlTag = makeMap(tags)
isHtmlTag('div')
isHtmlTag('Custom')
IsHtmlTag ('a ') It can be seen here that a Curried function is implemented, and it is also a closure state.
At this point, the first call will loop once, and no matter what label is judged later, it will not loop again, because the first loop result uses the closure already in memory, which is the performance optimization that the closure can bring
June 28, 2021
622 Reading
4 Comments
10 likes
2021-06-28
Vue 2. X Extended Picture Preview Plug in
Preview.jsimport ToastComponent from './Toast.vue'
const Toast = {}
Toast.install = Vue => {
const ToastConstructor = Vue.extend(ToastComponent)
const instance = new ToastConstructor()
Vue.prototype.$Toast = function (options) {
if (!
options) {
Return console. error ('Please Pass In The Data/Please Pass In The Data ')
}
if (options.constructor !==
Object) {
Return console. error ('Please Pass In The Object Format/Please Pass In The Object Format ')
}
Options. msg=options. msg | |'Default message '
options.duration = options.duration || 3000
if (document.getElementsByClassName('toast').length === 0) {
instance.$mount(document.createElement('div'))
document.body.appendChild(instance.$
el)
instance.msg = options.msg
instance.visible = true
setTimeout(() => {
instance.visible = false
document.body.removeChild(instance.$
el)
}, options.duration)
}
}
}
export default ToastPreview.vue<template>
<transition name="bounce">
<div class="toast" v-show="visible">
<span>{{ msg }}</span>
</div>
</transition>
</template>
<script>
export default {
data() {
return {
msg: '',
visible: false
}
}
}
</script>
<style lang="css" scoped>
.bounce-enter-active {
animation: bounce-in 0.5s linear;
}
.bounce-leave-active {
animation: bounce-in 0.5s linear reverse;
}
@keyframes bounce-in {
0% {
transform: translate3d(-50%, 0, 0) scale(0);
}
25% {
transform: translate3d(-50%, 0, 0) scale(0.55);
}
50% {
transform: translate3d(-50%, 0, 0) scale(1);
}
75% {
transform: translate3d(-50%, 0, 0) scale(0.85);
}
100% {
transform: translate3d(-50%, 0, 0) scale(1);
}
}
.toast {
position: fixed;
z-index: 5201314;
top: 50%;
left: 50%;
transform: translate3d(-50%, 0, 0);
background: rgba(0, 0, 0, 0.75);
padding: 0 32px;
height: 50px;
line-height: 50px;
color: #fff;
user-select: none;
border-radius: 4px;
box-shadow: 0 1px 6px rgba(0, 0, 0, 0.2);
font-size: 14px;
letter-spacing: 1px;
}
</style>
June 28, 2021
920 Reading
2 Comments
16 likes
2021-06-15
Vue Interview Questions
Difference between MVC and MVVM {callout color="# 68bbdf"} The MVC controller control layer processes the data in the data layer model layer and displays it in the view layer of the view layer. Similarly, the view layer of the view layer can also receive instructions from the user through the control layer controller, which acts on the data layer modelMVVM hides the controller control layer and directly controls the view layer and the model data layer.
The interaction between the view layer and the data layer of MVC needs to belong to one-way link through the control layer controller.
MVVM hides the control layer controller, so that the view layer and data layer can directly interact. It belongs to the event binding principle of two-way connection {/call} Vue. {callout color="# 68bbdf"} Vue binds events to elements through v-on or its syntax sugar @ instruction, and provides event modifiers. The basic process is to compile templates to generate AST, generate render functions, and then execute them to obtain VNode,
When VNode generates a real DOM node or component, it uses the addEventListener method to bind events {/call} Why data is a function {callout color="# 68bbdf"} The data in the component is written as a function, and the data is defined in the form of function return value, so that every time the component is reused, a new data will be returned,
Similar to creating a private data space for each component instance, let each component instance maintain its own data, and prevent variable pollution {/queue} Communication between Vue components {callout color="# 68bbdf"} (1) props/$emitApplicable to parent-child component communication (2) $parent/$children Applicable to parent-child component communication (3) EventBus ($exit/$on) Applicable to parent-child, intergenerational
Brother component communication (4) $attrs/$listeners are applicable to generational component communication (5) provide/inject is applicable to generational component communication (6) Vuex is applicable to parent-child, generational, brother component communication (7) Get component instance {/call} through $refs How does the parent component listen to the life cycle of the child component {callout color="# 68bbdf"} (1)
Trigger the event of the parent component through $emit//Parent.vue
<Child @mounted="doSomething"/>
<script>
// Child.vue
mounted() {
this.$emit("mounted");
}
</script>(2) Listen through hook//Parent.vue
<Child @ hook: mounted="doSomething"></Child>{/call} vue router There are several {callout color="# 68bbdf"} hash modes that use URL hash values for routing.
History relies on HTML5 History APIabstract to support all JavaScript running environments. For example, if Node.js server finds that there is no browser API, the route will automatically force it into this mode {/call} Vue data bidirectional binding {callout color="# 68bbdf"} to implement a listener Observer: traverse data objects,
Including the properties of the sub property object. Use Object. defineProperty() to add setters and getters to the properties. If you assign a value to the object, the setter will be triggered. Then you can listen to data changes and implement a parser Compile: parse Vue template instructions, and replace variables in the template with data,
Then initialize the rendering page view and bind the node corresponding to each instruction to the update function. Subscribers who add listening data will be notified once the data changes,
Call the update function to update the data and realize a subscriber Watcher: the watcher subscriber is the communication bridge between the Observer and Compile. The main task is to subscribe to the message of property value change in the Observer. When receiving the message of property value change, trigger the corresponding update function in the parser Compile.
Implement a subscriber Dep: the subscriber adopts the publish subscribe design pattern to collect subscriber watchers for unified management of the listener Observer and subscriber watcher.
{/call} Why don't we recommend using {callout color="# 68bbdf"} v-for and v-if together? Do not use v-for and v-if in the same tag, because v-for is resolved first and then v-if is resolved.
If you need to use it at the same time, you can consider writing it as a calculation attribute {/call} props custom verification {callout color="# 68bbdf"} props:{
num: {
default: 1,
validator: function (value) {
//If the return value is true, the verification fails and an error is reported
return [1, 2, 3, 4, 5].indexOf(value) !== -
one
}
}
}{/call} The immediate attribute of the watch {callout color="# 68bbdf"} For example, if you want to request data once when you create it, and if the search value changes, you also need to request data, we will write created(){
this.getList()
},
watch: {
searchInputValue(){
this.getList()
}
}This can be written using immediate. When it is true, the watch:{
searchInputValue:{
handler: 'getList',
immediate: true
}
}{/call} computed Implement parameter transfer {callout color="# 68bbdf"} new Vue ({
el: "#app",
data() {
return {
params: {
Name: 'Du Heng',
age: 18
}
}
},
computed: {
total() {
//By returning a higher-order function
return (arg) => {
return arg * 10
}
}
}
}) {/call} The use of vue's hook {callout color="# 68bbdf"} Our common way of using timers export default{
data(){
timer:null
},
mounted(){
this.timer = setInterval(()=>{
console.log('1');
},1000);
}
beforeDestory(){
clearInterval(this.timer);
}
}The disadvantage of the above method is that you can define one more timer variable globally and use hook to do this: export default{
methods:{
fn(){
const timer = setInterval(()=>{
console.log('1');
},1000);
this.$once('hook:beforeDestroy',()=>{
clearInterval(timer);
})
}
}
}{/call} Vue's el attribute and $mount priority {callout color="# 68bbdf"} In the following cases, el's priority will be greater than $mountnew Vue ({
router,
store,
el: '#app',
render: h => h(App)
}).$
Mount ('# root') {/call} Dynamic instructions and parameters in Vue {callout color="# 68bbdf"}<template>
<aButton @[someEvent]="handleSomeEvent()" :[someProps]="1000" />...
</template>
<script>
...
data(){
return{
...
someEvent: someCondition ?
"click" : "dbclick",
someProps: someCondition ?
"num" : "price"
}
},
methods: {
handleSomeEvent(){
// handle some event
}
}
</script>{/call} How to re render the same route component {callout color="# 68bbdf"} Often, multiple routes resolve to the same Vue component.
The problem is that Vue will not re render the shared components by default for performance reasons. If you try to switch between routes using the same components, no change will occur const routes=[
{
path: "/a",
component: MyComponent
},
{
path: "/b",
component: MyComponent
},
];
If you want to re render, you need to use key<template>
<router-view :key="$route.path"></router-view>
</template>{/callout}
June 15, 2021
293 Reading
3 Comments
1 Like
2021-02-21
Simple function of simulating Vue replacement interpolation expression
<!
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div id="app">
{{ msg }}111{{ msg }}
<div>{{msg}}</div>
</div>
<script>
class Vue {
constructor(options) {
this.options = options
/*Initialize compiling dom*/
this.compile()
}
compile() {
let el = document.querySelector(this.options.el)
if (!
el) return console.warn('element not exist!')
let childNodes = el.childNodes
/*Recursive compilation node*/
childNodes.length && this.compileNodes(childNodes)
}
compileNodes(childNodes) {
/*Loop Node*/
childNodes.forEach(node => {
/*If it is a text node, replace the interpolation expression*/
if (node.nodeType === 3) {
let reg = /\{\{\s*([^\{\{\}\}\s]+)\s*\}\}/g
if (reg.test(node.textContent)) {
/*$1 is the attribute value in the interpolation expression*/
let $1 = RegExp.$1
node.textContent = node.textContent.replace(reg, this.options.data[$1])
}
} else {
/*If it is not a text node, it will be recursive and has child nodes*/
node.childNodes.length && this.compileNodes(node.childNodes)
}
})
}
}
new Vue({
el: '#app',
data: {
Msg: 'Test data'
}
})
</script>
</body>
</html>
February 21, 2021
256 Reading
0 Comments
3 likes
2021-02-20
Several solutions to solve the problem of object memory address consistency in Vue
In the development of vue projects, we often encounter the same problem of memory address, which leads to the modification here and the change of another place at the same time. Solution: 1. Use JSON methods (extremely recommended, which will lose attributes, such as functions and undefined) let obj={}
Let newObj=JSON.parse (JSON.stringify (obj)) 2. Deep copy 3. Use Object.assig method to export default{
data() {
return {
test: {}
}
},
methods: {
change(obj) {
this.test = Object.assign({}, obj)
}
}
}4. Use the object expansion operator let obj1={
a: 1,
b: 2
}
let obj2 = {...
obj1}
February 20, 2021
195 Reading
0 Comments
1 Like
2021-02-20
Vue this$
Options. data() Reset the data in data
<!
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
<button @click="btnClick">click</button>
<button @click="btnReset">reset</button>
<p><input type="text" v-model="message"></p>
<p>{{message}}</p>
</div>
<script src="./vue.js"></script>
<script>
let vm = new Vue({
el: "#app",
data() {
return {
message: ''
}
},
methods: {
btnClick() {
this.message = 'bbbbbbbbbb'
},
btnReset() {
Object.assign(this.$
data, this.$options.data.call(this))
}
},
})
</script>
</body>
</html>
February 20, 2021
291 Reading
0 Comments
3 likes
2021-02-20
Vue solves the problem of repeated route clicks reporting errors
Router.js file//Add this
const originalPush = Router.prototype.push;
Router.prototype.push = function push(location) {
return originalPush.call(this, location).catch(err => err)
}
February 20, 2021
250 Reading
0 Comments
2 likes
2021-02-20
Vue restricts the content of the input box to only enter the amount or number
<template>
<input @input="formatValue(value)" v-model="value">
</template>
<script>
export default = {
data(){
return {
value: ""
}
},
methods:{
//Only numbers are allowed to be entered, others are not allowed to be entered
formatValue(val){
this.value = this.value.replace(/[^\d]/g, "")
},
//Only the amount type can be entered, with a maximum of two decimal places (such as 3.88)
formatValue(val){
val = val.replace(/(^\s*)|(\s*$)/g, "");
if (!
val) return this.value = "";
val = val.replace(/[^\d.]/g, "");
val = val.replace(/^\./
g,
"");
val = val
.replace(".", "$#$")
.replace(/\./g, "")
.replace("$#$", ".");
val = val.replace(/^(\-)*(\d+)\.
(\d\d).*$/, "$1$2.$3");
this.value = val;
},
}
}
</script>
February 20, 2021
646 Reading
5 Comments
2 likes
2021-02-08
Vue breadcrumb navigation implementation scheme
For example, if you want to implement a breadcrumb such as home page/project list/my project 1, first write the name router.jsexport default corresponding to the above breadcrumb in the routing js file[
{
path: "/",
children: [
{
path: "/todoList",
component: TodoList,
name: "todoList"
meta: {
BreadName: "Item List"
}
},
{
path: "/todoList/mylist",
component: MyList,
name: "mylist"
meta: {
BreadName: "My Project"
}
},
]
}
]2. Write bread crumb components<template>
<a-breadcrumb class="breadcrumb">
<a-breadcrumb-item v-for="(breadcrumb, index) in breadcrumbList" :key="index">
{{breadcrumb.meta.breadName}}
</a-breadcrumb-item>
</a-breadcrumb>
</template>
<script>
export default {
computed: {
breadcrumbList () {
//First define a variable to store the calculated navigation array
let breadArr = []
//Get the route of the current page, intercept the first/of the route string, and form an array
let path = this.$route.path.substr(1).split("/") // >>> ["todoList", mylist]
//Get the routing addresses of all pages through this$
Router.options
const allRouter = this.$router.options.routes[0].children
//Then loop allRouter to find the two paths that match in it and save them
allRouter.forEach(_ => {
//Judge whether each item of path has an item in allRouter
if (path.some(_item => _item === _.name)) {
breadArr.push(_)
}
})
Console. log (breadArr)//Print it to see if the data is correct. If there are two items and each item contains meta content, it is correct
//Because there is no home page in this array, we can add one manually. At this time, use unshift
breadArr.unshift({
path: "/",
meta: {
BreadName: "Home Page"
}
})
//Finally, the computed data needs to be returned, and the return data needs to be returned to the array
return breadArr
}
}
}
</script>
February 8, 2021
525 Reading
0 Comments
7 likes
one
two