vue插件内容解析
vue 的实例构建及基本使用
vue2 两种基本使用方式
vue3的两种基本使用
基本交互
1.插值表达式
{{}} vue的插值表达式 => Mustache语法 {{ 变量 }}
功能:用于加载当前容器对应的vue应用提供的-数据仓库变量-
取决于JS框架为其赋予的功能特性,在不同的框架下 语法功能能不同
范围:插值表达式只能被定于标签内容中
使用:<标签>{{ Vue应用数据仓库变量|JS匿名变量|JS表达式|JS内置对象 }}</标签>
记忆:当模板语法处于{{}}内部时,当做JS代码进行开发(注意使用范围)
<div id="app">
<!--
{{}} vue的插值表达式 => Mustache语法 {{ 变量 }}
功能:用于加载当前容器对应的vue应用提供的-数据仓库变量-
取决于JS框架为其赋予的功能特性,在不同的框架下 语法功能能不同
范围:插值表达式只能被定于标签内容中
使用:<标签>{{ Vue应用数据仓库变量|JS匿名变量|JS表达式|JS内置对象 }}</标签>
记忆:当模板语法处于{{}}内部时,当做JS代码进行开发(注意使用范围)
-->
<!-- <p class="{{ msg }}"></p> -->
<p >Vue应用数据仓库变量-msg:{{ msg }}</p>
<!-- <p >JS匿名变量:{{ 匿名字符串 }}</p> -->
<p >JS匿名变量:{{ '匿名字符串' }}</p>
<p >JS匿名变量:{{ 100 }}</p>
<p >JS匿名变量:{{ [1,2,3,4,5,6] }}</p>
<!-- 构建匿名对象时,必须通过空格明确分割语法和对象 -->
<p >JS匿名变量:{{ { a:1,b:2 } }}</p>
<p>vue的仓库变量msg的值是:{{ msg }}</p>
<!-- <p >JS表达式:{{ JS表达式 }}</p> -->
<p>{{ 'vue的仓库变量msg的值是:' + msg }}</p>
<p>{{ num * 100 }}%</p>
<p>arr:{{ arr }}</p>
<p>arr[0]:{{ arr[0] }}</p>
<p>user:{{ user }}</p>
<p>user.username:{{ user.username }}</p>
<p>user['username']:{{ user['username'] }}</p>
<p>flag三目计算:{{ flag?"真":"假" }}</p>
<p>flag三目计算:{{ !flag?"真":"假" }}</p>
<!-- 使用错误 -->
<!-- <p>{{ for(){} }}</p> -->
<!-- <p >JS内置对象:{{ JS内置对象 }}</p> -->
<p>PI:{{ Math.PI }}</p>
<p>random:{{ Math.random }}</p>
<p>random():{{ Math.random() }}</p>
<style>
/* 属性选择器 */
[v-cloak],
[v-html] {
display: none;
}
[v-cloak]+.loading {
display: block;
}
.loading {
display: none;
position: fixed;
top: 0px;
left: 0px;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.6);
color: white;
font-size: 40px;
text-align: center;
padding-top: 200px;
box-sizing: border-box;
}
</style>
</head>
<body>
<div id="app" v-cloak>
<p>插值表达式:{{msg}}</p>
<p v-text="'v-text:'+msg"></p>
</div>
<div class="loading">
loading
</div>
<script type="module">
import { createApp } from "../assets/vue3.0/vue.esm-browser.js"
// 模拟网络状态缓慢的情况
setTimeout(() => {
createApp({
data() {
return {
msg: "仓库数据MSG"
}
}
}).mount("#app")
}, 5000)
6、v-on
- 取值:Function | Inline Statement | Object | Array
* 当事件绑定时取值为 对应 方法名时,可以省略 () 不写
- 事件名称:JavaScript 的 eventName
<div id="app">
<!--
v-on 指令
+ 功能:绑定元素事件监听器,事件类型由参数指定
+ 缩写:@ ,项目中可用 @ 替代 v-on: => @缩写方法必须携带事件名
+ 语法:
<button v-on:事件名称="取值"></button>
<button @事件名称="取值"></button>
- 取值:Function | Inline Statement | Object | Array
* 当事件绑定时取值为 对应 方法名时,可以省略 () 不写
- 事件名称:JavaScript 的 eventName
v-on事件绑定对应的回调方法,根据vue的语法要求应该是容器对应的应用methods方法仓库中定义方法
methods:{
方法名:Function
}
+ methods 中定义方法,在vue程序构建时,会将此区域中的所有方法定义通过 call 方式调用的方法
而 js 中 call函数在执行方法时,可以通过 参数方式设置方法的内部this指向
this 指向被锁死在 当前vue应用实例上;
+ 因为vue在构建应用实例时,数据仓库中的数据,方法仓库中方法,最终都会被直接作为当前vue应用
实例的根数据进行绑定,所以通过构建vue应用实例对象是可以直接方法这些定义数据的
+ methods 定义的一层属性的方法取值为保证this指向,必须是普通函数
-->
<h5>取值:function</h5>
<input type="button" value="v-on:click提示-带()" v-on:click="showInfo()">
<input type="button" value="@click提示-带()" @click="showInfo()">
<!-- 不带() 的写法主要用于 vue组件化开发中 ==> 02vue进阶篇-组件数据传递 详细讲解 -->
<input type="button" value="v-on:click提示-不带()" v-on:click="showInfo">
<input type="button" value="@click提示-不带()" @click="showInfo">
<h5>取值:Inline Statement 赋值行内表达式</h5>
<p>flag:{{ flag }}</p>
<p>flag1:{{ flag1 }}</p>
<input type="button" value="changeFlag" @click="changeFlag()">
<input type="button" value="flag=!flag" @click=" flag = !flag; flag1 = !flag; ">
<h5>取值:Object 通过 v-on 指令一次性完成多事件的绑定操作</h5>
<input type="text" placeholder="input&change-无法执行" v-on=" { input:callbackA(),change:callbackB() } ">
<br>
<input type="text" placeholder="input&change" v-on=" { input:callbackA,change:callbackB } ">
<input type="text" placeholder="input&change-data中的事件对象" v-on="events">
<br>
<input type="text" placeholder="input&change-data中的事件对象" v-on="events1">
<input type="text" placeholder="input&change-data中的事件对象" v-on="events2">
<br>
<input type="text" placeholder="input&change" v-on:input="callbackA()" @change="callbackB()">
<h5>取值:Array 通过 v-on 指令为一个事件绑定多个回调</h5>
<input type="button" value="绑定两个回调-不能执行" @click="[ callbackC(),callbackD() ]">
<br>
<input type="button" value="绑定两个回调" @click="[ callbackC,callbackD ]">
<input type="button" value="绑定两个回调" @click="[ callbackD,callbackC ]">
<br>
<!-- 当一个元素同时出现相同事件绑定的指令时,只有最先绑定的有效 -->
<input type="button" value="绑定两个回调" @click="callbackC()" @click="callbackD()">
<br>
<!-- 实际项目开发中常用的是如下绑定规则 -->
<input type="button" value="绑定两个回调" @click="callbackC(),callbackD()">
</div>
<script type="module">
import { createApp } from "../assets/vue/3.0/vue.esm-browser.js";
import Message from "../assets/message/message.js"
let app = createApp({
data(){
// 仓库方法data中的this在vue3中依然指向于当前vue的应用实例
return {
flag:false,
flag1:true,
events:{
// this.callbackA this.callbackB 来自于 methods 方法仓库
input:this.callbackA,
change:this.callbackB
},
events1:{
input:function(){
console.log("input-匿名-普通方法",this)
},
change:function(){
console.log("change-匿名-普通方法",this)
}
},
events2:{
input:()=>{
console.log("input-匿名-箭头函数",this)
},
change:()=>{
console.log("change-匿名-箭头函数",this)
}
}
}
},
// 方法仓库
methods: {
showInfo:function(){
Message.info({
message:"测试事件绑定"
})
},
changeFlag(){
console.log(app===this);
console.log(app,this);
this.flag = !this.flag;
},
// changeFlag:()=>{
// console.log(app===this);
// console.log(app,this);
// this.flag = !this.flag;
// },
callbackA(){
console.log("input事件触发");
},
callbackB(){
console.log("change事件触发");
},
callbackC(){
console.log("方法1");
// this.callbackD()
},
callbackD(){
console.log("方法2");
}
},
}).mount("#app")
</script>
<div id="app">
<h5>vue2 语法中 取值Object 时 v-on 不能使用 缩写关键字 @</h5>
<!--
v-on = " { 事件名:回调方法|表达式 , …… } "
v-on 对象取值绑定方式 不支持 @ 缩写关键字的
对象中事件的对应回调方法不能被调用
-->
<input type="text" placeholder="input&change" v-on=" { input:callbackA,change:callbackB } ">
<!-- <input type="text" placeholder="input&change" @=" { input:callbackA,change:callbackB } "> -->
<h5>vue2 语法中 v-on 绑定数据取值 data 仓库中变量时 this 的问题</h5>
<input type="text" placeholder="input&change" v-on="events">
</div>
<script type="module">
import Vue from "../assets/vue/2.0/vue.esm.browser.js";
import Message from "../assets/message/message.js"
let vm = new Vue({
el: "#app",
// data:{
// events:{
// input:this.callbackA,
// change:this.callbackB
// },
// },
data() {
console.log(this);
return {
events: {
input: this.callbackA,
change: this.callbackB
},
}
},
methods: {
callbackA() {
console.log("input事件触发");
},
callbackB() {
console.log("change事件触发");
},
},
})
</script>
vue中容器的环境实际上就是与之对应的vue应用实例
在vue容器环境中 ,事件源对象的关键字 被修改为了 $event
vue3 容器页面中的this 为当前容器的应用实例对象
<!-- vue中容器的环境实际上就是与之对应的vue应用实例 -->
<div id="app">
<h5>匿名参数 = v-on 完成事件回调绑定时,以JS语法规范提供参数</h5>
<input type="button" value="事件匿名参数"
@click="printArgs('字符串',123,false,[1,2],{a:1},new Date(),new Set([1,2]) )"
>
<h5>vue应用的仓库变量参数&表达式参数 = 以JS语法规范提供参数(变量只能是容器对应应用的仓库数据)</h5>
<!-- info 获取不到 -->
<input type="button" value="事件仓库变量参数"
@click="printArgs( msg,info,`仓库变量msg的值是:${msg}` )"
>
<h5>事件源对象参数 = 触发该事件的组成对象(对象中记录事件触发时相关功能参数-参数会因触发方式不同发生变化)</h5>
<!-- 在vue容器环境中 ,事件源对象的关键字 被修改为了 $event -->
<input type="button" value="点击事件源对象" @click="printEvent( event )">
<input type="button" value="点击事件源对象" @click="printEvent( $event )">
<h5>容器页面中的this = (不要在容器中使用this关键字)</h5>
<!-- vue3 容器页面中的this 为当前容器的应用实例对象 -->
<input type="text" @input="getInputNewValue1(this.value)">
<input type="text" @input="getInputNewValue1(this)"><br>
<p>nv:{{ nv }}</p>
<input type="text" @input="getInputNewValue( $event.target.value )">
</div>
<script type="module">
let info = "js全局环境的变量";
import { createApp } from "../assets/vue/3.0/vue.esm-browser.js";
createApp({
data(){
return {
msg:"仓库数据变量",
nv:""
}
},
methods: {
// 方法形参定义模式为 ...变量名 ,表示该方法可以接收任意长度的参数
// 参数会被组成数组 提供变量
printArgs(...args){
console.log("参数:",args);
},
printEvent(e){
console.log(e);
},
getInputNewValue1(v){
console.log(v)
},
getInputNewValue(v){
console.log(v)
this.nv = v;
}
},
}).mount("#app")
</script>
vue2 容器页面中的this 是 window 对象
<!-- vue中容器的环境实际上就是与之对应的vue应用实例 -->
<div id="app">
<h5>容器页面中的this</h5>
<!-- vue2 容器页面中的this 是 window 对象 -->
<input type="text" @input="getInputNewValue1(this)"><br>
<input type="text" @input="getInputNewValue1(this.value)">
<p>nv:{{ nv }}</p>
<input type="text" @input="getInputNewValue( $event.target.value )">
</div>
<script type="module">
let info = "js全局环境的变量";
import Vue from "../assets/vue/2.0/vue.esm.browser.js";
new Vue({
el:"#app",
data(){
return {
nv:""
}
},
methods: {
getInputNewValue1(v){
console.log(v)
},
getInputNewValue(v){
console.log(v)
this.nv = v;
}
},
})
</script>
v-on:事件名.修饰符.修饰符……[="回调方法"]<input type="button" value="一次性事件" @click.once="printFun()">
html 结构中,元素存在层级嵌套关系,而页面布局需要使用嵌套元素结构构建复杂页面
但事件是和元素进行的绑定,必然存在部分元素只为了页面效果存在,事件被定义于父元素上
当功能是希望通过任意子元素触发都可以调用父元素事件
为了实现上述功能,html事件操作时引入了事件传播机制 - 子元素被执行了相关事件事件,其父元素也会被执行相关事件 (相同事件)
html事件传播提供两种传播方式 =>
+ 事件冒泡(主流浏览器) :在事件传播机制基础上,由子元素向父元素顺序调用事件
+ 事件捕获 :在事件传播机制基础上,由父元素向子元素顺序调用事件
<!-- 捕获是优先于冒泡 -->
<div class="box" @click.capture="printName('div1')">div1
<div class="box" @click="printName('div2')">div2
<div class="box" @click.stop="printName('div3')">div3
<div class="box" @click.capture="printName('div4')">div4
<div class="box" @click="printName('div5')">div5</div>
</div>
</div>
</div>
</div>
打印结果为:1,4,5,3
.self : 事件只有被绑定的元素才具有权限触发 - 仍然保留事件冒泡(事件穿透)
是只有点击该元素时才会触发事件,点击其他该元素不触发事件
<!-- middle 修饰符只能限制点击效果 -->
<textarea cols="30" rows="5" @click.middle=" setInfo($event) "></textarea>
!!! 按键修饰符 连写为或者关系
<!-- 按键修饰符的连写属于或者关系 -->
<textarea cols="30" rows="5" @keydown.a.b.c.d=" setInfo($event) "></textarea>
<!--
键盘按键和系统按键同时定义时属于 并且关系
-->
<textarea cols="30" rows="5" @keydown.ctrl.a=" setInfo($event) "></textarea>
<br>
<!-- ctrl+a || ctrl+c -->
<textarea cols="30" rows="5" @keydown.ctrl.a.c=" setInfo($event) "></textarea>
<br>
<!-- ctrl+alt+a -->
<textarea cols="30" rows="5" @keydown.ctrl.alt.a=" setInfo($event) "></textarea>
<br>
精确修饰符(2.5+):
<!-- exact 修饰符限制事件触发 只能是 ctrl+alt+a -->
<textarea cols="30" rows="5" @keydown.ctrl.alt.a.exact=" setInfo($event) "></textarea>
<!-- vue2.6^ 版本提供 事件绑定时事件名描述关键字 [] , [] 中定义名字将被作为仓库变量进行加载 -->
<input type="text" v-on:[en]=" msg = $event.target.value "> <br>
<script type="module">
import { createApp } from "../assets/vue/3.0/vue.esm-browser.js";
createApp({
data(){
return {
en:"input",
}
}
}).mount("#app")
Object类型取值=>通过JS对象的key表示样式名,value取值true|false表示样式是否生效
Array类型取值=>提供样式列表,实现样式的循环组合显示=>classList
<style>
body{
padding-bottom: 800px;
}
.fs{
font-size: 24px;
}
.fc{
color: red;
}
.bc{
background-color: #ccc;
}
.border{
border: 4px solid black;
}
</style>
</head>
<body>
<div id="app">
<h4>v-bind 完成 样式属性操作</h4>
<h5>class的动态绑定</h5>
<p>String类型取值=>按照HTML标签属性class取值规则进行定义即可</p>
<!-- 简单样式组成时的动态操作 -->
<div :class=" classStr ">string变量绑定</div>
<input type="button" value="切换fc" @click="changeStringFc()">
<br>
<p>Object类型取值=>通过JS对象的key表示样式名,value取值true|false表示样式是否生效</p>
<div :class=" classObj ">Object变量绑定</div>
<input type="button" value="切换fs" @click=" classObj.fs = !classObj.fs ">
<input type="button" value="切换fc" @click=" classObj.fc = !classObj.fc ">
<input type="button" value="切换bc" @click=" classObj.bc = !classObj.bc ">
<input type="button" value="切换border" @click=" classObj.border = !classObj.border ">
<div :class=" { fc:flag } ">Object变量绑定</div>
<input type="button" value="切换fc" @click=" flag = !flag ">
<br>
<p>Array类型取值=>提供样式列表,实现样式的循环组合显示=>classList</p>
<div :class=" classArr ">Array变量绑定</div>
<input type="button" value="切换fc" @click="changeArrayFc()">
<h5>动静结合绑定操作=>class静态样式定义和动态样式绑定可以同时存在</h5>
<!-- <div :id=" fc " id="a" ></div> -->
<div class="fs bc border" :class=" fc ">动静结合绑定操作</div>
<hr>
<h5>style的动态绑定</h5>
<p>String类型取值=>按照HTML标签属性style取值规则进行定义即可</p>
<div :style=" styleStr ">style-string动态绑定</div>
<p>Object类型取值=>通过JS对象的key表示样式名(可以定义JS的行内样式名),value取值是样式的有效取值(vue会剔除无效属性)</p>
<div :style=" styleObj ">style-Object动态绑定</div>
<div :style=" { color:'red',fontSize:size+'px' } ">style-Object动态绑定</div>
<input type="button" value="+" @click=" size++ ">
<input type="button" value="-" @click=" size-- ">
<p>Array类型取值=>组合程序多个对象的行内样式取值-(复用动态样式)</p>
<div :style=" [ styleObj,styleObj2 ] ">style-Object动态绑定</div>
<h5>动静结合绑定操作=>style静态样式定义和动态样式绑定可以同时存在</h5>
<div style="color:red" :style=" `font-size:${size}px` ">style-动静结合绑定绑定</div>
</div>
<script type="module">
import { createApp } from "../assets/vue/3.0/vue.esm-browser.js";
createApp({
data(){
return {
classStr:"fs fc bc border",
classObj:{
fs:true,
fc:true,
bc:true,
border:true
},
flag:false,
classArr:["fs","fc","bc","border"],
fc:"fc",
styleStr:"color:red;font-size:24px",
styleObj:{
color:"blue",
// "font-size":"24px"
fontSize:"24px"
},
styleObj2:{
border:"2px solid black"
},
size:24
}
},
methods: {
changeStringFc(){
let arr = this.classStr.split(" ");
// console.log(arr);
let i = arr.indexOf("fc")
if(i>=0){
arr.splice(i,1);
}else{
arr.push("fc")
}
this.classStr = arr.join(" ");
},
changeArrayFc(){
let set = new Set(this.classArr);
if(set.has("fc")){
set.delete("fc")
}else{
set.add("fc")
}
this.classArr = Array.from(set);
}
},
}).mount("#app")
</script>

