动力节点杜老师Vue笔记——2、Vue核心技术

动力节点杜老师Vue笔记——Vue程序初体验 我们可以先不去了解Vue框架的发展历史、Vue框架有什么特点、Vue是谁开发的,这些对我们编写Vue程序起不到太大的作用,更何况现在说了一些特点之后,我们也没有办法彻底理解它,因此我们可以先学会用,使用一段时间之后,我们再回头来熟悉一下Vue框架以及它的特点。只需要知道Vue是一个基于JavaScript(JS)实现的框架。要使用它就需要先拿到Vue的js文件。 阅读详情

动力节点Vue笔记第二章 Vue核心技术
20/100
发布文章
assdfgdfgjhtdo
未选择任何文件
new

2 Vue核心技术

2.1 事件处理

2.1.1 事件处理的核心语法

  1. 指令的语法格式:<标签 v-指令名:参数=”表达式”></标签>
  2. 事件绑定的语法格式:v-on:事件名。例如鼠标单击事件的绑定使用v-on:click。
  3. 绑定的回调函数需要在Vue实例中使用methods进行注册。methods可以配置多个回调函数,采用逗号隔开。
  4. 绑定回调函数时,如果回调函数没有参数,( )可以省略。
  5. 每一个回调函数都可以接收一个事件对象event。
  6. 如果回调函数有参数,并且还需要获取事件对象,可以使用$event进行占位。
  7. v-on:click可以简写为@click。简写的语法格式:@事件名
  8. 回调函数中的this是vm。如果回调函数是箭头函数的话,this是window对象,因为箭头函数没有自己的this,它的this是继承过来的,默认这个this是箭头函数所在的宿主对象。这个宿主对象其实就是它的父级作用域。而对象又不能构成单独的作用域,所以这个父级作用域是全局作用域,也就是window。
  9. 回调函数并没有在vm对象上,为什么通过vm可以直接调用函数呢?尝试手写Vue框架。
  10. 可以在函数中改变data中的数据,例如:this.counter++,这样会联动页面上产生动态效果。

2.1.2 事件修饰符

.stop - 调用 event.stopPropagation()。

*<div** @click="san"**>**  
3.     **<div** @click.stop="er"**>**  
4.         **<button** @click="yi"**>**{{name}}**</button>**  
5.     **</div>**  
6. **</div>**  

.prevent - 调用 event.preventDefault()。

 **<a** href="http://www.bjpowernode.com" @click.prevent="yi"**>**  
3. {{name}}  
4. **</a>** 

.capture - 添加事件侦听器时使用 capture 模式。

**<div** @click.capture="san"**>**  
3.     **<div** @click.capture="er"**>**  
4.         **<button** @click="yi"**>**{{name}}**</button>**  
5.     **</div>**  
6. **</div>**

注意:只有添加了capture修饰符的元素才会采用捕获模式。(或者说带有capture修饰符的优先触发)

.self - 只当事件是从侦听器绑定的元素本身触发时才触发回调。

 **<div** @click="san"**>**  
 1.     **<div** @click.self="er"**>**  
 2.         **<button** @click="yi"**>**{{name}}**</button>**  
 3.     **</div>**  
 4. **</div>**  

.once - 只触发一次回调。
5.

**<button** @click.once="yi"**>**  
 6.     {{name}}  
 7. **</button>** 

.passive - (2.3.0) 以 { passive: true } 模式添加侦听器
1.无需等待,直接继续(立即)执行事件默认行为。(对wheel事件有效果)
2. .passive 和 .prevent 修饰符不能共存。

2.1.3 按键修饰符

常用的按键修饰符包括:
.enter
.tab (只能配合keydown使用)
.delete (捕获“删除”和“退格”键)
.esc
.space
.up
.down
.left
.right

可以直接将 KeyboardEvent.key 暴露的任意有效按键名转换为 kebab-case 来作为修饰符。

<input type=”text” @keyup.page-down=”getInfo”>

可以通过全局 config.keyCodes 对象自定义按键修饰符别名

Vue.config.keyCodes.huiche = 13

2.1.4 系统修饰键

系统修饰键包括4个
.ctrl
.alt
.shift
.meta
系统修饰键在使用时应注意:

  1. 只有当系统修饰键和其他键组合使用,并且组合键释放时,才会触发keyup事件。

  2. 只要按下系统修饰键,就会触发keydown事件。

小技巧 <input type=”text” @keyup.ctrl.c=”getInfo”/>

2.2 计算属性

  1. 案例:用户输入信息,然后翻转用户输入的字符串。
  2. 插值语法可以实现,但是有三个问题
    1. 代码可读性差
    2. 代码不可复用
    3. 代码难以维护
  3. 可以使用methods方式实现,存在1个问题
    1. 效率低,即使数据没有发生变化,但每一次仍然会调用method。
  4. 使用计算属性可以解决以上问题。
  5. 什么是计算属性?

data中的是属性。用data的属性经过计算得出的全新的属性就是计算属性。

  1. 计算属性的使用
**<div** id="app"**>**  
3.     **<h1>**{{msg}}**</h1>**  
4.     输入的信息:**<input** type="text" v-model="info"**><br>**  
5.     反转的信息:{{reversedInfo}} **<br>**  
6.     反转的信息:{{reversedInfo}} **<br>**  
7.     反转的信息:{{reversedInfo}} **<br>**  
8.     反转的信息:{{reversedInfo}} **<br>**  
9. **</div>**  
10. **<script>**  
11.     const vm = new Vue({  
12.         el : '#app',  
13.         data : {  
14.             msg : '计算属性-反转字符串案例',  
15.             info : ''  
16.         },  
17.         computed : {  
18.             reversedInfo:{  
19.                 get(){  
20.                     console.log('getter被调用了');  
21.                     return this.info.split('').reverse().join('')  
22.                 },  
23.                 set(val){  
24.                     //this.reversedInfo = val // 不能这样做,这样会导致无限递归  
25.                     this.info = val.split('').reverse().join('')  
26.                 }  
27.             }  
28.         }  
29.     })  
30. **</script>**
  1. 计算属性需要使用:computed
  2. 计算属性通过vm. d a t a 是无法访问的。计算属性不能通过 v m . data 是无法访问的。计算属性不能通过vm. data是无法访问的。计算属性不能通过vm.data访问。
  3. 计算属性的getter/setter方法中的this是vm。
  4. 计算属性的getter方法的调用时机:
    1. 第一个时机:初次访问该属性。
    2. 第二个时机:计算属性所依赖的数据发生变化时。
  5. 计算属性的setter方法的调用时机:
    1. 当计算属性被修改时。(在setter方法中通常是修改属性,因为只有当属性值变化时,计算属性的值就会联动更新。注意:计算属性的值被修改并不会联动更新属性的值。)
  6. 计算属性没有真正的值,每一次都是依赖data属性计算出来的。
  7. 计算属性的getter和setter方法不能使用箭头函数,因为箭头函数的this不是vm。而是window。
  8. 计算属性的简写形式

只考虑读取,不考虑修改时,可以启用计算属性的简写形式。

