一、VUE的认识
Vue是一套用于构建用户界面的渐进式框架,与其他框架不同的是,Vue被设计为可以自底向上渐层应用。Vue的核心库只关注视图层,不仅易上手,还便于与第三方库或既有项目整合。另一方面,当与现代化的工具链以及各种支持类库结合使用时,Vue 也完全能够为复杂的单页应用提供驱动。
VUE官网
二、Vue快速实现购物车案例
<body>
<div id="app" style="border:solid 2px #aaa;padding: 20px;">
<ul>
<li v-for="(item,idx) in goods" :key="item.goodsId">
{{item.goodsId}} -
{{item.goodsName}} -
{{item.stock}}
<button @click="add(idx)" v-if="item.stock-item.sales != 0">+</button>
{{item.sales}}
<button @click="dec(idx)" v-if="item.sales != 0">-</button>
- {{item.stock - item.sales}}
<span v-if="item.stock - item.sales <= 0">卖完了</span>
</li>
</ul>
<p>总销售量:{{sum}}</p>
</div>
</body>
<script src="libs/vue.js"></script>
<script>
const vm = new Vue({
el:"#app",
data:{
goods:[{
goodsName:"手机",
stock:90,
sales:8,
goodsId:0
},{
goodsName:"电脑",
stock:20,
sales:5,
goodsId:1
},{
goodsName:"冰箱",
stock:30,
sales:26,
goodsId:2
}]
},
methods: {
add(i){
this.goods[i].sales++;
},
dec(i){
this.goods[i].sales--;
}
},
computed: {
sum(){
return this.goods.reduce((prev,now)=>{
return prev + now.sales;
},0);
}
},
})
</script>
三、MV*模式
- MVC模式
- M(Model)模型,V(View)视图,C(controller)控制器
- 是使用一种将业务、数据、视图分离的方式组织架构代码
- 组件是架构开发、常常将视图、数据、业务逻辑等写在一个模版内,如果组件内容很多,常常造成层次的混乱,增加开发和日常维护的成本
- MVC模式就说专门处理这种问题 - MVP模式
- 传统的MVC模式虽然可以管理页面系统中的数据,视图,控制器,但是在视图层创建界面时常常会用到模型层内的数据,使模型层和视图层耦合在一起,降低了复用性和灵活性
- MVP模式就是为了解决这方面的问题。
- M(Model)模型,V(View)视图,P(Presenter)管理器
- 视图层不再直接引入模型层中的数据,而是通过管理层实现对模型层内的数据的访问。
- 即所有层次的交互都发生在管理层中,从而降低了模型层和视图层之间的耦合关系,提升了灵活性和复用性 - MVVM模式
- 在MVP模式中,所有的操作都在管理层中,因此必须创建管理器才能实现需求,但是对于开发者来说,如果js学习的不深入,操作管理器的成本其实很大。
- MVVM模式的出现就是为了进一步的减少这种操作成本,使开发者只需要通过操作html就能创建视图实现页面需求
- M(Model)模型,V(View)视图,VM(ViewModel)视图模型层。
- 为视图层量身定做一套视图模型,并在视图模型中创建属性和方法,为视图层绑定数据并实现交互
- MVVM模式是从MVC模式和MVP模式演化而来,因此它主要也是分离视图和模型。
- 不同的是MVVM模式使视图层更加灵活,可以独立于数据层和视图层,实现独立修改,自由创建。
- MVVM模式是对视图模型层的高度抽象,因此当多个视图层对应一个视图模型层时,也使得视图模型层内的代码逻辑变得高度复用。
- 这样可以极大的方便不懂js的人,只要了解简单的html内容并按照视图层的规范格式创建视图即可,开发人员就可以专注于开发视图模型层内的业务逻辑。
四、VUE的使用
使用
- 引入
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
- 初始化VUE
const vm = new Vue(options);
- options解析
- Vue的配置信息,对象数据,键名由Vue指定,值由Vue约束
- 内含多个选项,如:el,data,methods,computed等… - el选项
//用于标记需要使用vue渲染的容器
<body>
<div id="app">
</div>
</body>
<script src="libs/vue.js"></script>
<script>
const vm = new Vue({
el:"#app" // 需要使用vue渲染的容器
})
</script>
- data选项 + 模板语法-插值
//用于设置vue实例中需要使用的数据
<body>
<div id="app">
<div v-bind:title="tit">{{msg}}</div>
</div>
</body>
<script src="libs/vue.js"></script>
<script>
const vm = new Vue({
el:"#app",
data:{ // 当前vue实例中需要使用的数据,以键值对的形式存在
msg:"hello vue",
tit:"鼠标悬停效果"
}
})
</script>
五、模版语法
vue提供的固有指令
指令 | 功能 |
---|---|
v-text | 模版语法-差值-不解析html |
v-html | 模版语法-差值-解析html |
v-show | 条件判断 |
v-if | 条件判断 |
v-else | 条件判断 |
v-else-if | 条件判断 |
v-for | 列表循环 |
v-on | 绑定事件 |
v-bind | 绑定属性 |
v-model | 双向绑定 |
v-slot | 插槽 |
v-pre | 跳过这个元素和他的子元素的编译过程 |
v-cloak | 这个指令保存在元素上直到关联实例结束编译 |
v-once | 只渲染元素和组件一次 |
差值语法
//{{}}, v-text, v-html
<body>
<div id="app" style="border:solid 2px #aaa;padding: 20px;">
<div>{{msg1}}</div>
<div>{{msg2}}</div>
<div v-text="msg1"></div>
<div v-text="msg2"></div>
<div v-html="msg1"></div>
<div v-html="msg2"></div>
</div>
</body>
<script src="libs/vue.js"></script>
<script>
const vm = new Vue({
el:"#app",
data:{
msg1:"hello vue",
msg2:"<mark>hello vue</mark>"
}
})
</script>
双向绑定
//v-model
<body>
<div id="app">
<!-- 输入框绑定value -->
<input type="text" placeholder="用户名" v-model="username" /><br data-tomark-pass>
<input type="password" placeholder="密码" v-model="password" /><br data-tomark-pass>
<!-- 单选框绑定选中的value -->
<input type="radio" name="sex" v-model="sex" value="1" />男<br data-tomark-pass>
<input type="radio" name="sex" v-model="sex" value="0" />女<br data-tomark-pass>
<!-- 下拉列表绑定选中的项 -->
<select v-model="city">
<option value="北京">北京</option>
<option value="上海">上海</option>
<option value="广州">广州</option>
</select>
<!-- 复选框(多个)绑定选中的项 -->
<input type="checkbox" name="like" value="篮球" v-model="like">篮球
<input type="checkbox" name="like" value="足球" v-model="like">足球
<input type="checkbox" name="like" value="排球" v-model="like">排球
<!-- 文本域绑定内容 -->
<textarea v-model="note"></textarea>
<!-- 复选框(单个)绑定是否选中的布尔值 -->
<input type="checkbox" v-model="flag">同意条款
<input type="button" value="查看用户输入信息" v-on:click="getData">
</div>
</body>
<script src="libs/vue.js"></script>
<script>
const vm = new Vue({
el:"#app",
data:{
username:"",
password:"",
sex:1,
city:"",
like:[],
note:"",
flag:false
},
methods: {
getData(){
console.log(this.$data);
}
}
})
</script>
条件渲染
//v-show, v-if, v-else, v-else-if
<body>
<div id="app" style="border:solid 2px #aaa;padding: 20px;">
<select v-model="state">
<option value="0" selected>0</option>
<option value="1">1</option>
<option value="2">2</option>
</select>
<h1 v-if="state==0">吃饭</h1>
<h1 v-else-if="state==1">睡觉</h1>
<h1 v-else="state">学习</h1>
<hr>
<h1 v-show="state==0">吃饭</h1>
<h1 v-show="state==1">睡觉</h1>
<h1 v-show="state==2">学习</h1>
</div>
</body>
<script src="libs/vue.js"></script>
<script>
const vm = new Vue({
el:"#app",
data:{
state:0
}
})
</script>
if 和 show的区别.gif
v-if 是“真正”的条件渲染
v-show 不管初始条件是什么,都会渲染,只是基于 CSS 的 display 进行切换
使用key值管理可复用元素
<body>
<div id="app" style="border:solid 2px #aaa;padding: 20px;">
<input v-if="loginType === 'username'" :key="0" placeholder="用户名">
<input v-else :key="1" placeholder="密码">
<br data-tomark-pass> <input type="button" v-on:click="setData" v-bind:value="loginType">
</div>
</body>
<script src="libs/vue.js"></script>
<script>
const vm = new Vue({
el:"#app",
data:{
loginType:"username"
},
methods: {
setData(){
this.loginType = this.loginType=="username" ? "password" : "username";
}
},
})
</script>
列表渲染
//v-for + key 属性的使用
<body>
<div id="app" style="border:solid 2px #aaa;padding: 20px;">
<ul>
<li v-for="item in list" :key="item">{{item}}</li>
</ul>
</div>
</body>
<script src="libs/vue.js"></script>
<script>
const vm = new Vue({
el:"#app",
data:{
list:["花生","瓜子","火腿肠"]
}
})
</script>
key的唯一性
同一个父元素的子元素必须有不同的 key。重复的 key 会造成渲染错误。
如果数据自身具有唯一性,可以将数据设置为key值
如果没有唯一的数据,可以将数据的索引设置为key值,但不推荐
尽量让数据拥有唯一的值
循环的嵌套
//循环支持嵌套使用
<div id="app" style="border:solid 2px #aaa;padding: 20px;">
<ul>
<li v-for="val in list" :key="s">
<span>{{val.title}}</span>
<ul>
<li v-for="item in val.items">{{item}}</li>
</ul>
</li>
</ul>
</div>
</body>
<script src="libs/vue.js"></script>
<script>
const vm = new Vue({
el:"#app",
data:{
list:[{
title:"大菜",
items:["红烧肉","糖醋排骨","麻辣鱼头"]
},{
title:"小菜",
items:["酸辣土豆丝","干煸豆角","地三鲜"]
},{
title:"凉菜",
items:["花生米","拌黄瓜","皮蛋豆腐"]
},]
}
})
</script>
注意
不推荐同时使用 v-if 和 v-for
v-if 与 v-for 一起使用时, v-for 比 v-if 的优先级更高。
class与style的绑定
- class的绑定
- 条件写法
<style>
.box{width: 100px;height: 100px;border: solid 1px black;}
.red{background: red;}
</style>
<body>
<div id="app" style="border:solid 2px #aaa;padding: 20px;">
<input type="checkbox" v-model="flag">
<div v-bind:class="flag ? 'box red' : 'box'"></div>
</div>
</body>
<script src="libs/vue.js"></script>
<script>
const vm = new Vue({
el:"#app",
data:{
flag:false
}
})
</script>
- 对象写法
<style>
.box{width: 100px;height: 100px;border: solid 1px black;}
.red{background: red;}
.green{background: green;}
</style>
<body>
<div id="app" style="border:solid 2px #aaa;padding: 20px;">
<div v-bind:class="{box:flag,red:!flag,green:flag}"></div>
</div>
</body>
<script src="libs/vue.js"></script>
<script>
const vm = new Vue({
el:"#app",
data:{
flag:true
}
})
</script>
- 数组的写法
<style>
.box{width: 100px;height: 100px;border: solid 1px black;}
.red{background: red;}
.green{background: green;}
</style>
<body>
<div id="app" style="border:solid 2px #aaa;padding: 20px;">
<div v-bind:class="[style,color]"></div>
</div>
</body>
<script src="libs/vue.js"></script>
<script>
const vm = new Vue({
el:"#app",
data:{
style:"box",
color:"red"
}
})
</script>
- style的绑定
- 对象写法
<p :style="{width:'100px',height:h,background:r}">段落2</p>
- 数组的写法
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app">
<p :style="[s1, s2]">段落3</p>
</div>
</body>
<script src="../vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
var vm = new Vue({
el:"#app",
data:{
s1:{
width:"80px",
height:"50px",
background:"#f0f"
},
s2:{
textAlign:"center"
}
}
})
</script>
</html>
六、事件
事件绑定
- 行内事件
- 可以直接在事件属性中执行js语句
- 不推荐使用,因为在更多情况下,事件的处理可能会更复杂
<body>
<div id="app">
<button v-on:click="msg = 'hello ' + msg">
点击
</button>
<span>{{msg}}</span>
</div>
</body>
<script src="libs/vue.js"></script>
<script>
const vm = new Vue({
el:"#app",
data:{
msg:"vue"
}
})
</script>
- 事件处理方法
- 在methods选项内,定义事件触发方法
- 在事件中调用方法名
- 无法传参
<body>
<div id="app">
<button v-on:click="say">
点击
</button>
<span>{{msg}}</span>
</div>
</body>
<script src="libs/vue.js"></script>
<script>
const vm = new Vue({
el:"#app",
data:{
msg:"vue"
},
methods: {
say(){
this.msg = "你好 " + this.msg;
}
},
})
</script>
3.行内调用事件处理方法
- 在methods选项内,定义事件触发方法
- 在事件中执行
- 可以传参
<body>
<div id="app">
<button v-on:click="say('萨瓦迪卡')">
点击
</button>
<span>{{msg}}</span>
</div>
</body>
<script src="libs/vue.js"></script>
<script>
const vm = new Vue({
el:"#app",
data:{
msg:"vue"
},
methods: {
say(m){
this.msg = m + this.msg;
}
},
})
</script>
事件对象
- 事件处理方法
//在事件处理方法内,接收event参数
<body>
<div id="app">
<button v-on:click="fn">
点击
</button>
</div>
</body>
<script src="libs/vue.js"></script>
<script>
const vm = new Vue({
el:"#app",
methods: {
fn(event){
console.log(event);
}
},
})
</script>
- 行内调用事件
//需要主动将$event传参
<body>
<div id="app">
<button v-on:click="fn($event)">
点击
</button>
</div>
</body>
<script src="libs/vue.js"></script>
<script>
const vm = new Vue({
el:"#app",
methods: {
fn(event){
console.log(event);
}
},
})
</script>
事件修饰符
//事件方法,为了更方便的处理数据逻辑,而不是DOM细节,vue提供了事件修饰符
//.stop: 阻止事件冒泡
//.prevent: 阻止默认事件
//.captrue: 使用事件捕获
//.once: 只会触发一次事件
//.passive: 立即触发滚动事件,不会等待onscroll结束
<!-- 阻止单击事件继续传播 -->
<a v-on:click.stop="doThis"></a>
<!-- 提交事件不再重载页面 -->
<form v-on:submit.prevent="onSubmit"></form>
<!-- 修饰符可以串联 -->
<a v-on:click.stop.prevent="doThat"></a>
<!-- 只有修饰符 -->
<form v-on:submit.prevent></form>
<!-- 添加事件监听器时使用事件捕获模式 -->
<!-- 即内部元素触发的事件先在此处理,然后才交由内部元素进行处理 -->
<div v-on:click.capture="doThis">...</div>
<!-- 只当在 event.target 是当前元素自身时触发处理函数 -->
<!-- 即事件不是从内部元素触发的 -->
<div v-on:click.self="doThat">...</div>
<!-- 点击事件将只会触发一次 -->
<a v-on:click.once="doThis"></a>
<!-- 滚动事件的默认行为 (即滚动行为) 将会立即触发 -->
<!-- 而不会等待 `onScroll` 完成 -->
<!-- 这其中包含 `event.preventDefault()` 的情况 -->
<div v-on:scroll.passive="onScroll">...</div>
按键修饰符
- 监听键盘事件时,方便查找具体的键
//监听键盘事件时,方便查找具体的键
//.enter:查找回车键
//.tab:查找tab键
//.delete:(捕获“删除”和“退格”键)
//.esc:查找esc键
//.space:查找空格键
//.up:查找上键
//.down:查找下键
//.right:查找右键
//.left:查找左键
//还可以通过全局config.keycodes对象自定义按键修饰符别名:
// 可以使用 `v-on:keyup.f1`
Vue.config.keyCodes.f1 = 112
系统修饰键
- 用来做组合键的系统按键
- .ctrl
- .cla
- .shift
- .meta
注意:在 Mac 系统键盘上,meta 对应 command 键 (⌘)。在 Windows 系统键盘 meta 对应 Windows 徽标键 (⊞)。在 Sun 操作系统键盘上,meta 对应实心宝石键 (◆)。在其他特定键盘上,尤其在 MIT 和 Lisp 机器的键盘、以及其后继产品,比如 Knight 键盘、space-cadet 键盘,meta 被标记为“META”。在 Symbolics 键盘上,meta 被标记为“META”或者“Meta”
表单修饰
- .lazy
//在默认情况下,v-model 在每次 input 事件触发后将输入框的值与数据进行同步。添加 lazy 修饰符,从而转为在 change 事件之后进行同步:
<!-- 在“change”时而非“input”时更新 -->
<input v-model.lazy="msg">
- number
- 即使在 type=“number” 时,HTML 输入元素的值也会返回字符串。
- 如果想自动将用户的输入值转为数值类型,可以给 v-model 添加 number 修饰符:
<input v-model.number="age" type="number">
- .trim
- 如果要自动过滤用户输入的首尾空白字符,可以给 v-model 添加 trim 修饰符:
<input v-model.trim="msg">