.prop - 将一个绑定强制设置为一个 DOM property。

取值:
* v-if:any
* v-else-if:any
* v-else:不需要表达式,该指令为boolean类型属性
* v-else 指令的上一个兄弟元素(不含注释) 必须使用了 v-if 或者 v-else-if
* v-else-if 指令的上一个兄弟元素(不含注释) 必须使用了 v-if 或者 v-else-if
v-show&v-if 的取值必须是可用于判断的boolean结果,如果取值不是boolean类型,遵守JS转换规则
v-show
* 取值:any
* 功能:根据表达式的 boolean 结果,切换元素的 display CSS 属性,控制元素显示隐藏
* 示例:`<p v-show=" flag "></p>`
v-if
* 取值:any
* 功能:根据表达式的 boolean 结果,描述元素在页面渲染时的创建和删除
<h4>项目开发时什么时候使用v-show,什么时候使用v-if,两者有什么区别</h4>
<ul>
<li>区别:v-show通过css控制元素显示隐藏,而v-if通过元素的创建很删除描述元素的显示和消失</li>
<li>数据安全:v-if项目中存在用户敏感数据需要保护,只能损失性能提高安全性; <br>
程序安全:v-show在程序第一次加载时直接完成元素的创建和渲染操作,然后才完成渲染显示和隐藏操作, <br>
v-if在程序第一加载时就会完成逻辑判断,确认是否需要创建该元素,因此v-if的程序安全性高于v-show
</li>
<li>运行效率:v-show的效率高于v-if => 性能优先的情况下,可以小范围进行性能提升</li>
<li>v-if可以实现多分支连续判断</li>
</ul>
10 、 v-for功能:基于数据多次渲染元素或模板块语法: < 标签 v - for=" 取值变量 in 待循环值 "></ 标签 >< 标签 v - for=" ( 取值变量 , 取值变量 , 取值变量 ) in 待循环值 "></ 标签 >待循环值取值: Array | Object | number | string | Iterable取值表达式:可直接定义临时变量;取值表达式:也可以为数组索引指定别名 ( 或者用于对象的键 ) :<div v-if = "type === 'A'" > A </div><div v-else-if = "type === 'B'" > B </div><div v-else > Not A/B/C </div><div v-for = "item in items" >{{ item.text }}</div><div v-for = "(value, index) in arrs" ></div><div v-for = "(val, key) in object" ></div> <div v-for = "(val, name, index) in object" ></div>
<p>arr:{{ arr }}</p>
<!-- let arr = ["aa","bb","cc"]
for (let str of arr) {
str = "11";
}
console.log(arr) -->
<p>不会对arr进行任何修改,因为str为基本数据类型,修改只在该变量上生效</p>
<ul>
<li v-for="(str, i) in arr">
<input type="text" :value="str" @input=" str = $event.target.value ">
</li>
</ul>
<p>会对arr进行修改,因为arr[i]为引用调用,修改会发生在原数据的地址指向上</p>
<ul>
<li v-for="(str, i) in arr">
<input type="text" :value="str" @input=" arr[i] = $event.target.value ">
</li>
</ul>
<hr>
<pre>list:{{ list }}</pre>
<p>会对list进行修改,因为该数组循环后的每个元素依然是引用数据类型,直接修改该引用数据的属性等同地址指向性修改</p>
<ul>
<li v-for="(p, i) in list">
{{ p.product }}: <input type="text" :value="p.num" @input=" p.num = $event.target.value ">
<input type="button" value="修改销量" @click="setNum(i)">
<input type="button" value="修改销量" @click="setNum2(p)">
</li>
</ul>
</div>
<script type="module">
import { createApp } from "../assets/vue/3.0/vue.esm-browser.js";
createApp({
data(){
return {
sales:[
{
year:"2020",
list:[
{ product: 'Matcha Latte', num:100},
{ product: 'Milk Tea', num:50 },
{ product: 'Cheese Cocoa', num:30 },
{ product: 'Walnut Brownie', num:40 }
]
},
{
year:"2021",
list:[
{ product: 'Matcha Latte', num:80},
{ product: 'Milk Tea', num:60 },
{ product: 'Walnut Brownie', num:70 }
]
},
{
year:"2022",
list:[
{ product: 'Matcha Latte', num:120},
{ product: 'Milk Tea', num:70 },
{ product: 'Cheese Cocoa', num:80 },
{ product: 'Walnut Brownie', num:10 }
]
}
],
arr:["aa","bb","cc"],
list:[
{ product: 'Matcha Latte', num:100},
{ product: 'Milk Tea', num:50 },
{ product: 'Cheese Cocoa', num:30 },
{ product: 'Walnut Brownie', num:40 }
]
}
},
methods: {
setNum(i){
this.list[i].num = Math.ceil(Math.random()*100)
},
setNum2(p){
p.num = Math.ceil(Math.random()*100)
}
},
}).mount("#app")
</script>
v-for为什么一定要加key属性?
辅助属性key
v-for为什么一定要加key属性?
1、用于让vue模板语法对应的数据和标签直接产生唯一对应关系;
2、通过唯一对应关系,可以改变vue的就近渲染原则,提该渲染效率
<!--
就近渲染原则:是保留页面中已存在的数据,基于新的数据进行数据替换,当元素不足时创建新的元素,元素多时删除多余元素
可以有效的减少元素的操作数量提高性能
当使用key 作为唯一时:新增数据向页面进行渲染时,优先判断标签和数据是否对应,如果不是新增标签为该数据提供服务,如果是更新该标签
使用key可以准确判断需要操作的元素,进一步减少元素的操作量,进一步提供程序运行性能
-->
<!--
key 值取值下标和没定义key是一样的
key 的有效取值必须是 数据对于的唯一关联值(来自于服务器后端的 数据 ID)
-->
辅助标签 template
<!--
借用了HTML的 template 元素,通过功能修改实现元素包裹区定义和操作
该标签可以充当临时父元素进行 v-for和v-if 指令调用,但指令一旦执行完成,该标签直接被移除,
不影响页面结构
-->
<div class="list">
<template v-for="(item, index) in list">
<span>ID:{{ item.id }}</span>
<span>NAME:{{ item.name }}</span>
<br>
</template>
</div>
v-if 和 v-for 的辅助渲染辅助属性: key 描述 vue 项目构成的属性在创建删除时不被复用辅助标签: <template> 为 vue 页面提供 无父元素标签的统一操作 结构标签vue2 对于v-if和v-for指令同时定义于一个标签上时,优先执行v-for
+ vue2.0 语法程序可以正常运行 => v-if和v-for同时出现在一个标签上时,
语法解析会先执行v-for,再执行v-if
vue3 对于v-if和v-for指令同时定义于一个标签上时,优先执行v-if
+ vue3.0 语法程序报错 => 直接优先执行 v-if ,最后再执行v-for
<!--
v-memo="[ 判断属性|判断表达式,…… ]" 完成vue渲染的时机判断
当判断发现 绑定的属性或表达式和上一次渲染结果不同,对元素进行重新渲染执行
以此减少渲染次数,提高渲染性能
-->
<li v-for="(item, index) in list" :key="item.id" v-memo="[item.num]">
{{ item.product }}:{{ item.num }}=={{ getStr(item.product) }}
<br>
<!-- num变化 可以触发渲染 -->
<input type="button" value="+" @click="item.num++">
<input type="button" value="-" @click="item.num--">
<br>
<!-- product 无法触发渲染 -->
<input type="text" :value="item.product" @change=" item.product=$event.target.value ">
</li>