computed : {  
2.     reversedInfo(){  
3.         console.log('getter被调用了');  
4.         **return** **this**.info.split('').reverse().join('')  
5.     }  
6. }  

2.3 侦听属性的变化

  1. 侦听属性的变化其实就是监视某个属性的变化。当被监视的属性一旦发生改变时,执行某段代码。
  2. 监视属性变化时需要使用watch配置项。

使用watch实现:比较数字大小的案例

**<div** id="app"**>**  
2.     **<h1>**{{msg}}**</h1>**  
3.     数值1:**<input** type="text" v-model="number1"**><br>**  
4.     数值2:**<input** type="text" v-model="number2"**><br>**  
5.     比较大小:{{compareResult}}  
6. **</div>**  
7. **<script>**  
8.     const vm = new Vue({  
9.         el : '#app',  
10.         data : {  
11.             msg : '侦听属性的变化',  
12.             number1 : 1,  
13.             number2 : 1,  
14.             compareResult : ''  
15.         },  
16.         watch : {  
17.             number1 : {  
18.                 immediate : true,  
19.                 handler(newVal, oldVal){  
20.                     let result = newVal - this.number2  
21.                     if(result **>** 0){  
22.                         this.compareResult = newVal + '**>**' + this.number2  
23.                     }else if(result **<** **0**){  
24.                         this.compareResult = newVal + '**<**' + this.number2  
25.                     }else{  
26.                         this.compareResult = newVal + '=' + this.number2  
27.                     }  
28.                 }  
29.             },  
30.             number2 : {  
31.                 immediate : true,  
32.                 handler(newVal, oldVal){  
33.                     let result = this.number1 - newVal  
34.                     if(result **>** 0){  
35.                         this.compareResult = this.number1 + '**>**' + newVal  
36.                     }else if(result **<** **0**){  
37.                         this.compareResult = this.number1 + '**<**' + newVal  
38.                     }else{  
39.                         this.compareResult = this.number1 + '=' + newVal  
40.                     }  
41.                 }  
42.             }  
43.         }  
44.     })  
45. **</script>** 

运行效果:


  1. 如何深度监视:
    1. 监视多级结构中某个属性的变化,写法是:’a.b.c’ : {}。注意单引号哦。
    2. 监视多级结构中所有属性的变化,可以通过添加深度监视来完成:deep : true
  2. 如何后期添加监视:
    1. 调用API:vm.$watch(‘number1’, {})
  3. watch的简写:
    1. 简写的前提:当不需要配置immediate和deep时,可以简写。
    2. 如何简写?
      1. watch:{ number1(newVal,oldVal){}, number2(newVal, oldVal){} }
    3. 后期添加的监视如何简写?
      1. vm.$watch(‘number1’, function(newVal, oldVal){})
  4. computed和watch如何选择?
    1. 以上比较大小的案例可以用computed完成,并且比watch还要简单。所以要遵守一个原则:computed和watch都能够完成的,优先选择computed。
    2. 如果要开启异步任务,只能选择watch。因为computed依靠return。watch不需要依赖return。
  5. 关于函数的写法,写普通函数还是箭头函数?
    1. 不管写普通函数还是箭头函数,目标是一致的,都是为了让this和vm相等。
    2. 所有Vue管理的函数,建议写成普通函数。
    3. 所有不属于Vue管理的函数,例如setTimeout的回调函数、Promise的回调函数、AJAX的回调函数,建议使用箭头函数。

2.4 class与style绑定

数据绑定的一个常见需求场景是操纵元素的 CSS class 列表和内联样式。因为 class 和 style 都是 attribute,我们可以和其他 attribute 一样使用 v-bind 将它们和动态的字符串绑定。但是,在处理比较复杂的绑定时,通过拼接生成字符串是麻烦且易出错的。因此,Vue 专门为 class 和 style 的 v-bind 用法提供了特殊的功能增强。除了字符串外,表达式的值也可以是对象或数组。

2.4.1 class绑定

2.4.1.1 绑定字符串

适用于样式的名字不确定,需要动态指定。

. <!DOCTYPE html**>**  
2. **<html** lang="en"**>**  
3. **<head>**  
4.     **<meta** charset="UTF-8"**>**  
5.     **<title>**class绑定字符串形式**</title>**  
6.     **<script** src="../js/vue.js"**></script>**  
7.     **<style>**  
8.         .static{  
9.             border: 1px solid black;  
10.             background-color: beige;  
11.         }  
12.         .big{  
13.             width: 200px;  
14.             height: 200px;  
15.         }  
16.         .small{  
17.             width: 100px;  
18.             height: 100px;  
19.         }  
20.     **</style>**  
21. **</head>**  
22. **<body>**  
23.     **<div** id="app"**>**  
24.         **<h1>**{{msg}}**</h1>**  
25.         **<div** class="static" :class="c1"**></div>**  
26.     **</div>**  
27.     **<script>**  
28.         const vm = new Vue({  
29.             el : '#app',  
30.             data : {  
31.                 msg : 'class绑定字符串形式',  
32.                 c1 : 'small'  
33.             }  
34.         })  
35.     **</script>**  
36. **</body>**  
37. **</html>** 

运行效果:

使用vue开发者工具修改c1的small为big:

通过测试可以看到样式完成了动态的切换。

2.4.1.2 绑定数组

适用于绑定的样式名字不确定,并且个数也不确定。

 <!DOCTYPE html**>**  
2. **<html** lang="en"**>**  
3. **<head>**  
4.     **<meta** charset="UTF-8"**>**  
5.     **<title>**class绑定数组形式**</title>**  
6.     **<script** src="../js/vue.js"**></script>**  
7.     **<style>**  
8.         .static{  
9.             border: 1px solid black;  
10.         }  
11.         .active{  
12.             background-color: green;  
13.         }  
14.         .text-danger{  
15.             color: red;  
16.         }  
17.     **</style>**  
18. **</head>**  
19. **<body>**  
20.     **<div** id="app"**>**  
21.         **<h1>**{{msg}}**</h1>**  
22.         **<div** class="static" :class="['active','text-danger']"**>**数组形式**</div>**  
23.         **<br><br>**  
24.         **<div** class="static" :class="[activeClass,errorClass]"**>**数组形式**</div>**  
25.         **<br><br>**  
26.         **<div** class="static" :class="classArray"**>**数组形式**</div>**  
27.     **</div>**  
28.     **<script>**  
29.         const vm = new Vue({  
30.             el : '#app',  
31.             data : {  
32.                 msg : 'class绑定数组形式',  
33.                 activeClass : 'active',  
34.                 errorClass : 'text-danger',  
35.                 classArray : ['active', 'text-danger']  
36.             }  
37.         })  
38.     **</script>**  
39. **</body>**  
40. **</html>**  

运行效果:

使用vue开发者工具删除数组中的一个样式:

2.4.1.3 绑定对象

适用于样式名字和个数都确定,但是要动态决定用或者不用。

