Vue.js使用了基于 HTML 的模板语法,允许开发者声明式地将 DOM 绑定至底层 Vue实例的数据。所有 Vue.js的模板都是合法的 HTML,所以能被遵循规范的浏览器和 HTML 解析器解析。
在底层的实现上,Vue将模板编译成虚拟 DOM 渲染函数。结合响应系统,Vue`能够智能地计算出最少需要重新渲染多少组件,并把 DOM 操作次数减到最少。
1.创建一个Vue实例
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><!--1- 引入核心模块,提供了构造函数Vue --><script src="lib/vue.js"></script>
</head>
<body></body>
<script>// 1- vm即是Vue实例。// 2- Vue构造函数接收一个配置对象。// 3- 配置对象中可以设置data属性(类型是一个对象)// 4- data对象的属性会作为vm的实例属性(记住)。// 5- 建议将方法放置到methods属性中(类型也是一个对象)// const vm = new Vue({// // 实例中的数据// data:{// a:1,// b:2,// c:{// userName:"zhangsan"// },// d:[1,2,3]// },// // 定义方法// methods:{// fn(){//// }// }// });// console.log(vm);// 关于data的特点:// 1- data中的属性会作为Vue实例中的属性// 2- data的属性值发生改变,那么Vue实例中对应的属性值也会发生改变// 3- Vue实例中的属性值发生改变,那么data中的属性值也会发生改变。const data = {a:1}const vm = new Vue({data});data.a = 100;vm.a = 200;console.log(vm.a,data.a);
</script>
</html>
2.Vue挂载
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><script src="lib/vue.js"></script>
</head>
<body><div class="root" id="root"><h1>{{str}}</h1><h1>{{this.str}}</h1><h1>{{vm.str}}</h1></div>
</body>
<script>// 注意重点:在Vue模板中可以直接使用Vue实例中的属性或方法(不需要使用this,不需要使用this)// 注意重点:模块中可以使用this(不建议),说明模块所处的环境上下文中的this指向的是Vue实例。// 挂载(Vue实例挂载):指定Vue实例应用的范围(元素)const vm = new Vue({// 将ID为root的元素作为Vue实例挂载的元素(挂载的元素自此可以称为Vue模板)// el:document.querySelector("#root"),// 将ID为root的元素作为Vue实例挂载的元素(挂载的元素自此可以称为Vue模板)// el:"#root",// 将class为root的元素作为Vue实例挂载的元素( 不建议)// el:".root",// 将标签名字为div的元素作为Vue实例挂载的元素( 不建议)// el:"div",// el:"body",// 不允许// el:"html",// 不允许data:{str:"我现在开始学习Vue,第一步要进行挂载",vm:{str:"vm"}}})
</script>
</html>
2.1相同Vue实例挂载到不同元素
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><script src="lib/vue.js"></script>
</head>
<body>
<div id="one"><h1>{{str}}</h1>
</div>
<div id="two"><h1>{{str}}</h1>
</div>
</body>
<script>// 同一个页面,支持多个实例挂载至不同元素中。new Vue({el:"#one",data:{str:"one"}})new Vue({el:"#two",data:{str:"two"}})
</script>
</html>
3.插值表达式
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><script src="lib/vue.js"></script>
</head>
<body><div id="root"><!--将Vue实例下的属性num进行渲染--><p>{{num}}</p><!--将Vue实例下的属性str进行渲染--><p>{{str}}</p><!--将字符串进行渲染--><p>{{"str"}}</p><!--将数字进行渲染--><p>{{1}}</p><!--将Vue实例下的属性bol进行渲染--><p>{{bol}}</p><!--将布尔值进行渲染--><p>{{false}}</p><!--将Vue实例下的属性fn进行渲染--><p>{{fn}}</p><!--将Vue实例下的fn函数运行的结果进行渲染--><p>{{fn()}}</p><!--将Vue实例下的属性arr进行渲染--><p>{{arr}}</p><!--将Vue实例下的属性obj进行渲染--><p>{{obj}}</p><p>{{null}}</p><p>{{undefined}}</p><p>{{sex===1?"男":"女"}}</p><p>{{str.split("").reverse().join("")}}</p><template></template></div>
</body>
<script>// 总结1:插值表达式支持字符串,数字,布尔,对象,数组,方法// 总结2:undefined,null不会进行任何输出(与React相同)// 总结3:数组不支持直接展开(React支持)// 总结4:支持输出对象(React不支持)// 总结5:Vue中包裹标签为<template></template>new Vue({el:"#root",data:{num:1,str:"师法魔级超",bol:true,arr:[1,2,3,4],sex:1,obj:{userName:"zhangsan"}},methods:{fn(){return this.str.split("").reverse().join("");}}})
</script>
</html>
4.vue中的指令
4.1v-html与v-text
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><script src="lib/vue.js"></script>
</head>
<body><div id="root"><h3>v-text</h3><p v-text="userName">{{str}}</p><p v-text='userName'>{{str}}</p><p v-text=userName>{{str}}</p><p v-text=`userName`>{{str}}</p><hr/><h3>v-html</h3><p v-html="userName">{{str}}</p><p v-html='userName'>{{str}}</p><p v-html=userName>{{str}}</p><p v-html=`userName`>{{str}}</p><template v-html="userName">123</template></div>
</body>
<script>// 响应式:视图是通过数据进行驱动的(当数据发生改变,视图会根据所使用的数据的变化而变化)// 响应式即是视图会响应最新的数据。// v-text与v-html的共同特点:// 1- 值是一个字符串// 2- 该字符串会作为Vue实例的属性名,将对应的属性值在指令所在的标签中进行输出。// 3- 会覆盖原有数据。// 4- 属性值可以使用双引号,单引号// 5- 属性值也可以省略双引号,单引号// 6- 如果使用的是反引号会将包裹的值在标签中直接输出// 7- 无法与template结合使用。// v-text与v-html的区别:// v-text不支持HTML标签而v-html支持。new Vue({el:"#root",data:{str:"我是一个字符串",userName:"zhangsan"}})</script>
</html>
4.2v-if v-else-if v-else(条件渲染)
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><script src="lib/vue.js"></script>
</head>
<body>
<div id="root"><p>{{isShow}}</p><p>{{isShow && "你好&&"}}</p><p>{{isShow || "你好||"}}</p><!-- 三元表达式 --><p>{{sex===1?"男":"女"}}</p><p>{{fn()}}</p><!--多条件1--><p>{{getAgeStr()}}</p><!--多条件2-使用指令--><p v-if="age>80">老年</p><p v-else-if="age>40">中年</p><p v-else-if="age>28">壮年</p><p v-else-if="age>18">青年</p><p v-else-if="age>12">少年</p><p v-else-if="age>6">儿童</p><p v-else>婴儿</p><hr/><template v-if="isLogin">您好,欢迎您的到来!</template><template v-else><input type="text" placeholder="请输入管理员账号"><input type="text" placeholder="请输入管理员密码"></template>
</div>
</body>
<script>// 注意1:v-if以及v-else-if的值是一个布尔值,如果成立则渲染指令所在的元素,不成立则不渲染// 注意2:v-else-if需要与v-if结合使用// 注意3:v-else=需要与v-if或v-else结合使用// 注意4:v-if,v-else-if,v-else指令所在的元素之间不要出现其它元素。new Vue({el:"#root",data:{isShow:true,sex:1,age:100,isLogin:true},methods:{fn(){return this.sex===1?"男":"女"},getAgeStr(){if(this.age>80) return "老年";if(this.age>40) return "中年"if(this.age>28) return "壮年"if(this.age>18) return "青年"if(this.age>12) return "少年"if(this.age>6) return "儿童"return "婴儿"}}})
</script>
</html>
4.3v-show
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><script src="lib/vue.js"></script>
</head>
<body>
<div id="root">
<!-- <p v-if="isShow">v-if</p>-->
<!-- <p v-show="isShow">v-show</p>-->
<!-- <p v-show='isShow'>1</p>-->
<!-- <p v-show=isShow>2</p>--><p v-show="'isShow'">3</p><p v-show="''">4</p><p v-show="1">5</p><p v-show="0">6</p><p v-show="true">7</p><p v-show="false">8</p><p v-show="null">9</p><p v-show="undefined">10</p>
</div>
</body>
<script>// v-if与v-show的值都是布尔值。// v-if为true表示渲染元素,false表示不渲染元素// v-show为true表示显示元素,false表示隐藏元素(通过display:none)// 注意1:空字符串,0,undefined,null作为判断条件相当于false// 注意2:非空字符串,1作为判断条件相当于truenew Vue({el:"#root",data:{// isShow:true}})
</script>
</html>
4.4v-bind(属性渲染)
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><script src="lib/vue.js"></script>
</head>
<body>
<div id="root"><!--未使用v-bind,直接设置属性值,而不需要使用Vue的实例属性 --><img width="50" src="https://img12.360buyimg.com/pop/s590x470_jfs/t1/169453/32/37700/50662/64ae6e63Fffd824d7/f6409309d91610b1.jpg.avif" alt=""><hr/><!-- 将Vue实例属性imgSrc的值作为src的属性值。 --><img v-bind:width="imgW" v-bind:src="imgSrc" alt=""/><hr/><!-- 使用v-bind,直接设置属性值,而不需要使用Vue的实例属性 --><img v-bind:width="300" v-bind:src="'https://img12.360buyimg.com/pop/s590x470_jfs/t1/169453/32/37700/50662/64ae6e63Fffd824d7/f6409309d91610b1.jpg.avif'" alt=""><hr/><a href="http://www.baidu.com">百度</a><hr/><!-- 将字符串作为href的属性值--><a v-bind:href='"http://www.baidu.com"'>{{siteName}}</a><hr/><!-- 将实例属性siteHref作为href的属性值 --><a v-bind:href="siteHref">{{"百度3"}}</a><hr/><!-- 将实例属性w的值作为img的属性的名字。 --><img v-bind:[w]="imgW" v-bind:[h]="imgH" v-bind:[s]="imgSrc" alt=""/><hr/><a :href="siteHref">{{"百度3"}}</a><img :width="imgW" :src="imgSrc" alt=""><img :[w]="imgW" :[s]="imgSrc" alt="">
</div>
</body>
<script>// v-bind:属性名 有一个简写形式:冒号new Vue({el:"#root",data:{imgSrc:"https://img12.360buyimg.com/pop/s590x470_jfs/t1/169453/32/37700/50662/64ae6e63Fffd824d7/f6409309d91610b1.jpg.avif",imgW:200,imgH:400,siteName:"百度2",siteHref:"http://www.baidu.com",w:"width",h:"height",s:"src"}})
</script>
</html>
4.5style特殊
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><script src="lib/vue.js"></script>
</head>
<body>
<div id="root"><!-- 字符串 --><p style="background:yellow;color:red;">1</p><p :style="'background:yellow;color:red;'">2</p><p :style='"background:yellow;color:red;"'>3</p><p :style ="one">4</p><!-- 对象 --><p :style="{background:'green',color:'pink'}">5</p><p :style="two">6</p><!-- 数组 --><p :style="[{background:'yellow'},{color:'red'}]">7</p><p :style="[bg,cl]">8</p>
</div>
</body>
<script>new Vue({el:"#root",data:{one:"background:yellow;color:red;",two:{background:'green',color:'pink'},bg:{background:"yellow"},cl:{color:"red"}}})
</script>
</html>
4.6class特殊
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><style>.bg{background:yellow;}.cl{color:red;}</style><script src="lib/vue.js"></script>
</head>
<body>
<div id="root"><!-- 字符串 --><p class="bg">1</p><p class="cl">2</p><p class="bg cl">3</p><p :class="'bg cl'">4</p><p :class="one">5</p><!-- 对象:常用 --><!-- class绑定的值可以是对象,对象的属性名即是样式类的名字,值是布尔。如果为true类生效,否则无效 --><p :class="{bg:false,cl:true}">6</p><!-- 数组 --><p :class="['bg','cl']">7</p></div>
</body>
<script>new Vue({el:"#root",data:{one:'bg cl'}})</script>
</html>
4.7v-on 事件
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><script src="lib/vue.js"></script>
</head>
<body>
<div id="root"><h3>{{num}}</h3>
<!-- 未简写:--><!-- 1-语句 -->
<!-- <button v-on:click="num++">加1</button>--><!-- 2-函数:当点击按钮会调用Vue实例中的函数changeNum -->
<!-- <button v-on:click="changeNum">加2</button>--><!-- 3-调用函数:函数名后加括号不会被立即调用 -->
<!-- <button v-on:click="changeNum2(3,$event)">加3</button>--><!-- 1-语句 --><button @click="num++">加1</button><!-- 2-函数:当点击按钮会调用Vue实例中的函数changeNum --><button @click="changeNum">加2</button><!-- 3-调用函数:函数名后加括号不会被立即调用 --><button @click="changeNum2(3,$event)">加3</button>
</div>
</body>
<script>// 语句:如果操作语句比较简单,建议直接写语句// 函数:如果操作比较复杂或要在多个不同的地方调用且不需要传递参数使用函数// 调用函数:如果操作比较复杂或要在多个不同的地方调用且需要传递参数使用调用函数// 如果要传递事件对象可以通过$event// v-on可以简写:@new Vue({el:"#root",data:{num:0},methods:{changeNum(e){this.num+=2;// console.log("changeNum",this)// console.log(e.target.innerText)},changeNum2(num,e){this.num+=num;// console.log("changeNum2",num)console.log(e.target.innerText)}}})
</script>
</html>
4.8v-model
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><script src="lib/vue.js"></script>
</head>
<body>
<div id="root"><!-- 单向绑定:视图不会更新数据,但数据发生改变视图会改变 -->
<!-- <input v-bind:value="str" type="text">-->
<!-- <input :value="str" type="text">--><!-- 双向绑定:视图发生改变数据会变,数据改变视图也会改变 -->
<!-- <input @input="changeStr" :value="str" type="text">-->
<!-- <input @input="str=$event.target.value" :value="str" type="text">-->
<!-- <input @input="changeStr2($event)" :value="str" type="text">--><!-- 可以通过v-model指令实现双向绑定 --><input v-model="str" type="text"><!-- 注意:v-model只可以与表单元素结合使用-->
<!-- <div v-model="str"></div>--><h3>{{str}}</h3>
</div>
</body>
<script>new Vue({el:"#root",data:{str:"大家好!我叫刘德华!"},methods:{changeStr(e){this.str = e.target.value;// console.log(e.target.value)},changeStr2(e){this.str = e.target.value;}}})
</script>
</html>
4.8.1修饰符
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><script src="lib/vue.js"></script>
</head>
<body>
<div id="root"><!-- 修饰符trim:去除左右空格 -->
<!-- <input v-model.trim="str" type="text">-->
<!-- <h3>青龙{{str}}白虎</h3>--><!-- 修饰符number:类型保持为number -->
<!-- <input type="text" v-model.number="a">+<input type="text" v-model.number="b"> <button @click="sum=a+b">=</button>-->
<!-- <input v-model="sum" type="text">--><!-- 修饰符lazy:当失去焦点之后数据才会进行改变。--><input v-model.lazy="str" type="text"><h3>{{str}}</h3><h3>{{str}}</h3><h3>{{str}}</h3><h3>{{str}}</h3><h3>{{str}}</h3><h3>{{str}}</h3>
</div>
</body>
<script>new Vue({el:"#root",data:{str:"蔡徐坤",a:1,b:2,sum:3}})
</script>
</html>
4.9v-for(重点)
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><script src="lib/vue.js"></script>
</head>
<body>
<div id="root"><!-- 1- 数组-->
<!-- <div v-for="item in arr">{{item}}</div>-->
<!-- <div v-for="(value,index) in arr">{{index}}:{{value}}</div>--><!-- 2- 对象-->
<!-- <div v-for="item in obj">{{item}}</div>-->
<!-- <div v-for="(value,key) in obj">{{key}}:{{value}}</div>--><!-- 3- 数字-->
<!-- <div v-for="item in num">{{item}}</div>-->
<!-- <div v-for="(n,i) in num">{{i}}:{{n}}</div>--><!-- 4- 字符串-->
<!-- <div v-for="item in str">{{item}}</div>-->
<!-- <div v-for="(s,i) in str">{{i}}:{{s}}</div>-->
</div>
</body>
<script>new Vue({el:"#root",data:{arr:["zhangsan","wangwu","zhaoliu","yanqi","shenba","qianjiu"],obj:{userName:"zhangsan",age:12},num:10,// [1,2,3,4,5,6,7,8,9,10]str:"我爱你中国,我亲爱的母亲,我为你流泪也为你自豪!"}})
</script>
</html>
4.9.1key
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><script src="lib/vue.js"></script>
</head>
<body>
<div id="root">
<!-- 使用ID-->
<!-- <div :key="item.id" v-for="item in arr">-->
<!-- <h3>《{{item.bookName}}》</h3>-->
<!-- <p>作者:{{item.author}}</p>-->
<!-- <hr/>-->
<!-- </div>--><!-- 使用下标 --><div :key="index" v-for="(item,index) in arr"><h3>《{{item.bookName}}》</h3><p>作者:{{item.author}}</p><hr/></div>
</div>
</body>
<script>new Vue({el:"#root",data:{arr:[{id:1,bookName:"天龙八部",author:"金庸"},{id:2,bookName: "一念永恒",author:"耳根"}]}})
</script>
</html>
5.适用案例
5.1js实现
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>#root button{padding: 5px;margin: 5px;}#root button.active{background: red;}#root div {width: 500px;height: 300px;border: 1px solid green;}</style>
</head><body><div id="root"><button>体育</button><button>娱乐</button><button>财经</button><div>体育新闻列表</div><div>娱乐新闻列表</div><div>财经新闻列表</div> </div>
</body>
<script>const btns = document.querySelectorAll("#root button");const divs = document.querySelectorAll("#root div");let index = 0;btns.forEach(function(item,i){//不让div显示divs[i].style.display = "none";item.onclick = function(){//点击的和显示的div一致的话就不用管了if(i === index) return; //不一致的话要先将元素置空btns[index].className = null;divs[index].style.display = "none";//将当前点击的赋值给indexindex = i;//将点击的显示按钮要高亮btns[index].className = "active";divs[index].style.display = "block";}});//默认的,开头第一个按钮btns[index].className = "active";divs[index].style.display = "block";
</script>
</html>
5.2vue实现
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<style>#root button {padding: 5px;margin: 5px;}#root button.active {background: red;}#root div {width: 500px;height: 300px;border: 1px solid green;}</style>
<script src="lib/vue.min.js"></script>
<body><div id="root">//点击的时候给index赋值 v-bind 拿到index 判断是否是对应的div<button @click="index=0" :class="{active:index === 0}">体育</button><button @click="index=1" :class="{active:index === 1}">娱乐</button><button @click="index=2" :class="{active:index === 2}">财经</button>//判断 index的值<div v-show="index === 0">体育新闻列表</div><div v-show="index === 1">娱乐新闻列表</div><div v-show="index === 2">财经新闻列表</div></div>
</body>
<script>new Vue({el:"#root",data:{index:0}})
</script>
</html>
5.3vue高级实现
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<style>#root button {padding: 5px;margin: 5px;}#root button.active {background: red;}#root div {width: 600px;height: 300px;border: 1px solid green;}
</style>
<script src="lib/vue.js"></script>
<body><div id="root"><button @click="index=i" :class="{active:index===i}" :key="item.id" v-for="(item,i) in newList">{{item.typeName}}</button><div v-show="index ===i" v-for="(data,i) in newList"><p v-for="info in data.items"><a href="info.newsHref" target="_blank">{{info.newsTitle}}</a></p></div></div></body>
<script>new Vue({el:"#root",data:{index:0,newList:[{id:1,typeName:"体育",items:[{id:11,newsTitle:"CBA选秀大会:陈国豪当选状元 邹阳意外跌至第五",newsHref:"https://fans.sports.qq.com/post.htm?id=1771451668139868317&mid=63#1_allWithElite"},{id:12,newsTitle:"从大山里的孩子到CBA职业球员,云南滑翔机矣进宏的故事有多励志?",newsHref:"https://new.qq.com/rain/a/20230715V03AI700"}]},{id:2,typeName:"娱乐",items:[{id:21,newsTitle:"《奔跑吧》后期团队回应!坦言压力很大,曝最后一期能播且很精彩",newsHref:"https://new.qq.com/rain/a/20230715V04IB500"},{id:22,newsTitle:"朱珠一边拍戏一边带娃,抱着女儿候场好心酸,两岁珠宝颜值复刻妈妈",newsHref:"https://new.qq.com/rain/a/20230715V041EZ00"}]},{id:3,typeName:"财经",items:[{id:31,newsTitle:"经济学家姚余栋:房地产是“黄金坑”,能熬出来,还有实实在在的需求",newsHref:"https://new.qq.com/rain/a/20230713V09O3D00"},{id:32,newsTitle:"国常会:我国正处于经济恢复的关键期 要做好能源电力保供工作",newsHref:"https://new.qq.com/rain/a/20230714A08E8400"}]}]}})
</script>
</html>