历史介绍
angular 09年创建
react 2013年创建
vue在2014年创建,作者尤雨溪
前端框架和库的区别
框架功能齐全,dom+请求发送+路由+模板引擎
库一般只封装了了一些函数,我们自己把控库的代码
使用框架是让框架来运行我们编写的代码,像一些初始化操作和释放资源操作,框架都已经分装好了
vue起步
引包
<!-- 1.引包 -->
<script src="./vue.js"></script>
初始化
<script>
// console.log(Vue);
// 2.初始化
const vm = new Vue({
el: '#app',
// 数据属性
data: {
msg: 'hello vue',
txt: 'hello',
msg2: 'content',
msg3:'<p>插值语法</p>'
},
// 存放的是方法
methods: {
getContent() {
return this.msg + ' ' + this.msg2;
}
}
});
console.log(vm.msg);
</script>
插值表达式
<div id="app">
<h2>{{ msg }}</h2>
<h3>{{ 2 }}</h3>
<h3>{{ "hello" }}</h3>
<h3>{{ {id:1} }}</h3>
<h3>{{ 1>2 ? '真的':'假的'}}</h3>
<h3>{{ txt.split('').reverse().join('') }}</h3>
<h1>{{ getContent() }}</h1>
<h1>{{ msg3 }}</h1>
</div>
- {{表达式内容}}
- 可以用于页面中简单粗暴的测试
- 要使用插值表达式,必须在data对象中声明该字段
指令
在vue中提供了一些可以改变页面和属性的操作,这些操作叫做指令,以v-开头。
指令中封装了一些dom行为,每个指令对应不同属性,这些属性叫做暗号,不同的暗号执行不同的dom操作。
vue常用指令
- v-text :获取元素的textContent属性,必须是双标签,效果和插值表达式一样。
- v-html: 获取元素的innerHtml属性。
- v-if: 控制元素是否初始化
- v-show: 控制元素的显示和隐藏,如果要隐藏,则给元素的style加上display:none
v-if和v-show的区别
v-if是真实控制元素的创建和销毁,它是惰性的,如果指令的值为false,则不创建dom对象,
v-show只是控制元素样式的切换,不管结果是什么,它绑定的dom对象都会进行初始化。
只是将css样式控制为显示和隐藏而已。v-if对于样式切换的开销比较大,所以在样式切换频繁的场景下,
使用v-show,v-show对于初始化的开销比较大。因此对于大量需要初始化的对象时,我们使用v-if。
v-bind使用
<div id='app'>
<a v-bind:href = 'res.url' v-bind:title='res.title'>{{res.name}}</a>
<img :src="imgSrc" alt="">
<h3 class='name' :class = "{active:isActive}">v-bind的用法</h3>
<!-- <h4 :aaa = 'res.name'></h4> -->
<h4 :style='{color:isColor,fontSize:fontSize+"px"}'>hello bind</h4>
</div>
<script src="./vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
res:{
name:'百度',
url:'https://www.baidu.com',
title:'百度一下'
},
imgSrc:'./images/logo.png',
isActive:true,
isColor:'green',
fontSize:30
}
})
</script>
v-bind是用来给元素的属性赋值的,格式为 v-bind:属性名=属性值,简写为:属性名=属性值。
v-on使用
<div id='app'>
<h3>{{num}}</h3>
<button v-on:click.once="handleClick">+1</button>
<div class='box' :class='{active:isActive}'></div>
<button @click='changeClick'>切换</button>
<input v-on:keyup.up="submit">
</div>
<script src="./vue.js"></script>
<script>
/*
1.扫一眼 HTML 模板便能轻松定位在 JavaScript 代码里对应的方法。
2.因为你无须在 JavaScript 里手动绑定事件,你的 ViewModel 代码可以是非常纯粹的逻辑,和 DOM 完全解耦,更易于测试。
3.当一个 ViewModel 被销毁时,所有的事件处理器都会自动被删除。你无须担心如何清理它们。
*/
new Vue({
el: '#app',
data: {
num:0,
isActive:false
},
methods: {
handleClick(){
this.num+=1;
},
changeClick(){
this.isActive = !this.isActive;
},
submit(){
alert(1);
}
},
})
v-on是用来给元素绑定事件的,格式为v-on:事件名=“函数名称”,简写为@事件名=“函数名称”。
v-model使用
v-model是用来双向数据绑定的。内存数据能影响js数据,js数据能影响内存数据。格式为v-model=“数据对象名”
<div id='app'>
<p>{{msg}}</p>
<input type="text" v-model='msg'>
<!-- 复选框单选 -->
<label for="checkbox">{{checked}}</label>
<input type="checkbox" id='checkbox' v-model='checked'>
<div class="box">
<label for="a">黄瓜</label>
<input type="checkbox" id='a' value='黄瓜' v-model='checkedNames'>
<label for="b">西红柿</label>
<input type="checkbox" id='b' value='西红柿' v-model='checkedNames'>
<label for="c">芸豆</label>
<input type="checkbox" id='c' value='芸豆' v-model='checkedNames'>
<br />
<span>{{checkedNames}}</span>
</div>
<label>{{txt}}</label>
<input v-model.lazy="txt">
<label>{{msg2}}</label>
<input v-model.trim="msg2">
</div>
<script src="./vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
msg: '小马哥',
msg2: '',
txt: '',
checked: false,
checkedNames: []
},
methods: {
},
})
</script>
v-model和v-bind的区别
- v-model是双向数据绑定,内存js中的值会影响页面上的值,页面上的值发生改变时也会影响内存中的值。
- v-bind只是简单的单向数据绑定,内存js中的值会影响页面上的值,但是页面上值发生改变不会影响内存中的值。
v-for的使用
基础格式: v-for= ’ item in arr’
对象格式:v-for=‘(val,key)in obj’
数组没有id: v-for=“(item,index) in arr” :class=“index”
<div id='app'>
<div>
<ul>
<li v-for = '(item,index) in menus' :key = 'item.id'>
<h3>{{index}} - id:{{item.id}} 菜名:{{item.name}}</h3>
</li>
</ul>
<ol>
<li v-for = "(val,key) in obj" :key='key'>
{{key}}---{{val}}
</li>
</ol>
</div>
</div>
<script src="./vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
menus:[
{id:1,name:'大腰子'},
{id:2,name:'烤鸡翅'},
{id:3,name:'烤韭菜'},
{id:4,name:'烤大蒜'},
],
obj:{
title:'hello 循环',
author:'小马哥'
}
},
methods: {
},
})
</script>
watch监听器
watch主要监听页面中元素变化对于js内存数据变化造成的影响,浅度监视可以直接监控简单数据类型,深度监视可以监视对象和数组。
<div id='app'>
<input type="text" v-model='msg'>
<h3>{{msg}}</h3>
<h3>{{stus[0].name}}</h3>
<button @click='stus[0].name = "Tom"'>改变</button>
</div>
<script src="./vue.js"></script>
<script>
// 基本的数据类型可以使用watch直接监听,复杂数据类型Object Array 要深度监视
new Vue({
el: '#app',
data: {
msg:'',
stus:[{name:'jack'}]
},
watch: {
// key是属于data对象的属性名 value:监视后的行为 newV :新值 oldV:旧值
'msg':function(newV,oldV){
// console.log(newV,oldV);
if(newV === '100'){
console.log('hello');
}
},
// 深度监视: Object |Array
"stus":{
deep:'true',
handler:function(newV,oldV){
console.log(newV[0].name);
}
}
},
})
</script>
计算属性computed
计算属性是用来计算js内存地址中的数据的一些运算操作的,定义的对象方法可以作为一个数据对象在页面中使用,默认只有get方法。计算属性的好处是当页面中的数据发生变化时,引用它的对应的计算属性也会发生变化,从而产生联动效果。computed计算属性是有缓存的,当js内存中的值没有发生变化,可以去缓存来节约性能。
div id='app'>
{{reverseMsg}}
<h3>{{fullName}}</h3>
<button @click='handleClick'>改变</button>
</div>
<script src="./vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
msg: 'hello world',
firstName: '小马',
lastName: '哥'
},
methods: {
handleClick(){
this.msg = '计算属性computed';
this.lastName = '妹';
}
},
computed: {
// computed默认只有getter方法
// 计算属性最大的优点:产生缓存 如果数据没有发生变化 直接从缓存中取
reverseMsg: function () {
return this.msg.split('').reverse().join('')
},
fullName: function () {
return this.firstName + this.lastName;
}
},
})
</script>
计算属性set方法
对于computed定义的方法,可以指定set方法,此时该计算属性的的值可以向对象一样被其它方法赋值,set方法中可以将该计算属性接受到的新值赋值给另一个变量从而达到数据传递效果。
<div id='app'>
{{content}}
<input type="text" v-model='content' @input = 'handleInput'>
<button @click='handleClick'>获取</button>
</div>
<script src="./vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
msg: '',
},
methods: {
handleInput:function(event){
const {value} = event.target;
this.content = value;
},
handleClick(){
// console.log();
if (this.content) {
console.log(this.content);
}
}
},
computed: {
content:{
set:function(newV){
this.msg = newV;
},
get:function(){
return this.msg;
}
}
},
})
</script>
过滤器filter
过滤器主要是为数据进行添油加醋的,过滤器分为两种,全局过滤器和局部过滤器,全局过滤器对于所有el对象中的data数据都能进行操作,局部过滤器只能针对于当前el对象中的数据属性进行操作。调用过滤器的格式是数据名称| 过滤器名称(参数)
<div id="app">
<h3>{{price | myPrice('¥')}}</h3>
<h3>{{msg|myReverse}}</h3>
</div>
<script src="./vue.js"></script>
<script>
// 创建全局过滤器
Vue.filter('myReverse', (val) => {
return val.split('').reverse().join('');
})
// 为数据添油加醋
// ¥ $20
new Vue({
el: '#app',
data: {
price: 10,
msg:'hello 过滤器'
},
// 局部过滤器
filters: {
myPrice: function (price, a) {
return a + price;
}
}
})
</script>
音乐播放器
此案例能帮忙理解梳理以上指令和生命周期方法
<!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>案例:音乐播放器</title>
<style>
* {
padding: 0;
margin: 0;
}
ul {
list-style: none;
}
ul li {
margin: 20px 20px;
padding: 10px 5px;
border-radius: 3px;
}
ul li.active {
background-color: #D2E2F3;
}
</style>
</head>
<body>
<div id='app'>
<audio :src="currentSrc" controls autoplay @ended='handleEnded'></audio>
<ul>
<li :class='{active:index===currentIndex}' v-for='(item,index) in musicData' :key='item.id'
@click='handleClick(item.songSrc,index)'>
<h2>{{item.id}}-歌名:{{item.name}}</h2>
<p>{{item.author}}</p>
</li>
</ul>
<button @click='handleNext'>下一首</button>
</div>
<script src="./vue.js"></script>
<script>
const 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: '#app',
data: {
musicData,
currentSrc: './static/于荣光 - 少林英雄.mp3',
currentIndex: 0
},
methods: {
handleClick(src, index) {
this.currentSrc = src;
this.currentIndex = index;
},
handleEnded() {
// // 下一首的播放
// this.currentIndex++;
// this.currentSrc = this.musicData[this.currentIndex].songSrc;
this.handleNext();
},
handleNext() {
this.currentIndex++;
if (this.currentIndex === this.musicData.length) {
this.currentIndex = 0;
}
this.currentSrc = this.musicData[this.currentIndex].songSrc
}
}
})
</script>
</body>
</html>
利用计算属性进行优化
利用计算属性,可以简化很多代码,播放哪一首音乐实际上就是对应索引指向的音乐的src,我们来定义一个计算属性,用索引来计算src。
<div id='app'>
<audio :src="getCurrentSongSrc" controls autoplay @ended='handleEnded'></audio>
<ul>
<li :class='{active:index===currentIndex}' v-for='(item,index) in musicData' :key='item.id'
@click='handleClick(index)'>
<h2>{{item.id}}-歌名:{{item.name}}</h2>
<p>{{item.author}}</p>
</li>
</ul>
<button @click='handleNext'>下一首</button>
</div>
<script src="./vue.js"></script>
<script>
const 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: '#app',
data: {
musicData,
currentIndex: 0
},
computed:{
getCurrentSongSrc(){
return this.musicData[this.currentIndex].songSrc;
}
},
methods: {
handleClick(index) {
this.currentIndex = index;
},
handleEnded() {
this.handleNext();
},
handleNext() {
this.currentIndex++;
if (this.currentIndex === this.musicData.length) {
this.currentIndex = 0;
}
}
}
})
</script>