. <!DOCTYPE html**>**  
2. **<html** lang="en"**>**  
3. **<head>**  
4.     **<meta** charset="UTF-8"**>**  
5.     **<title>**class绑定对象形式**</title>**  
6.     **<script** src="../js/vue.js"**></script>**  
7.     **<style>**  
8.         .static{  
9.             border: 1px solid black;  
10.         }  
11.         .active{  
12.             background-color: green;  
13.         }  
14.         .text-danger{  
15.             color: red;  
16.         }  
17.     **</style>**  
18. **</head>**  
19. **<body>**  
20.     **<div** id="app"**>**  
21.         **<h1>**{{msg}}**</h1>**  
22.         **<div** class="static" :class="{active : true, 'text-danger' : true}"**>**对象形式**</div>**  
23.         **<br><br>**  
24.         **<div** class="static" :class="classObject"**>**对象形式**</div>**  
25.     **</div>**  
26.     **<script>**  
27.         const vm = new Vue({  
28.             el : '#app',  
29.             data : {  
30.                 msg : 'class绑定对象形式',  
31.                 classObject : {  
32.                     active : true,  
33.                     'text-danger' : false  
34.                 }  
35.             }  
36.         })  
37.     **</script>**  
38. **</body>**  
39. **</html>**  

运行效果:

使用vue开发者工具修改text-danger为true:

2.4.2 style绑定

2.4.2.1 绑定对象
**<div** id="app"**>**  
2.     **<h1>**{{msg}}**</h1>**  
3.     <!-- 静态写法 -->  
4.     **<div** class="static" style="font-size: 20px;"**>**对象形式**</div><br><br>**  
5.     <!-- 动态写法1 -->  
6.     **<div** class="static" :style="{fontSize: 40 + 'px'}"**>**对象形式**</div><br><br>**  
7.     <!-- 动态写法2 -->  
8.     **<div** class="static" :style="styleObject"**>**对象形式**</div><br><br>**  
9. **</div>**  
10. **<script>**  
11.     const vm = new Vue({  
12.         el : '#app',  
13.         data : {  
14.             msg : 'style绑定对象形式',  
15.             styleObject : {  
16.                 fontSize : '40px'  
17.             }  
18.         }  
19.     })  
20. **</script>** 
2.4.2.2 绑定数组
**<div** id="app"**>**  
2.     **<h1>**{{msg}}**</h1>**  
3.     <!-- 静态写法 -->  
4.     **<div** class="static" style="font-size: 40px; color: red;"**>**数组形式**</div><br><br>**  
5.     <!-- 动态写法1 -->  
6.     **<div** class="static" :style="[{fontSize:'40px'},{color:'red'}]"**>**数组形式**</div><br><br>**  
7.     <!-- 动态写法2 -->  
8.     **<div** class="static" :style="styleArray"**>**对象形式**</div><br><br>**  
9. **</div>**  
10. **<script>**  
11.     const vm = new Vue({  
12.         el : '#app',  
13.         data : {  
14.             msg : 'style绑定对象形式',  
15.             styleArray : [  
16.                 {fontSize:'40px'},  
17.                 {color:'red'}  
18.             ]  
19.         }  
20.     })  
21. **</script>** 

2.5 条件渲染

2.5.1 v-if

指令用于条件性地渲染一块内容。这块内容只会在指令的表达式返回true时才被渲染

**<div** id="app"**>**  
2.     **<h1>**{{msg}}**</h1>**  
3.     温度:**<input** type="number" v-model="temprature"**><br>**  
4.     天气:  
5.     **<span** v-if="temprature <= 10"**>**寒冷**</span>**  
6.     **<span** v-if="temprature > 10 && temprature <= 25"**>**凉爽**</span>**  
7.     **<span** v-if="temprature > 25"**>**炎热**</span>**  
8. **</div>**  
9. **<script>**  
10.     const vm = new Vue({  
11.         el : '#app',  
12.         data : {  
13.             msg : '条件渲染',  
14.             temprature : 10  
15.         }  
16.     })  
17. **</script>** 

运行效果:

2.5.2 v-else-if、v-else

顾名思义,v-else-if 提供的是相应于 v-if 的“else if 区块”。它可以连续多次重复使用。
一个使用 v-else-if 的元素必须紧跟在一个 v-if 或一个 v-else-if元素后面。
你也可以使用 v-else 为 v-if 添加一个“else 区块”,当然,v-else元素也是必须紧跟在一个 v-if 或一个 v-else-if元素后面。

 **<div** id="app"**>**  
2.     **<h1>**{{msg}}**</h1>**  
3.     温度:**<input** type="number" v-model="temprature"**><br>**  
4.     天气:  
5.     **<span** v-if="temprature <= 10"**>**寒冷**</span>**  
6.     **<span** v-else-if="temprature <= 25"**>**凉爽**</span>**  
7.     **<span** v-else**>**炎热**</span>**  
8. **</div>**  
9. **<script>**  
10.     const vm = new Vue({  
11.         el : '#app',  
12.         data : {  
13.             msg : '条件渲染',  
14.             temprature : 10  
15.         }  
16.     })  
17. **</script>** 

2.5.3 与v-if

因为 v-if 是一个指令,他必须依附于某个元素。但如果我们想要切换不止一个元素呢?在这种情况下我们可以在一个 元素上使用 v-if,这只是一个不可见的包装器元素,最后渲染的结果并不会包含个 元素。v-else 和 v-else-if 也可以在 上使用。

 **<div** id="app"**>**  
2.     **<h1>**{{msg}}**</h1>**  
3.     温度:**<input** type="number" v-model="temprature"**><br>**  
4.     天气:  
5.     **<template** v-if="temprature <= 10"**>**  
6.         **<span>**寒冷**</span>**  
7.     **</template>**  
8.     **<template** v-else-if="temprature <= 25"**>**  
9.         **<span>**凉爽**</span>**  
10.     **</template>**  
11.     **<template** v-else**>**  
12.         **<span>**炎热**</span>**  
13.     **</template>**  
14. **</div>**  
15. **<script>**  
16.     const vm = new Vue({  
17.         el : '#app',  
18.         data : {  
19.             msg : '条件渲染',  
20.             temprature : 10  
21.         }  
22.     })  
23. **</script>** 

2.5.4 v-show

另一个可以用来按条件显示一个元素的指令是 v-show。其用法基本一样:

 **<div** id="app"**>**  
2.     **<h1>**{{msg}}**</h1>**  
3.     温度:**<input** type="number" v-model="temprature"**><br>**  
4.     天气:  
5.     **<span** v-show="temprature <= 10"**>**寒冷**</span>**  
6.     **<span** v-show="temprature > 10 && temprature <= 25"**>**凉爽**</span>**  
7.     **<span** v-show="temprature > 25"**>**炎热**</span>**  
8. **</div>**  
9. **<script>**  
10.     const vm = new Vue({  
11.         el : '#app',  
12.         data : {  
13.             msg : '条件渲染',  
14.             temprature : 10  
15.         }  
16.     })  
17. **</script>**  

不同之处在于 v-show 会在 DOM 渲染中保留该元素;v-show 仅切换了该元素上名为 display 的 CSS 属性。
v-show 不支持在 元素上使用,也不能和 v-else 搭配使用。

2.5.5 v-if VS v-show

