一. MVC和MVVM的关系
如何把数据放到标签里? 如何渲染页面?
视图框架使用的是数据驱动的方式.(没有DOM操作).
数据驱动: => 给标签绑定数据,要修改标签,直接修改与之绑定的数据即可.(没有DOM操作).
学框架的第一个困难 => 就是无法从DOM操作的思路转换成数据驱动的思路.
DOM操作 VS 数据驱动
MVC VS MVVM
MVC的描述:
- MVC => M是数据model层, V就是视图View层, C就是控制control层
- MVC最最经典的系统就是电视机系统.
- M => 电视节目
- V => 电视机
- C => 遥控器
- MVC模式其实是最早最直观最传统的软件设计模式.
- MVC的缺点是: C太臃肿,功能太多,没有得到合理分工.
- V 呈现数据的视图.
- const oDiv = document.querySelectorAll('#app')[0];
- M 要呈现的数据
- let msg = 'hello Vue!!!';
- C DOM操作把M和V联系在一起.
- oDiv.innerHTML = msg;
- MVVM => M还是数据model层, V还是视图View层, VM数据视图层view-model层
- MVVM => 声控电视系统.(你只需要关注你要做什么,不需要关心怎么做)
二. 插值表达式
// V => el
// M => data
// VM => vm实例。
let vm = new Vue({
// 指定视图.
el: '#app',
// 指定数据
data: {
msg: 'hello Vue!!'
}
});
三. v-bind指令
<body>
<div id='app'>
{{msg}}
<h1>{{msg}}</h1>
<h1>{{0 ? 100 : 200}}</h1>
<h1>{{Math.random()}}</h1>
<h1>{{alert(1000)}}</h1>
<h1>{{x}}</h1>
</div>
<div>{{msg}}</div>
<p>{{msg}}</p>
</body>
{{插值表达式}} => 可以写任意的js表达式
插值表达式内的数据或者方法都应该vm实例的属性或者方法.
alert不是Vm实例的方法,因此会报错.
<script src="js/vue.js"></script>
<script>
let x = 200000;
// vm就是一个Vue实例
let vm = new Vue({
// 确定视图范围.app内部所有的后代元素都可以绑定数据
// el的值是选择器.如果选择器匹配多个元素,则只有第一个生效.
// 不能设置body和html这样的特殊标签作为视图.
el: '#app',
// data内的数据都会变成Vue实例的属性.
data: {
msg: '幂幂',
str: '你好吗'
},
// vm实例的方法都写在methods中.
methods: {
alert() {
window.alert(10000);
return 'alert'
}
}
});
console.log(vm.msg);
console.log(vm.str);
</script>
四. v-bind绑定class
<style>
.active{
background-color: red;
}
</style>
</head>
<body>
<div id='app'>
<h3 v-bind:class='cn'>{{msg}}</h3>
<h3 :class='cn'>{{msg}}</h3>
<input type="text" v-bind:value='val'>
<input type="text" :value='val'>
<input type="text" :value='0 ? 100 : 200'>
<input type="text" :value='"val"'>
</div>
</body>
- v-bind:属性名 => 指令 => 让标签的属性绑定一个Vue数据
- v-bind:的简写是:(冒号)
- 指令的值可以是任意表达式.意即把表达式的返回值绑定到指定是属性上.
<script src="js/vue.js"></script>
<script>
let vm = new Vue({
el: '#app',
data: {
msg: 'Vue!!!',
cn: 'active',
val: 'input的值'
}
})
</script>
五. v-on指令绑定事件
<style>
.active{
background-color: red;
}
</style>
</head>
<body>
<div id='app'>
<button v-on:click='fn'>按钮</button>
<button @click='fn'>按钮</button>
<button @click='show(100, $event)'>按钮</button>
<div>{{msg}}</div>
</div>
</body>
- v-on:事件名 => 指令 => 用来给元素添加事件
- v-on的简写 => @
- v-on事件传参,直接在指令后写函数调用.
v-on使用事件对象.
1:没参数 => 直接通过形参获取.
2:有参数 => 需要手动传入$event
<script src="js/vue.js"></script>
<script>
// 事件句柄内的this默认永远指向当前的vm实例.
new Vue({
el: '#app',
data: {
msg: '你好'
},
methods: {
fn(ev) {
// vm.msg = Math.random();
this.msg = Math.random();
console.log(ev);
},
show(x, ev) {
console.log(x)
console.log(ev)
}
}
});
// 事件传参(React可以):
// 1: click = function () { fn(100) }
// 2: click = fn(100); fn需要返回函数
// 3: click = fn.bind(null, 100);
</script>
六. 条件渲染
<body>
<div id='app'>
<button @click='fn'>按钮</button>
<div v-if='flag'>111111111111111</div>
<div v-show='flag'>111111111111111</div>
<h3 v-if='1>2'>111</h3>
<h3 v-else-if='1<2'>222</h3>
<h3 v-else>333</h3>
</div>
</body>
- v-if => 条件渲染 => 显示隐藏 => 指令值是布尔值. true表示显示,false表示隐藏
- v-if 和 v-show功能一致.(区别要学到虚拟节点)
- v-show 其实是通过display样式来控制显示隐藏的。
- v-if 和 v-else-if 和 v-else 指令可以配合使用.
- if - else if - else
<script src="js/vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
flag: true,
},
methods: {
fn() {
this.flag = !this.flag
}
}
})
</script>
七. v-bind绑定style属性
<body>
<div id='app'>
<div :style='sty'>999999</div>
<div :style='obj'>999999</div>
<div :style='{width: "100px", heigth: "100px", backgroundColor: "red"}'>999999</div>
<div :style='{width: "100px", height: "100px", backgroundColor: color}'>999999</div>
</div>
</body>
- 绑定style属性,还可以写成对象的形式.
<script src="js/vue.js"></script>
<script>
let vm = new Vue({
el: '#app',
data: {
color: 'red',
sty:'width: 100px; height: 100px; background-color: red',
obj: {
width: '100px',
height: '200px',
backgroundColor: 'red',
}
}
})
</script>
八. v-for
<body>
<div id='app'>
<ul>
<li v-for='item in arr'>{{item}}</li>
</ul>
<ul>
<li v-for='(item,i) in arr'>{{i}}--{{item}}</li>
</ul>
<ul>
<li v-for='item in list'>
<a href="#">{{item.title}}</a>
<span>{{item.date}}</span>
</li>
</ul>
<ul>
<li v-for='{title, date} in list'>
<a href="#">{{title}}</a>
<span>{{date}}</span>
</li>
</ul>
</div>
</body>
<script src="js/vue.js"></script>
<script>
// 新闻列表 => 数组 => 插入对应的li => 列表渲染
new Vue({
el: "#app",
data: {
arr: [111, 222, 333, 444],
list: [
{
title: '该死,都是因为我太帅了',
date: '2021-08-09'
},{
title: '该死,都是因为我太帅了',
date: '2021-08-10'
},{
title: '该死,都是因为我太帅了',
date: '2021-08-11'
}
]
}
});
</script>
<body>
<div id='app'>
<ul>
<li v-for='val in list'>{{val}}</li>
</ul>
<ul>
<li v-for='(val, key) in list'>{{key}}---{{val}}</li>
</ul>
</div>
</body>
<script src="js/vue.js"></script>
<script>
// 新闻列表 => 数组 => 插入对应的li => 列表渲染
new Vue({
el: "#app",
data: {
list: {
name: '小陈',
age: 32,
sex: '女'
}
}
});
</script>
九. 嵌套v-for
<body>
<div id='app'>
<ul v-for='val in list'>
<li v-for='item in val'>{{item}}</li>
</ul>
</div>
</body>
- 子v-for可以获取父v-for的临时变量。
- 兄弟元素无法共享v-for的临时变量.
<script src="js/vue.js"></script>
<script>
new Vue({
el: "#app",
data: {
list: {
arr1: [444, 555, 666],
arr2: [111, 222, 333]
}
}
});
</script>
十. 操作数组
<body>
<div id='app'>
<ul>
<button @click='fn'>按钮</button>
<li v-for='(item, i) in arr'>
{{item}}
</li>
</ul>
</div>
</body>
用框架经常遇到的问题: 数据变了视图不变.
<script src="js/vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
arr: [111,222,{name: '幂幂'}]
},
methods: {
fn() {
// 直接修改数组元素,如果这个元素是基本类型.则视图是不会改变的.
// this.arr[0] = Math.random();
// 修改应用类型,可以驱动视图更新
// this.arr[2].name = '超越';
// 直接修改第三个数组的元素变成一个新的对象,视图不会改变.
// this.arr[2] = {name: '超越'};
// 直接修改length视图也不会改变.
// this.arr.length = 0;
// push,pop,shift,unshift,splice,sort,reverse => 这7个方法修改数组可以驱动视图更新
this.arr.splice(0,1,Math.random());
// console.log(this.arr);
}
}
})
</script>
十一. v-model
<body>
<div id='app'>
<input type="text" @input='fn' :value='msg'>
<div>{{msg}}</div>
</div>
</body>
msg绑定到value上.则我希望value变msg也会跟着变.
msg变化,div也跟着变.
<script src="js/vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
msg: '111'
},
methods: {
fn(ev) {
// 把vue数据变成事件源的value.(变成用户输入的东西)
this.msg = ev.target.value;
}
}
})
</script>
<body>
<div id='app'>
<input type="text" v-model='msg'>
<div>{{msg}}</div>
</div>
</body>
v-model => 只用在表单元素上 => 用于实现双向绑定.
双向: 数据变,视图变,视图变,数据也变.
<script src="js/vue.js"></script>
<script>
let vm = new Vue({
el: '#app',
data: {
msg: '111'
}
})
</script>
十二. 复选框v-model
<body>
<div id='app'>
<h3>选择你喜欢的水果</h3>
<hr>
<input type="checkbox" value='苹果' v-model='favo'>苹果
<input type="checkbox" value='香蕉' v-model='favo'>香蕉
<input type="checkbox" value='雪梨' v-model='favo'>雪梨
<hr>
你喜欢的水果:{{favo.join()}}
</div>
</body>
- 绑定数组后,复选框如果是打钩的,则它的value会自动放入绑定的数组.
- 绑定数组后,复选框如果是不打钩的,则它的value会自动从数组内删除.
<script src="js/vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
favo: ['香蕉', '雪梨']
}
})
</script>
<body>
<div id='app'>
<input type="checkbox" v-model='flag'>切换
<div v-if='flag'>111111111111111</div>
</div>
</body>
如果复选框绑定的是一个布尔值.则复选框打钩,这个布尔值会自动变成true,不打钩则会默认变成false
<script src="js/vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
flag: false,
}
})
</script>
十三. 单选框
v-model
<body>
<div id='app'>
<h3>选择你的性别</h3>
<hr>
<input type="radio" value='男' v-model='sex'>男
<input type="radio" value='女' v-model='sex'>女
<hr>
你的性别是:{{sex}}
</div>
</body>
<script src="js/vue.js"></script>
<script>
// 多个单选框绑定同一个数据,则这些单选框就只有一个是可以打钩的.(name的作用)
// 打钩的选项卡,它的value就会变成当前绑定数据的值.
new Vue({
el: '#app',
data: {
sex: '女'
}
})
</script>
十四. 下拉框v-modle
<body>
<div id='app'>
请选择你的出生年份:
<select v-model='year'>
<option>1997</option>
<option>1998</option>
<option>1999</option>
<option>2000</option>
</select>
<div>你的出生年份是:{{year}}</div>
<textarea v-model='msg' cols="30" rows="10"></textarea>
<div>{{msg}}</div>
</div>
</body>
- v-model应该用在select标签上
- 选中的option的内容会自动变成绑定的数据值
<script src="js/vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
year: '1999',
msg: 111
}
})
</script>
十五. 高亮
v-for
<body>
<div id='app'>
<ul>
<li
:style='{backgroundColor: colors[i]}'
v-for='(item,i) in arr'
@click='toRed(i)'
>{{item}}</li>
</ul>
</div>
</body>
<script src="js/vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
arr: [111, 222, 333, 444, 555],
colors: ['', '', '', '', '']
},
methods: {
toRed(i) {
// 循环让所有的元素都变白色.
for (let i = 0; i < this.colors.length; i++) {
this.colors[i] = '';
}
// 当前的变红
this.colors.splice(i, 1, 'red');
}
}
})
</script>
<body>
<div id='app'>
<ul>
<li
:style='{backgroundColor: index==i ? "red" : ""}'
v-for='(item,i) in arr'
@click='toRed(i)'
>{{item}}</li>
</ul>
</div>
</body>
<script src="js/vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
arr: [111, 222, 333, 444, 555],
// 点击的li的下标.
index: null
},
methods: {
toRed(i) {
// 记录被点击的li的下标.
this.index = i;
}
}
})
</script>