Vue:vue基本用法 + 指令系统 + 小案例(轮播图 音乐播放器)
Vue的基本用法
模板语法的使用 {{ }}
可以渲染 属性、字符串、运算、字典、对象、三元运算、反转、标签等
步骤:引包 + 实例化对象
<body> <div id="app">
<!--模板语法 可以直接使用 data 中的key --> <h2>{{ msg }}</h2> <h3>{{ 'hhahda' }}</h3> <h3>{{ 1+1 }}</h3> <h4>{{ {'name':'alex'} }}</h4> <h5>{{ person.name }}</h5> <h2>{{ 1>2? '真的': '假的' }}</h2> <p>{{ msg2.split('').reverse().join('') }}</p> //反转 <div>{{ text }}</div>
</div>
<!--1.引包--> <script src='./vue.js'></script> <script>
//2.实例化对象 new Vue({ el:'#app', //绑定标签 data:{ //数据属性 种子 msg:'苹果', person:{ name:'wusir' }, msg2:'hello Vue', text:'<h2>天空</h2>' } });
</script> </body>
Vue指令系统的使用
vue指令是写在标签里的。
指令 (Directives) 是带有 v- 前缀的特殊特性。指令特性的值预期是单个 JavaScript 表达式 (v-for 是例外情况,稍后我们再讨论)。指令的职责是,当表达式的值改变时,将其产生的连带影响,响应式地作用于 DOM。
一、v-text 和 v-html
v-text相当于innerText,渲染的是字符串 v-html相当于innerHTML,带有标签的会渲染成标签
示例:
<body> <div id="content"> {{ msg }} <div v-text="msg"></div> <div v-html="msg"></div> </div> <!--1.引包--> <script src='./vue.js'></script> <script> new Vue({ el: '#content', data() { //data中是一个函数 函数中return一个对象,可以是空对象 但不能不return return { msg: "<h4>alex</h4>" } } }) </script> </body>
效果:

二、v-if 和 v-show
v-if 和 v-show 都是用来控制DOM元素的显示和隐藏的,true(显示),false(隐藏)
1、v-show
相当于 style.display=none,不管初始条件是什么,元素都会被渲染,并且只是简单地基于 CSS 进行切换。
使用场景:需要非常频繁的切换时使用,因为它有更好的初识渲染开销
2、v-if
是真正的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。
也是惰性的,如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。
使用场景:如果在运行时条件很少改变(切换),因为它有更高的切换开销,
3、v-if 和 v-else 的使用
两者是相反的,一个创建,另一个就销毁,
4、示例
<style> .box{ width:200px; height: 200px; background-color: red; } .box2{ width:200px; height: 200px; background-color: green; } </style> </head> <body> <div id="content"> {{ add(2,3) }} <!--{{}}只能用在标签中间,不能用在标签属性里,且标签属性中指令系统对应的值必须是字符串,且字符串中的值必须是实例化对象中的属性或方法--> <!--(1)获取事件源对象(这里直接获取了);(2)绑定事件v-on:事件=调用函数名 ,此函数就是事件处理(数据驱动)--> <button v-on:click = 'handlerClick'>隐藏</button>
<div class="box" v-show='isShow'></div> #单纯的显示和隐藏 <div class="box2" v-if='isShow'></div> #条件渲染,创建和销毁 <div v-if="Math.random() > 0.5">有了</div <div v-else>没有了</div> </div> <!--1.引包--> <script src="../vue.js"></script> <!--2.实例化对象--> <script> // 数据驱动 new Vue({ el:'#content', //绑定标签 data() { //单体模式 //data是一个函数,函数中return一个对象,可以是空对象,但不能不return return{ msg:'<h2>haha</h2>', isShow:true }//data里有内置监听Observer机制,这里变化了那么标签中也会跟着变化 }, methods:{ add(x,y){ return x+y }, handlerClick(){ //数据驱动 console.log(this); this.isShow = !this.isShow; #直接取反即可 } } }) </script> </body>
运行机制:

效果:

三、v-bind 和 v-on
1、v-bind
可以绑定标签中的任何属性,简写为冒号 :
2、v-on
可以监听 js 中的所有事件,click、mouseenter、mouseleave等事件,简写为 @
举例:
v-bind:src 等价于 :src
v-on:click 等价于 @click
示例1:
需求:加载图片,绑定图片的地址
<div id="app"> <!--v-bind 标签中所有的属性 img标签src alt,a标签的href title id class--> <img v-bind:src="imgSrc" v-bind:alt="msg"> #绑定属性 </div> <script src="../vue.js"></script> <script> // 数据驱动视图,设计模式 :MVVM,, Model(数据) View(视图标签) ViewModel(模板语法、指令系统) //声明式JavaScript框架,DOM操作是命令式 new Vue({ el:'#app', //绑定标签 data() { //单体模式 //data是一个函数,函数中return一个对象,可以是空对象,但不能不return return{ imgSrc:"./1.jpg", msg:"图片加载失败", } } }) </script>
示例2:
需求:点击按钮,绑定点击事件,切换盒子的颜色,通过控制类名来显示盒子的颜色
<style> .box{ width:200px; height: 200px; background-color: red; } .active{ background-color: green; } </style> </head> <body> <div id="app"> <img v-bind:src="imgSrc" v-bind:alt="msg"> <!--绑定类--> <button v-on:click = 'handerChange'>切换颜色</button> <div class="box" v-bind:class="{active:isActive}"></div> </div> <!--1.引包--> <script src="../vue.js"></script> <!--2.实例化对象--> <script> // 数据驱动视图,设计模式 :MVVM,, Model(数据) View(视图标签) ViewModel(模板语法、指令系统) new Vue({ el:'#app', //绑定标签 data() { //单体模式 //data是一个函数,函数中return一个对象,可以是空对象,但不能不return return{ isActive:true } }, methods:{ handerChange(){ this.isActive = !this.isActive } } }) </script> </body>
效果:

四、v-for 一定要绑定 :key
v-for 是遍历循环,生成标签,一定要加 :key 不然会警告,
一定要绑定key,不绑定,数据发生变化,会出现错误,
在指令中 v-for 的优先级高
<div id="app"> <!--遍历列表--> <ul v-if = "data.status === 'ok'"> <!--绑定key标识(diff算法):为了减少性能消耗,实际上每个li各自数据,当我们修改这里的列表的数据的时候,不用重新遍历渲染,不用计算内部的DOM--> <!--key绑定时如果item有id,就绑定id,没有就绑定index-->
<!--这里的优先级,v-for 高于 v-bind--> <li v-for = '(item,index) in data.users' :key = "item.id"> <h3>{{ item.id }}--{{ item.name }}--{{ item.age }}</h3> </li> </ul> <!--遍历对象 先value 后 key--> <div v-for = '(value,key) in person'> {{ key }}---{{ value }} </div> </div> <!--1.引包--> <script src="../vue.js"></script> <!--2.实例化对象--> <script> new Vue({ el:'#app', //绑定标签 data() { //单体模式 //data是一个函数,函数中return一个对象,可以是空对象,但不能不return return{ data:{ status: 'ok', users:[ {id:1, name:'alex', age: 18}, {id:2, name:'wusir', age: 23}, {id:3, name:'egon', age: 34}, ] }, person:{ name:'axel' } } }, methods:{ } }) </script>
效果:

五、v-model (表单输入 数据双向绑定)
1、v-model是双向数据绑定
即数据到view,view到数据,一方有更改,另一方也会随之更改。
你可以用 v-model 指令在表单 <input>、<textarea> 及 <select> 元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素。尽管有些神奇,但 v-model 本质上不过是语法糖。它负责监听用户的输入事件以更新数据,并对一些极端场景进行一些特殊处理。
2、表单标签
普通input、文本、复选框、
v-model="msg" 意思是将input中的value值,赋值到data中的属性msg中
value 变化 =========》 msg变化 ============》 其他标签value值也变化
3、修饰符
v-model.lazy='mag' 懒监听
v-model.number='age' 只能是数字
v-model.trim='msg' 清除前后空格
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>Title</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <style> h3{ color: red; } </style> </head> <body> <div id="app">
<h3>input框和p标签</h3> <label for="username">用户名:</label> <input type="text" v-model="msg" id="username">
<p>{{ msg }}</p>
<!--懒监听--> <input v-model.lazy="msg" > :懒监听 <br> <!--数字显示--> <input v-model.number="age" type="number"> :数字显示 <br> <!--清除前后空格--> <input v-model.trim="msg"> :清除前后空格 <br> <hr>
<h3>textarea文本</h3> <textarea placeholder="add multiple lines" v-model='msg'></textarea> <hr>
<h3>复选框</h3> <input type="checkbox" id="checkbox" v-model="checked"> <label for="checkbox">{{ checked }}</label> <hr>
<!--多个复选框 使用列表保存--> <h3>多个复选框 使用列表保存</h3> <input type="checkbox" id="jack" value="Jack" v-model="checkedNames"> <label for="jack">Jack</label> <input type="checkbox" id="john" value="John" v-model="checkedNames"> <label for="john">John</label> <input type="checkbox" id="mike" value="Mike" v-model="checkedNames"> <label for="mike">Mike</label> <br> <span>Checked names: {{ checkedNames }}</span> <hr>
<h3>下拉菜单</h3> <select v-model="selected"> <option disabled value="">请选择</option> <option>A</option> <option>B</option> <option>C</option> </select> <span>Selected: {{ selected }}</span> </div> <script src="vue.js"></script> <script> new Vue({ el: '#app', data() { return { msg: '大海', checked: false, checkedNames: [], selected:'', age:0 } } }) </script> </body> </html>
效果:

4、@input事件
数据双向绑定的实现,基于 input 事件
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>Title</title> <meta name="viewport" content="width=device-width, initial-scale=1"> </head> <body> <div id="app"> <!-- 双向数据绑定实现 @input --> <input type="text" :value="msg" @input = 'changeHandler'> <p>{{ msg }}</p> </div> <script src="vue.js"></script> <script> //Object.definePropty() new Vue({ el:'#app', data(){ return { msg:'alex' } }, methods:{ changeHandler(e){ this.msg = e.target.value //等于input中的value值,即输入的内容 } } }) </script> </body> </html>
小案例
一、轮播图
需求:
通过上一张和下一张按钮点击进行翻页,并能够实现自动翻页
<body> <div id="app"> <img :src="images[currentIndex].imgSrc" alt=""> # img绑定图片地址 <br> <button @click="perHandler">上一张</button> <!--<button @click='nextHandler'>下一张</button>--> <button @click='nextHandler'>下一张</button> </div> <script src="./vue.js"></script> <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script> <script> new Vue({ el: "#app", data() { return { images: [ {id: 1, imgSrc: './images/1.jpg'}, {id: 2, imgSrc: './images/2.jpg'}, {id: 3, imgSrc: './images/3.jpg'}, {id: 4, imgSrc: './images/4.png'} ], currentIndex: 0 } }, methods: { perHandler(e) { this.currentIndex--; if (this.currentIndex == -1) { this.currentIndex = 3; } }, nextHandler(e) { this.currentIndex++; //更改图片地址 if (this.currentIndex == 4) { this.currentIndex = 0; } }, }, // 组件创建完成时就调用,vue的钩子函数 created() { //this指向问题 能用箭头函数 不要用匿名函数 // ajax、axios、定时器都要用箭头函数
//开定时器让轮播图自动滚动 setInterval(() => { // console.log(this); //vue对象 this.currentIndex++; if (this.currentIndex == 4) { this.currentIndex = 0; } }, 2000); //如果不用箭头函数的话,可以先声明一个 vue的this,(_this),在函数中 let _this = this; // _this表示的是vue对象 setInterval( function () { console.log(_this); },1000) } }) </script> </body>
二、vue 中使用 ajax(重要)
需求:
通过请求接口,获取分类列表,然后点击谁,谁变成红色
通过 for 循环获取标签span,然后通过点击事件控制类名,来改变颜色
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>Title</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <style> span.active{ color:red; } </style> </head> <body> <div id="app"> <div>
<!-- for的优先级最高,一定要有:key, @click点击事件, :class符合条件就添加类名 --> <span @click = 'handlerClick(index,category.id)' v-for = '(category,index) in categoryList' :key = 'category.id' :class = '{active:currentIndex==index}'> {{category.name}} </span> </div> </div> <script src="./vue.js"></script> <!--axios--> <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script> <script> let vm = new Vue({ el: '#app', data() { return { categoryList:[], currentIndex:0 } }, methods: { handlerClick(i,id){ this.currentIndex = i; //发起请求 $.ajax({ url:`https://www.luffycity.com/api/v1/courses/?sub_category=${id}`, //该接口是路飞的接口 type:'get',
//要使用箭头函数 success:(data) => { var data = data.data; console.log(data);
<!-- 这里暂时未做处理 --> } }) } },
//组件创建完成, ajax vue的钩子函数 created() { //this指向问题 ajax请求要用箭头函数 不要用匿名函数,获取分类列表 $.ajax({ url:"https://www.luffycity.com/api/v1/course_sub/category/list/", //该接口是路飞的接口 type:"get", success: (data) => { console.log(data); if (data.error_no === 0){ var data = data.data; //‘全部’不属于接口中的,因此需要手动添加到列表中 let obj = { id:0, name:'全部', category:0 }; this.categoryList = data; this.categoryList.unshift(obj) //unshift是插到数组的第一个位置 } }, error:function (err) { console.log(err); } }) } }) </script> </body> </html>
效果:


三、音乐播放器
需求:
1、前端显示音乐按钮,显示歌手名、歌名
2、点击相应歌名,播放相应歌曲
3、当一首歌播放完成后,自动播放下一曲
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>Title</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <style> ul li.active{ background-color: darkcyan; } </style> </head> <body> <div id="music"> <!--@ended事件,当媒体播放完成 会自动调用该方法,执行该脚本,自动播放下一首--> <audio :src="musicData[currentIndex].songSrc" controls autoplay @ended = 'nextHanlder'></audio> <ul> <!-- 循环歌名,展示 --> <li @click = 'songHandler(index)' v-for = '(item,index) in musicData' :key="item.id" :class = '{active:index===currentIndex}'> <h2>歌手:{{ item.author }}</h2> <p>歌名:{{ item.name }}</p> </li> </ul> </div> <script src="./vue.js"></script> <script> var musicData = [{ id: 1, name: '于荣光 - 少林英雄', author: '于荣光', songSrc: './static/于荣光 - 少林英雄.mp3' }, { id: 2, name: 'Joel Adams - Please Dont Go', author: 'Joel Adams', songSrc: './static/Joel Adams - Please Dont Go.mp3' }, { id: 3, name: 'MKJ - Time', author: 'MKJ', songSrc: './static/MKJ - Time.mp3' }, { id: 4, name: 'Russ - Psycho (Pt. 2)', author: 'Russ', songSrc: './static/Russ - Psycho (Pt. 2).mp3' } ]; new Vue({ el: '#music', data() { return { musicData:[], currentIndex:0 } }, methods:{ //点击那首歌播放哪一首 songHandler(i){ this.currentIndex = i; }, //播放下一首 nextHanlder(){ this.currentIndex++; } }, created(){ //赋值变量 this.musicData = musicData } }) </script> </body> </html>
效果:

利用计算属性(computed)中监听媒体地址:
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>Title</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <style> ul li.active{ background-color: darkcyan; } </style> </head> <body> <div id="music"> <!--@ended 播放完成 会自动调用该方法--> <audio :src="currentSong" controls autoplay @ended = 'nextHanlder'></audio> <ul> <li @click = 'songHandler(index)' v-for = '(item,index) in musicData' :key="item.id" :class = '{active:index===currentIndex}'> <h2>歌手:{{ item.author }}</h2> <p>歌名:{{ item.name }}</p> </li> </ul> </div> <script src="./vue.js"></script> <script> var musicData = [{ id: 1, name: '于荣光 - 少林英雄', author: '于荣光', songSrc: './static/于荣光 - 少林英雄.mp3' }, { id: 2, name: 'Joel Adams - Please Dont Go', author: 'Joel Adams', songSrc: './static/Joel Adams - Please Dont Go.mp3' }, { id: 3, name: 'MKJ - Time', author: 'MKJ', songSrc: './static/MKJ - Time.mp3' }, { id: 4, name: 'Russ - Psycho (Pt. 2)', author: 'Russ', songSrc: './static/Russ - Psycho (Pt. 2).mp3' } ]; new Vue({ el: '#music', data() { return { musicData:[], currentIndex:0 } },
// computed:{ currentSong () { return this.musicData[this.currentIndex].songSrc } }, methods:{ songHandler(i){ this.currentIndex = i; }, nextHanlder(){ this.currentIndex++; } }, created(){ this.musicData = musicData } }) </script> </body> </html>
watch侦听器
只能监听一个属性
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>Title</title> <meta name="viewport" content="width=device-width, initial-scale=1"> </head> <body> <div id="app"> <p>{{ msg }}</p> <button @click = 'clickHandler'>修改</button> </div> <script src="vue.js"></script> <script> new Vue({ el:'#app', data(){ return { msg:"alex", age:18 } }, methods:{ clickHandler(){ this.msg = "wusir" } }, watch:{ //watch单个属性,如果想监听多个属性 声明多个属性的监听要用computed //监听是指,在watch中改变了属性的值,标签中也随着改变 'msg':function (value) { console.log(value); if (value === 'wusir'){ this.msg = '大武sir' } }, } }) </script> </body> </html>
computed 计算属性
可以监听多个属性
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>Title</title> <meta name="viewport" content="width=device-width, initial-scale=1"> </head> <body> <div id="app"> <p>{{ myMsg }}</p> <button @click='clickHandler'>修改</button> </div> <script src="vue.js"></script> <script> let vm = new Vue({ el: '#app', data() { return { msg: "alex", age: 18 } }, created() { //定时器 ajax 库 function(){} setInterval(() => { }) }, methods: { clickHandler() { //this的指向就是当前对象 this.msg = "wusir"; this.age = 20; }, clickHandler: function () { console.log(this); } }, computed: { myMsg: function () { //业务逻辑 // 计算属性默认只有getter方法 return `我的名字叫${this.msg},年龄是${this.age}`; } } }) </script> </body> </html>
效果:


浙公网安备 33010602011771号