v-if 是“真实的”按条件渲染,因为它确保了在切换时,条件区块内的事件监听器和子组件都会被销毁与重建
v-if 也是惰性的:如果在初次渲染时条件值为 false,则不会做任何事。条件区块只有当条件首次变为 true 时才被渲染。
相比之下,v-show 简单许多,元素无论初始条件如何,始终会被渲染,只有 CSS display属性会被切换。
总的来说,v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。因此,如果需要频繁切换,则使用 v-show 较好;如果在运行时绑定条件很少改变,则 v-if 会更合适。

2.6 列表渲染

语法格式:v-for指令。该指令用在被遍历的标签上。

  1. v-for="(element, index) in elements" :key="element.id"

或者

v-for="(element, index) of elements" :key="element.id"  

2.6.1 遍历数组、对象、字符串、指定次数

 **遍历数组**
2. **<div** id="app"**>**  
3.     **<h1>**{{msg}}**</h1>**  
4.     **<h2>**遍历数组**</h2>**  
5.     **<ul>**  
6.         **<li** v-for="(product, index) in products" :key="product.id"**>**  
7.             商品名称:{{product.name}},单价:{{product.price}}元/千克,下标:{{index}}  
8.         **</li>**  
9.     **</ul>**  
10. **</div>**  
11. **<script>**  
12.     const vm = new Vue({  
13.         el : '#app',  
14.         data : {  
15.             msg : '列表渲染',  
16.             products : [  
17.                 {id:'111',name:'西瓜',price:20},  
18.                 {id:'222',name:'苹果',price:10},  
19.                 {id:'333',name:'香蕉',price:30}  
20.             ]  
21.         }  
22.     })  
23. **</script>** 

运行效果:

  1. 遍历对象
*<div** id="app"**>**  
3.     **<h1>**{{msg}}**</h1>**  
4.     **<h2>**遍历对象**</h2>**  
5.     **<ul>**  
6.         **<li** v-for="(propertyValue, propertyName) of dog" :key="propertyName"**>**  
7.             {{propertyName}}:{{propertyValue}}  
8.         **</li>**  
9.     **</ul>**  
10. **</div>**  
11. **<script>**  
12.     const vm = new Vue({  
13.         el : '#app',  
14.         data : {  
15.             msg : '列表渲染',  
16.             dog : {  
17.                 name : '拉布拉多',  
18.                 age : 3,  
19.                 gender : '雄性'  
20.             }  
21.         }  
22.     })  
23. **</script>**

运行结果:

  1. 遍历字符串
**<div** id="app"**>**  
3.     **<h1>**{{msg}}**</h1>**  
4.     **<h2>**遍历字符串**</h2>**  
5.     **<ul>**  
6.         **<li** v-for="char,index of str" :key="index"**>**  
7.             {{index}}:{{char}}  
8.         **</li>**  
9.     **</ul>**  
10. **</div>**  
11. **<script>**  
12.     const vm = new Vue({  
13.         el : '#app',  
14.         data : {  
15.             msg : '列表渲染',  
16.             str : '动力节点'  
17.         }  
18.     })  
19. **</script>**  

运行结果:

  1. 遍历指定次数
**<div** id="app"**>**  
3.     **<h1>**{{msg}}**</h1>**  
4.     **<h2>**遍历指定次数**</h2>**  
5.     **<ul>**  
6.         **<li** v-for="number,index of 10" :key="index"**>**  
7.             下标:{{index}},数字:{{number}}  
8.         **</li>**  
9.     **</ul>**  
10. **</div>**  
11. **<script>**  
12.     const vm = new Vue({  
13.         el : '#app',  
14.         data : {  
15.             msg : '列表渲染'  
16.         }  
17.     })  
18. **</script>** 

运行结果:

2.6.2 虚拟dom和diff算法

所谓的虚拟dom就是内存当中的dom对象。vue为了提高渲染的效率,只有真正改变的dom元素才会重新渲染。

2.6.3 v-for的key的作用以及实现原理

  1. 用index作为key
<!DOCTYPE html**>**  
3. **<html** lang="en"**>**  
4. **<head>**  
5.     **<meta** charset="UTF-8"**>**  
6.     **<title>**key的原理**</title>**  
7.     **<script** src="../js/vue.js"**></script>**  
8. **</head>**  
9. **<body>**  
10.     **<div** id="app"**>**  
11.         **<h1>**{{msg}}**</h1>**  
12.         **<button** @click="addFirst"**>**在数组第一个位置添加tom**</button>**  
13.         **<button** @click="addLast"**>**在数组最后位置添加vue**</button>**  
14.         **<table>**  
15.             **<tr>**  
16.                 **<th>**序号**</th>**  
17.                 **<th>**姓名**</th>**  
18.                 **<th>**邮箱**</th>**  
19.                 **<th>**选择**</th>**  
20.             **</tr>**  
21.             **<tr** v-for="(vip,index) of vips" :key="index"**>**  
22.                 **<td>**{{index + 1}}**</td>**  
23.                 **<td>**{{vip.name}}**</td>**  
24.                 **<td>**{{vip.email}}**</td>**  
25.                 **<td><input** type="checkbox"**></td>**  
26.             **</tr>**  
27.         **</table>**  
28.     **</div>**  
29.     **<script>**  
30.         const vm = new Vue({  
31.             el : '#app',  
32.             data : {  
33.                 msg : 'key原理(虚拟dom与diff算法)',  
34.                 vips : [  
35.                     {id:'100',name:'jack',email:'jack@123.com'},  
36.                     {id:'200',name:'lucy',email:'lucy@123.com'},  
37.                     {id:'300',name:'james',email:'james@123.com'}  
38.                 ]  
39.             },  
40.             methods : {  
41.                 addFirst(){  
42.                     this.vips.unshift({id:'400',name:'tom',email:'tom@123.com'})  
43.                 },  
44.                 addLast(){  
45.                     this.vips.push({id:'500',name:'vue',email:'vue@123.com'})  
46.                 }  
47.             }  
48.         })  
49.     **</script>**  
50. **</body>**  
51. **</html>** 

运行效果:

全部选中:

添加tom:

可以看到错乱了。思考这是为什么?

  1. 用vip.id作为key

运行和测试结果正常,没有出现错乱。为什么?

  1. key的作用

key存在于虚拟dom元素中,代表该虚拟dom元素的唯一标识(身份证号)。

  1. diff算法是如何比较的?

新的虚拟dom和旧的虚拟dom比较时,先拿key进行比较:

  1. 如果key相同:则继续比较子元素:
    1. 子元素不同:直接将新的虚拟dom元素渲染到页面生成新的真实dom元素。
    2. 子元素相同:直接复用之前的真实dom。
  2. 如果key不同:直接将新的虚拟dom元素渲染到页面生成新的真实dom元素。
  3. index作为key存在两个问题
  4. 效率较低。
  5. 对数组的非末尾元素进行增删时,容易错乱。
  6. index作为key和vip.id作为key对比

当index作为key时:

当vip.id作为key时:

2.7 列表过滤

使用watch和computed分别进行实现:

 <!DOCTYPE html**>**  
2. **<html** lang="en"**>**  
3. **<head>**  
4.     **<meta** charset="UTF-8"**>**  
5.     **<title>**列表过滤**</title>**  
6.     **<script** src="../js/vue.js"**></script>**  
7.     **<style>**  
8.         table,tr,th,td{  
9.             border: 1px solid blue;  
10.         }  
11.     **</style>**  
12. **</head>**  
13. **<body>**  
14.     **<div** id="app"**>**  
15.         **<h1>**{{msg}}**</h1>**  
16.         **<input** type="text" placeholder="请输入搜索关键词" v-model="keyword"**>**  
17.         **<table>**  
18.             **<tr>**  
19.                 **<th>**序号**</th>**  
20.                 **<th>**姓名**</th>**  
21.                 **<th>**邮箱**</th>**  
22.             **</tr>**  
23.             **<tr** v-for="(vip,index) of filterVips" :key="vip.id"**>**  
24.                 **<td>**{{index+1}}**</td>**  
25.                 **<td>**{{vip.name}}**</td>**  
26.                 **<td>**{{vip.email}}**</td>**  
27.             **</tr>**  
28.         **</table>**  
29.     **</div>**  
30.     **<script>**  
31.         const vm = new Vue({  
32.             el : '#app',  
33.             data : {  
34.                 keyword : '',  
35.                 msg : '列表过滤',  
36.                 vips : [  
37.                     {id:'100',name:'jack',email:'jack@123.com'},  
38.                     {id:'200',name:'lucy',email:'lucy@123.com'},  
39.                     {id:'300',name:'james',email:'james@123.com'}  
40.                 ],  
41.                 //filterVips : []  
42.             },  
43.             /* watch : {  
44.                 keyword : {  
45.                     immediate : true,  
46.                     handler(newValue, oldValue){  
47.                         this.filterVips = this.vips.filter((v) =**>** {  
48.                             return v.name.indexOf(newValue) **>**= 0  
49.                         })  
50.                     }  
51.                 }  
52.             }, */  
53.             computed : {  
54.                 filterVips(){  
55.                     return this.vips.filter((v) =**>** {  
56.                         return v.name.indexOf(this.keyword) **>**= 0  
57.                     })  
58.                 }  
59.             }  
60.         })  
61.     **</script>**  
62. **</body>**  
63. **</html>**

2.8 列表排序

<!DOCTYPE html**>**  
2. **<html** lang="en"**>**  
3. **<head>**  
4.     **<meta** charset="UTF-8"**>**  
5.     **<meta** http-equiv="X-UA-Compatible" content="IE=edge"**>**  
6.     **<meta** name="viewport" content="width=device-width, initial-scale=1.0"**>**  
7.     **<title>**列表排序**</title>**  
8.     **<script** src="../js/vue.js"**></script>**  
9.     **<style>**  
10.         table,tr,td,th{  
11.             border:1px solid black;  
12.         }  
13.     **</style>**  
14. **</head>**  
15. **<body>**  
16.     **<div** id="app"**>**  
17.         **<h1>**{{msg}}**</h1>**  
18.         **<input** type="text" placeholder="输入关键字搜索" v-model="keyword"**><br>**  
19.         **<button** @click="type = 1"**>**按照名字升序**</button><br>**  
20.         **<button** @click="type = 2"**>**按照名字降序**</button><br>**  
21.         **<button** @click="type = 0"**>**按照名字原始顺序**</button><br>**  
22.         **<table>**  
23.             **<tr>**  
24.                 **<th>**序号**</th>**  
25.                 **<th>**姓名**</th>**  
26.                 **<th>**邮箱**</th>**  
27.                 **<th>**操作**</th>**  
28.             **</tr>**  
29.             **<tr** v-for="(vip, index) in filterVips" :key="vip.id"**>**  
30.                 **<td>**{{index+1}}**</td>**  
31.                 **<td>**{{vip.name}}**</td>**  
32.                 **<td>**{{vip.email}}**</td>**  
33.                 **<td><input** type="checkbox"**></td>**  
34.             **</tr>**  
35.         **</table>**  
36.     **</div>**  
37.     **<script>**  
38.         const vm = new Vue({  
39.             el : '#app',  
40.             data : {  
41.                 msg : '列表排序',  
42.                 vips : [  
43.                     {id:'100',name:'jack',email:'jack@123.com'},  
44.                     {id:'200',name:'lucy',email:'lucy@123.com'},  
45.                     {id:'300',name:'james',email:'james@123.com'},  
46.                     {id:'400',name:'lilei',email:'lilei@123.com'},  
47.                 ],  
48.                 keyword : '',  
49.                 type : 0  
50.             },  
51.             computed : {  
52.                 filterVips(){  
53.                     // 筛选  
54.                     let arr = this.vips.filter((vip) =**>** {  
55.                         return vip.name.indexOf(this.keyword) **>**= 0  
56.                     })   
57.                     // 根据排序类型进行排序  
58.                     if(this.type){  
59.                         arr.sort((v1, v2) =**>** {  
60.                             console.log('@')  
61.                             return this.type == 1 ? v1.name.localeCompare(v2.name) : v2.name.localeCompare(v1.name)  
62.                         })  
63.                     }  
64.                     // 返回  
65.                     return arr  
66.                 }  
67.             }  
68.         })  
69.     **</script>**  
70. **</body>**  
71. </html>

2.9 收集表单数据

 <!DOCTYPE html**>**  
2. **<html** lang="en"**>**  
3. **<head>**  
4.     **<meta** charset="UTF-8"**>**  
5.     **<title>**收集表单数据**</title>**  
6.     **<script** src="../js/vue.js"**></script>**  
7. **</head>**  
8. **<body>**  
9.     **<div** id="app"**>**  
10.         **<h1>**{{msg}}**</h1>**  
11.         **<form** @submit.prevent="send"**>**  
12.             **<label** for="username"**>**用户名:**</label>**  
13.             **<input** id="username" type="text" v-model.trim="user.username"**><br><br>**  
14.             密码:**<input** type="password" v-model="user.password"**><br><br>**  
15.             年龄:**<input** type="number" v-model.number="user.age"**><br><br>**  
16.             性别:  
17.                 男**<input** type="radio" name="gender" v-model="user.gender" value="1"**>**  
18.                 女**<input** type="radio" name="gender" v-model="user.gender" value="0"**><br><br>**  
19.             爱好:  
20.                 运动**<input** type="checkbox" name="interest" value="sport" v-model="user.interest"**>**  
21.                 旅游**<input** type="checkbox" name="interest" value="travel" v-model="user.interest"**>**  
22.                 唱歌**<input** type="checkbox" name="interest" value="sing" v-model="user.interest"**><br><br>**  
23.             学历:  
24.                 **<select** v-model="user.grade"**>**  
25.                     **<option** value=""**>**请选择学历**</option>**  
26.                     **<option** value="zk"**>**专科**</option>**  
27.                     **<option** value="bk"**>**本科**</option>**  
28.                     **<option** value="ss"**>**硕士**</option>**  
29.                 **</select><br><br>**  
30.             简介:**<textarea** cols="30" rows="10" v-model.lazy="user.introduce"**></textarea><br><br>**  
31.             **<input** type="checkbox" v-model="user.isAgree"**>**阅读并接受协议**<br><br>**  
32.             **<button>**注册**</button>**  
33.         **</form>**  
34.     **</div>**  
35.     **<script>**  
36.         const vm = new Vue({  
37.             el : '#app',  
38.             data : {  
39.                 msg : '收集表单数据',  
40.                 user : {  
41.                     username : '',  
42.                     password : '',  
43.                     age : '',  
44.                     gender : '0',  
45.                     interest : ['sport'],  
46.                     grade : 'ss',  
47.                     introduce : '',  
48.                     isAgree : ''  
49.                 }  
50.             },  
51.             methods : {  
52.                 send(){  
53.                     console.log(JSON.stringify(this.user))  
54.                 }  
55.             }  
56.         })  
57.     **</script>**  
58. **</body>**  
59. **</html>** 

页面展示效果:

运行结果:

2.10 过滤器

过滤器filters适用于简单的逻辑处理,例如:对一些数据进行格式化显示。他的功能完全可以使用methods,computed来实现。过滤器可以进行全局配置,也可以进行局部配置:

  1. 全局配置:在构建任何Vue实例之前使用Vue.filter(‘过滤器名称’, callback)进行配置。
  2. 局部配置:在构建Vue实例的配置项中使用filters进行局部配置。

过滤器可以用在两个地方:插值语法和v-bind指令中。
多个过滤器可以串联:{{msg | filterA | filterB | filterC}}
过滤器也可以接收额外的参数,但过滤器的第一个参数永远接收的都是前一个过滤器的返回值。

2.11 Vue的其它指令

2.11.1 v-text

将内容填充到标签体当中,并且是以覆盖的形式填充,而且填充的内容中即使存在HTML标签也只是会当做一个普通的字符串处理,不会解析。功能等同于原生JS中的innerText。

2.11.2 v-html

将内容填充到标签体当中,并且是以覆盖的形式填充,而且将填充的内容当做HTML代码解析。功能等同于原生JS中的innerHTML。
v-html不要用到用户提交的内容上。可能会导致XSS攻击。XSS攻击通常指的是通过利用网页开发时留下的漏洞,通过巧妙的方法注入恶意指令代码到网页,使用户加载并执行攻击者恶意制造的网页程序。这些恶意网页程序通常是JavaScript。
例如:用户在留言中恶意植入以下信息:

其他用户上当了:如果点击了以上的留言,就会将cookie发送给恶意的服务器。

2.11.3 v-cloak

v-cloak配置css样式来解决胡子的闪现问题。
v-cloak指令使用在标签当中,当Vue实例接管之后会删除这个指令。
这是一段CSS样式:当前页面中所有带有v-cloak属性的标签都隐藏起来。
[v-cloak] {
display : none;
}

2.11.4 v-once

初次接触指令的时候已经学过了。只渲染一次。之后将被视为静态内容。

2.11.5 v-pre

使用该指令可以提高编译速度。带有该指令的标签将不会被编译。可以在没有Vue语法规则的标签中使用可以提高效率。不要将它用在带有指令语法以及插值语法的标签中。

2.12 vue的自定义指令

函数式:
directives : {
‘text-reverse’ : function(element, binding){
// element 是真实dom对象(可以通过 element instanceof HTMLElement 判断)
// binding 是绑定的对象
element.innerText = binding.value.split(‘’).reverse().join(‘’)
}
}

函数调用时机:
第一时机:模板初次解析时(元素与指令初次绑定)。
第二时机:模板重新解析时。
对象式:可以使用对象式完成更加细致的功能。
directives : {
‘bind-parent’ : {
// 元素与指令初次绑定时自动调用。
bind(element, binding){},
// 元素已经被插入页面后自动调用。
inserted(element, binding){},
// 模板重新解析时被自动调用。
update(element, binding){}
}
}
自定义指令的函数中的this是window。
以上是局部指令,全局指令怎么定义:
对象式:
Vue.directive(‘bind-parent’, {
bind(element, binding){},
inserted(element, binding){},
update(element, binding){}
})
函数式:
Vue.directive(‘text-reverse’, function(element, binding){})

2.13 响应式与数据劫持

  1. 什么是响应式?

修改data后,页面自动改变/刷新。这就是响应式。就像我们在使用excel的时候,修改一个单元格中的数据,其它单元格的数据会联动更新,这也是响应式。

  1. Vue的响应式是如何实现的?

数据劫持:Vue底层使用了Object.defineProperty,配置了setter方法,当去修改属性值时setter方法则被自动调用,setter方法中不仅修改了属性值,而且还做了其他的事情,例如:重新渲染页面。setter方法就像半路劫持一样,所以称为数据劫持。

  1. Vue会给data中所有的属性,以及属性中的属性,都会添加响应式。
  2. 后期添加的属性,不会有响应式,怎么处理?
  3. Vue.set(目标对象, ‘属性名’, 值)
  4. vm.$set(目标对象, ‘属性名’, 值)
  5. Vue没有给数组下标0,1,2,3…添加响应式,怎么处理?
  6. 调用Vue提供的7个API:

push()
pop()
reverse()
splice()
shift()
unshift()
sort()
或者使用:
Vue.set(数组对象, ‘index’, 值)
vm.$set(数组对象, ‘index’, 值)

2.14 Vue的生命周期

2.14.1 什么是生命周期

所谓的生命周期是指:一个事物从出生到最终的死亡,整个经历的过程叫做生命周期。
例如人的生命周期:

  1. 出生:打疫苗
  2. 3岁了:上幼儿园
  3. 6岁了:上小学
  4. 12岁了:上初中
  5. …
  6. 55岁了:退休
  7. …
  8. 临终:遗嘱
  9. 死亡:火化

可以看到,在这个生命线上有很多不同的时间节点,在不同的时间节点上去做不同的事儿。

Vue的生命周期指的是:vm对象从创建到最终销毁的整个过程。

  1. 虚拟DOM在内存中就绪时:去调用一个a函数
  2. 虚拟DOM转换成真实DOM渲染到页面时:去调用一个b函数
  3. Vue的data发生改变时:去调用一个c函数
  4. …
  5. Vue实例被销毁时:去调用一个x函数

在生命线上的函数叫做钩子函数,这些函数是不需要程序员手动调用的,由Vue自动调用,程序员只需要按照自己的需求写上,到了那个时间点自动就会执行。

2.14.2 掌握Vue的生命周期有什么用

研究Vue的生命周期主要是研究:在不同的时刻Vue做了哪些不同的事儿。
例如:在vm被销毁之前,我需要将绑定到元素上的自定义事件全部解绑,那么这个解绑的代码就需要找一个地方写一下,写到哪里呢?你可以写到beforeDestroy()这个函数中,这个函数会被Vue自动调用,而且是在vm对象销毁前被自动调用。像这种在不同时刻被自动调用的函数称为钩子函数。每一个钩子函数都有对应的调用时间节点。
换句话说,研究Vue的生命周期主要研究的核心是:在哪个时刻调用了哪个钩子函数。

2.14.3 Vue生命周期的4个阶段8个钩子

Vue的生命周期可以被划分为4个阶段:初始阶段、挂载阶段、更新阶段、销毁阶段。
每个阶段会调用两个钩子函数。两个钩子函数名的特点:beforeXxx()、xxxed()。
8个生命周期钩子函数分别是:

  1. 初始阶段
    1. beforeCreate() 创建前
    2. created() 创建后
  2. 挂载阶段
    1. beforeMount() 挂载前
    2. mounted() 挂载后
  3. 更新阶段
    1. beforeUpdate() 更新前
    2. updated() 更新后
  4. 销毁阶段
    1. beforeDestroy() 销毁前
    2. destroyed() 销毁后

8个钩子函数写在哪里?直接写在Vue构造函数的options对象当中。
Vue官方的生命周期图:

翻译后的生命周期图:

2.14.4 初始阶段做了什么事儿

做了这么几件事:

  1. 创建Vue实例vm(此时Vue实例已经完成了创建,这是生命的起点)
  2. 初始化事件对象和生命周期(接产大夫正在给他洗澡)
  3. 调用beforeCreate()钩子函数(此时还无法通过vm去访问data对象的属性)
  4. 初始化数据代理和数据监测
  5. 调用created()钩子函数(此时数据代理和数据监测创建完毕,已经可以通过vm访问data对象的属性)
  6. 编译模板语句生成虚拟DOM(此时虚拟DOM已经生成,但页面上还没有渲染)

该阶段适合做什么?
beforeCreate:可以在此时加一些loading效果。
created:结束loading效果。也可以在此时发送一些网络请求,获取数据。也可以在这里添加定时器。

2.14.5 挂载阶段做了什么事儿

做了这么几件事:

  1. 调用beforeMount()钩子函数(此时页面还未渲染,真实DOM还未生成)
  2. 给vm追加 e l 属性,用它来代替” e l ”, el属性,用它来代替”el”, el属性,用它来代替”el”,el代表了真实的DOM元素(此时真实DOM生成,页面渲染完成)
  3. 调用mounted()钩子函数

该阶段适合做什么?
mounted:可以操作页面的DOM元素了。

2.14.6 更新阶段做了什么事儿

做了这么几件事:

  1. data发生变化(这是该阶段开始的标志)
  2. 调用beforeUpdate()钩子函数(此时只是内存中的数据发生变化,页面还未更新)
  3. 虚拟DOM重新渲染和修补
  4. 调用updated()钩子函数(此时页面已更新)

该阶段适合做什么?
beforeUpdate:适合在更新之前访问现有的 DOM,比如手动移除已添加的事件监听器。
updated:页面更新后,如果想对数据做统一处理,可以在这里完成。

2.14.7 销毁阶段做了什么事儿

做了这么几件事:

  1. vm.$destroy()方法被调用(这是该阶段开始的标志)
  2. 调用beforeDestroy()钩子函数(此时Vue实例还在。虽然vm上的监视器、vm上的子组件、vm上的自定义事件监听器还在,但是它们都已经不能用了。此时修改data也不会重新渲染页面了)
  3. 卸载子组件和监视器、解绑自定义事件监听器
  4. 调用destroyed()钩子函数(虽然destroyed翻译为已销毁,但此时Vue实例还在,空间并没有释放,只不过马上要释放了,这里的已销毁指的是vm对象上所有的东西都已经解绑完成了)

该阶段适合做什么?
beforeDestroy:适合做销毁前的准备工作,和人临终前写遗嘱类似。例如:可以在这里清除定时器。

【动力节点】杜老师Vue笔记——Vue程序初体验 我们可以先不去了解Vue框架的发展历史、Vue框架有什么特点、Vue是谁开发的,这些对我们编写Vue程序起不到太大的作用,更何况现在说了一些特点之后,我们也没有办法彻底理解它,因此我们可以先学会用,使用一段时间之后,我们再回头来熟悉一下Vue框架以及它的特点。以上程序执行原理:Vue编译器对template进行编译,遇到胡子{{}}时从data中取数据,然后将取到的数据插到对应的位置。第二:虽然是直接写到HTML代码当中的,但以上程序中第3~6行已经不是HTML代码了,它是具有Vue语法特色的模板语句。 阅读详情

相关推荐

动力节点杜老师Vue课程笔记第三章Vue组件化

click、keydown、keyup,这些事件都是内置事件。Vue也支持给组件添加自定义事件。包括两种方式:第一种方式:直接在组件标签上绑定事件第二种方式:通过代码来给组件绑定事件所有从父向子传递函数的位置,都可以修改为自定义事件方式。主要改造子向父传数据的功能。

A_coding的博客 413

动力节点老杜Vue笔记第三章 Vue组件化

click、keydown、keyup,这些事件都是内置事件。Vue也支持给组件添加自定义事件。包括两种方式:第一种方式:直接在组件标签上绑定事件第二种方式:通过代码来给组件绑定事件所有从父向子传递函数的位置,都可以修改为自定义事件方式。主要改造子向父传数据的功能。

assdfgdfgjhtdo的博客 395

动力节点B站的Java视频路线资源,非常全面

作为动力节点的铁杆粉丝,从刚开始接触Java就跟着动力节点的路线去学,一直到去年找到了还不错的工作,我今天整理了他们的学习资源,java学习路线和相关的学习视频,如果是零基础入门java的小伙伴,跟着这个路线可以节省很多时间。 这里有所有前沿技术,从基础到项目实战,而且是最新的教程,按照这个顺序学就完了! 一、Java基础阶段 【B站排名第一的】Java零基础视频844集(适合Java 0基础,Java初学入门) https://www.bilibili.com/video/BV1Rx411.

Java_Coding1的博客 1086

【动力节点】杜老师Vue笔记第七章vue3

绑定事件触发事件将组合式API拿出来,封装成一个函数,在需要复用的位置,使用这个hook函数。一般创建一个hooks目录,在hooks目录当中放hook函数。代码复用。

weixin_54585403的博客 1631

动力节点老杜Vue框架教程【五】Vuex

vuex是实现数据集中式状态管理的插件。数据由vuex统一管理。其它组件都去使用vuex中的数据。只要有其中一个组件去修改了这个共享的数据,其它组件会同步更新。一定要注意:全局事件总线和vuex插件的区别:全局事件总线关注点:组件和组件之间数据如何传递,一个绑定on,一个触发on,一个触发on,一个触发emit。数据实际上还是在局部的组件当中,并没有真正的让数据共享。只是数据传来传去。vuex插件的关注点:共享数据本身就在vuex上。其中任何一个组件去操作这个数据,其它组件都会同步更新。

2301_76637473的博客 240

2023年Java学习路线【超详细超实用】

Java学习路线速看版:JavaSE--> MySQL--> JavaSE项目【图书管理系统】-->JDBC -->前端必修课-->Vue--> JavaWeb -->Ajax -->Linux-->Maven--> MyBatis--> Spring-> SpringMVC- > Git-->CRM项目--> Redis7 --> Maven进阶--> SpringBoot3 --> MyBatis Plus --> Dubbo -->盈利宝项目--> 动力恒合仓储项目 --> SpringC

m0_47946173的博客 1155

动力节点杜老师Vue视频笔记第三章Vue组件化

click、keydown、keyup,这些事件都是内置事件。Vue也支持给组件添加自定义事件。包括两种方式:第一种方式:直接在组件标签上绑定事件第二种方式:通过代码来给组件绑定事件所有从父向子传递函数的位置,都可以修改为自定义事件方式。主要改造子向父传数据的功能。

Java_Coding1的博客 253

2023年Java学习路线,精心整理-文中有书籍抽奖

给大家整理了一份2023年最系统、最具有规划、最全面的Java学习路线图

m0_58118573的博客 1283

[记录学习]自学动力节点荣姐SpringMVC5笔记

SpringMVC5 学习笔记

sls1223074612的博客 4978

论文理解【LLM-OR】——【OptiMUS】Scalable Optimization Modeling with (MI)LP Solvers and Large Language Models

OptiMUS 把“自然语言→优化建模与求解”从单次生成改造成“结构化问题 + 多智能体协作 + 连接图检索”的模块化流程,并在更长更难的数据集上验证了这种结构化方法相对端到端 prompting 的优

佚失的诗篇 823

绕过限制?实测修改UA在PC端运行微信小程序的可行性及风险

本文探讨了通过修改User-Agent(UA)在PC端运行微信小程序的技术可行性及风险。分析了小程序设备限制的技术原理,包括`wx.getSystemInfo`API和UA检测机制,并提供了多种修改方案及其局限性。同时强调了潜在的安全和法律风险,推荐使用官方模拟器或安卓模拟器等更安全的替代方案。

weixin_30879169的博客 363

vue入门第一天,Vue模板

vue中文文档:https://vuejs.bootcss.com/guide/ vue230集的视频:https://www.bilibili.com/video/BV15741177Eh WebStorm 2018.2.3:老版本好破解,哈哈,代码提示也强悍,用HBuilderX基本上写一小时代码要改两小时,VsCode下了一堆插件,代码提示还是一塌糊涂。 暂时就靠这三个家伙了搞定Vue了。 跟着动力节点的老杜学完了他讲的HTML,CSS,JS,JQuery。 然后跟着黑马的pink老师学了段

专注微信小程序 345

CMOS 半加器和全加器&&数字集成电路&& Cadence Virtuoso

数字集成电路——半加器和全加器

计科小学生的博客 1万+

2022年最新整理,动力节点Java自学全套资源

今天整理了java开发的学习路线和相关的学习视频资源,非常适合零基础入门java的小伙伴,希望大家在学习的时候,能够节省时间。 这里有你需要掌握的所有前沿技术,史上最全的Java学习路线资源,从基础到项目实战,而且是最新的教程,按照以下顺序学就完了!纯干货! 一、Java基础阶段 【B站排名第一的】Java零基础视频844集(适合Java 0基础,Java初学入门) https://www.bilibili.com/video/BV1Rx411876f 图书管理系统JavaSE项目实战训练-适合

Java_Leo12的博客 2345

从零开始:用摩尔线程S4000运行开源AI项目的完整流程

本文详细介绍了如何使用摩尔线程S4000 GPU从零开始运行开源AI项目的完整流程,包括硬件选择、驱动安装、容器化环境配置以及典型AI项目的实战部署。通过性能优化技巧,显著提升推理速度,适合开发者快速上手国产GPU的AI应用开发。

weixin_29231725的博客 581

【Bug已解决】codex: tool call timeout / Function execution exceeds limit — CodeX CLI 工具调用超时解决方案

CodeX CLI 工具调用超时(Bash/文件/MCP)的解决方案,含增加超时、拆分命令、后台运行、避免交互卡住与限制读取。

博客 4204

2023年全新版Java学习路线,精心整理【文中送书福利 】

先恭喜你看(学)到了最后,学完的小伙伴记得评论区分享你的进步和心得,鼓励其他Java学习者,大家互动学习,共同成长!

Java___interview的博客 1186

javascript 酷炫时钟

javascript 酷炫时钟

liuhao9999的博客 631

重磅!2021年国内有名的编程培训机构排名公布啦

从市场发展前景来看,在国家和地方政策利好的驱动下,编程课程在学校下沉,另一方面,大批编程机构崛起,对编程开发行业动向感知的同学蜂拥而入,面对形形色色的编程机构,大家往往在选择时要看看培训机构排名的情况,一般排名靠前的都是比较有知名度的,今天小编就给大家分享2021年国内有名的编程培训机构排名,仅供大家参考: 第一名:动力节点 北京动力节点教育科技有限公司(简称:动力节点),目前已累计培训和影响了大量Java软件工程师,是中国Java研发人才一体化服务的倡导者,为解决当前软件开发技术飞速发展,而企业招不到优秀

weixin_54792157的博客 1万+

数学建模学习(5):最全概率分析之图表绘制详解,内容比较多,建议收藏

(1) 绘制正整数频率使用 tabulate(X) (2)

全栈川川 4592

智能车图像处理1-基础图像规格

从厂家摄像头的库函数中,我们可以直接得到完整图像的灰度数组,经过二值化之后(算力允许,可以考虑大津法),就是我们要处理的0-1二值图像了。本系列所有的文章中,我们的图像规格如下。

taiyuezyh的博客 4335

学习建议及顺序

学习建议1.数据结构和算法在学会一门语言后就可以去学一学数据结构和算法,一个优秀的程序员一定是“内外双修”的,不要听网上说“这都是一些没用的八股文”或者说“面试造火箭,工作打螺丝”。

2401_88369734的博客 2402

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

跨专业-Java开发学习路线

Java开发学习路线

qq351159769的博客 819

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

绝不误人子弟!零基础应该选择学习Java、PHP,还是前端?

上周,有读者私信我说,“二哥,零基础该选择 Java 还是 PHP 啊?” 我瞬间就误了!PHP?世界上最好的编程语言? 后来,又有读者私信问我,“挺纠结的,不知道该选前端还是 Java?” 真不好选,因为“男怕入错行,女怕嫁错郎”,初学者纠结这个问题也是情有可原。 首先来说说 PHP,Web 蛮荒的年代,PHP 真的是王者姿态,连 Java 可能都要礼让三分,但近些年,PHP 只能做一些速成型的外包项目了,如果想增加更多的业务,想在性能上有所改善,PHP 就真的很难了! 所以,本着不误人子弟的原则,我

沉默王二 5万+

【B站】Java自学精选视频,Java全套资源奉上,收藏起来慢慢学

现在学习Java的小伙伴越来越多,Java也确实有它独特的魅力并且迎合大中企业需求,而且就业前景好。 2022年了,希望你们能够快速成长,所以我今天精心挑选了一些java相关的视频资源分享给大家,大家一定好好利用起来,这些技术学会之后,工作随便挑,进大厂指日可待,加油。 一、JavaSE阶段 【B站排名第一】动力节点Java零基础视频844集(适合Java 0基础,Java初学入门) https://www.bilibili.com/video/BV1Rx411876f 黑马Java零基础572集

A_coding的博客 2672
上一篇: 动力节点Vue3笔记——Vue程序初体验
下一篇: 动力节点杜老师Vue视频笔记第三章Vue组件化
Java_Coding1
博客等级 码龄5年 9粉丝 46原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值