vue:
vue ?
发展历史,产生背景
优势:
核心:数据决定视图,双向数据绑定
MVC:
三层架构:
MVVM: Model View ViewModel vue的实例对象
高亮代码括号的插件
vue的代码提示插件
标签重命名插件
指令 (Directives) 是带有 v-
前缀的特殊 attribute。指令 attribute 的值预期是单个 JavaScript 表达式。指令的职责是,当表达式的值改变时,将其产生的连带影响,响应式地作用于 DOM。解析模板/标签(标签属性,标签体内容,绑定事件等) 例如:
//点击toggle按钮,会显示红色方块,再次点击,红色方块消失,这里就是通过控制属性的真假,通过指令作用到红色方块上来控制方块的显示隐藏
<button v-on:click="isaaa = !isaaa">toggle</button>
<div class="block" v-show="isaaa"></div>
//书写位置:任意 HTML 元素的开始标签内
<p v-if="seen">现在你看到我了</p>
//注意:一个开始标签内可写入多个指令,多个指令间使用空格分隔
<a rel="nofollow" href="javascript:;" :class="{active:timeflag}" @click="queryAll('time')">全部</a>
v-text
语法格式:v-text='表达式'
作用相当于之前学习的DOM操作中的innerText属性,会直接覆盖元素中原本的文本内容,实际开发中使用不多
<p v-text="name+'法撒旦'"></p>
<script>
let app = new Vue({
el:'p',
data:{
stat:true,
name:'张三'
}
})
</script>
v-html
语法格式:v-html='表达式'
作用相当于DOM操作中的innerHTML属性,可以识别字符串中的标签。
<p v-html="msg"></p>
<script>
let app = new Vue({
el:'p',
data:{
msg:'你好哈哈哈'
}
})
</script>
**v-if
v-else-if
v-else
**
作用等同于js代码中的 if else if elseif else 帮助我们按照需求去控制DOM元素的显示与隐藏。
语法格式:v-if='表达式'
v-else-if='表达式'
v-else='表达式'
注意: v-if 和后续的v-else-if v-else都要连续使用,如果中间有间隔,效果是可以正常显示的,但是,控制台会报错。这个特性针对操作同级元素的时候来说。
<body>
<div id="max">
<ul v-if='num>10'>
<li>你好哈哈1</li>
<li>你好哈哈2</li>
<li>你好哈哈3</li>
</ul>
<ul v-else="num>5">
<li>你好嘿嘿1</li>
<li>你好嘿嘿2</li>
<li>你好嘿嘿3</li>
</ul>
</div>
</body>
<script>
let app = new Vue({
el: '#max',
data: {
num: 9
}
})
</script>
v-show
控制元素是否显示,作用等同于css样式的display:none 或非none
语法格式: v-show='true/false'
; true为显示,false为不显示
<div id="max">
<p v-show='stat'>你好哈哈哈</p>
<button v-on:click='tiggleShow()'>点我</button>
</div>
<script type="text/javascript">
let app = new Vue({
el:'#max',
data:{
stat:true,
},
methods:{
tiggleShow(){
this.stat = !this.stat;
}
}
})
</script>
v-if与v-show区别:
v-show指令的元素始终会被渲染到HTML
它只是简单地为元素设置CSS的style属性。当不满足条件的元素被设置style="display:none"样式
v-if指令满足条件是,会渲染到html中,不满足条件时,是不会渲染到html中的
v-if 指令有更高的切换消耗
v-if当条件成立的时候会将元素加上,不成立的时候,就会移除dom,并且内部的指令不会执行
v-show 指令有更高的初始渲染消耗
v-show只是简单的隐藏和显示
如果需要频繁切换使用 v‐show 较好,如果在运行时条件不大可能改变 使用v‐if 较好
v-for
循环遍历 #*
v-for的作用等同于js代码中的for循环,用于循环生成DOM结构,想循环哪个DOM结构,就在哪个DOM结构上添加v-for。
但凡使用到v-for的地方 必须添加第二个属性 :key='id'
<body>
<div id="box">
<!-- 遍历数组
语法 v-for="(item,index) in arr"
item 就表示数组中的每一个数据
index表示下标
-->
<ul>
<li v-for="(item,index) in arr">{{item}}</li>
</ul>
<!-- 遍历普通对象
语法 v-for="(val,key,i) in arr"
val 就表示对象中的每一个值
key 就表示对象中的每一个键值
i就是下标
-->
<ul>
<li v-for="(val,key,i) in user">{{key}}--{{val}}--{{i}}</li>
</ul>
<!-- 遍历字符串 -->
<ul>
<li v-for="(item,i) in str">{{item}}</li>
</ul>
</div>
<script>
let app = new Vue({
el: '#box',
data: {
arr: ['a', 'b', 'c'],
user: { "name": '张三', "age": 18, "address": '郑州' },
str:'abcdefg'
}
})
</script>
</body>
v-on
绑定事件和事件处理
vue的绑定事件的方式,只需要把原生事件名字的on去掉就可以了
例如: onclick === > @click/v-on:click onblur ===> @blur/v-on:blur
普通用法
为 HTML 元素绑定事件监听
v-on:事件名称 =‘函数名称()’
表达式可以是一个方法的名字或一个内联语句
简写语法:@事件名称 =‘函数名称()’
注意:函数定义在 methods 配置项中
<button v-on:click='fn()'>toggle</button>
v-on: 可以简写成 @
<button @click='fn()'>toggle</button>
v-bind
作用:为元素的属性 动态的绑定值
v-bind可以在其名称后面带一个参数,参数通常是HTML元素的属性(attribute),v-bind是动态绑定指令,默认情况下自带属性的值是固定的,为了能够动态的给这些属性添加/修改值可以使用v-bind指令
v-bind:属性名 = ‘表达式’
简写形式:v-bind可以省略,直接书写为 :属性名 = ‘表达式’
<img v-bind:src="imageSrc"> 等价于 <img :src="imageSrc"> //绑定一个属性
v-bind:绑定class
//对象语法
我们可以传给 v-bind:class 一个对象,以动态地切换 class:
格式:<div v-bind:class="{ 类名: 布尔值 }"></div>
//isActive是boolean属性的参数,为true就给div添加类名active,为false就不添加
<div v-bind:class="{ active: isActive }"></div>
可以同时绑定多个类名,也可以和静态类名同时存在
<div class="static" v-bind:class="{ active: isActive, 'text-danger': hasError }"></div>
//数组语法
我们可以把一个数组传给 v-bind:class,以应用一个 class 列表:
<div v-bind:class="[activeClass, errorClass]"></div>
data: {
activeClass: 'active',
errorClass: 'text-danger'
}
<div v-bind:class="[isActive ? activeClass : '', errorClass]"></div>
//绑定多个属性
<div v-bind:class="{'textColor':isColor, 'textSize':isSize}">多个样式的绑定</div>
<div id="box">
<a rel="nofollow" :href="url" v-bind:class='classname'>点我</a>
</div>
<script>
new Vue({
el:'#box',
data:{
url:'http://www.baidu.com',
classname:['aaa','bbb','ccc']
}
})
</script>
v-bind:绑定内联样式
#对象语法
//v-bind:style 的对象语法十分直观——看着非常像 CSS,但其实是一个 JavaScript 对象。CSS property 名可以用驼峰式 (camelCase) 或短横线分隔 (kebab-case,记得用引号括起来) 来命名:
<div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>
data: {
activeColor: 'red',
fontSize: 30
}
//直接绑定到一个样式对象通常更好,这会让模板更清晰:
<div v-bind:style="styleObject"></div>
data: {
styleObject: {
color: 'red',
fontSize: '13px'
}
}
#数组语法
//v-bind:style 的数组语法可以将多个样式对象应用到同一个元素上:
<div v-bind:style="[styleObject,baseStyles, overridingStyles]"></div>
v-model
你可以用 v-model
指令在表单 <input>
、<textarea>
及 <select>
元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素。尽管有些神奇,但 v-model
本质上不过是语法糖。它负责监听用户的输入事件以更新数据,并对一些极端场景进行一些特殊处理。
v-model
会忽略所有表单元素的 value
、checked
、selected
attribute 的初始值而总是将 Vue 实例的数据作为数据来源。你应该通过 JavaScript 在组件的 data
选项中声明初始值。
v-model说白了就像监听器一样,会自动的将vue实例的值同步更新到表单中,同样的也会把表达中的值同步到vue实例中。
这就是双向数据绑定。
**注意:**只有表单元素使用v-model使用才有意义,因为只有表单元素才可以跟用户交互。别的元素使用只能显示数据,没有别的意义。
对input框,操作的是value属性的值:
<body>
<div class="box">
<input type="text" value="你好嘿嘿嘿" v-model='msg'>
<br>
{{msg}}
</div>
<script>
new Vue({
el:'.box',
data:{
msg:'你好哈哈哈'
}
})
</script>
</body>
**对单个复选框操作的是 checked属性的值:**
```html
<body>
<div class="box">
<input type="checkbox" v-model='b'>
<br>
{{b}}
</div>
<script>
new Vue({
el:'.box',
data:{
b:''
}
})
</script>
</body>
此时vue实例中b的值会就跟复选框绑定到了一起。
对多个复选框操作如果在vue实例中是用一个数组接收,接收到是一个数组,里边包含的是被选中的复选框的vlaue值
<body>
<div class="box">
<input type="checkbox" value="1" v-model='b'>
<input type="checkbox" value="2" v-model='b'>
<input type="checkbox" value="3" v-model='b'>
<br>
{{b}}
</div>
<script>
new Vue({
el:'.box',
data:{
b:[]
}
})
</script>
想让哪个框默认选中,就直接把这个框的值写入到vue的实例中去。
对于单选框来说,拿到的是被选中的那个单选框的value属性的值:
<body>
<div class="box">
<input type="radio" value="男" name="sex" v-model="s">男
<input type="radio" value="女" name="sex" v-model="s">女
<br>
{{s}}
</div>
<script>
new Vue({
el:'.box',
data:{
s:""
}
})
</script>
</body>
对于下拉框来说,拿到的是被选中的那个选项的值
<body>
<div class="box">
<select name="" id="" v-model="selected" multiple>
<option value="a">a</option>
<option value="b">b</option>
<option value="c">c</option>
<option value="d">d</option>
</select>
<br>
{{selected}}
</div>
<script>
new Vue({
el:'.box',
data:{
selected:''
}
})
</script>
</body>
此时selected拿到的就是被选中的项的value值,如果是多选的下拉框,此时的selected值就是选中的多个框的value值。
v-model的专用修饰符
.lazy - 取代 input 监听 change 事件
原本的数据绑定相当于对input框进行oninput事件监听,使用v-model.lazy之后相当于把oninput事件换成了onchange事件
.number - 输入字符串转为有效的数字 自动转换为数字
<div id="app">
<input type="text" v-model.number='num1'>+<input type="text" v-model.number='num2'>=<span>{{num1+num2}}</span>
</div>
<script>
new Vue({
el:'#app',
data:{
num1:1,
num2:2
}
})
</script>
.trim - 输入首尾空格过滤
获取事件对象
<div id="max">
<button @click='fn($event)'>点我获取事件对象</button>
</div>
<script>
new Vue({
el: '#max',
methods: {
fn(e){
console.log(e);
}
}
})
</script>
事件修饰符
v-on后面可以增加修饰符
<div @click.stop='fn()'>点我</div>
事件修饰符:
常用:
.stop:调用event.stopPropagation() 阻止事件冒泡
.prevent : 调用event.preventDefault()阻止默认行为
不常用:
.self : 只当事件是从侦听器绑定的元素本身触发时才触发回调
例如:如果不想添加冒泡事件,可以给父子级的元素都添加.self修饰符这样就不会触发冒泡事件,只有在点击元素自身的时候才会触发。
.once:点击事件将只会触发一次
事件只会被触发一次,触发后,底层就会解绑事件 类似于jquery中one()事件绑定
.capture:添加事件监听器时使用事件捕获模式
.passive:滚动事件的默认行为 (即滚动行为) 将会立即触发
按键修饰符
在监听键盘事件时,我们经常需要检查详细的按键。Vue 允许为 v-on
在监听键盘事件时添加按键修饰符:
<!-- 只有在 `key` 是 `Enter` 时调用 `vm.submit()` -->
<input v-on:keyup.enter="submit">
注意:keyCode
的事件用法已经被废弃了并可能不会被最新的浏览器支持。
使用 keyCode
attribute 也是允许的:
<input v-on:keyup.13="fn1">enter键触发
<input v-on:keyup.65="fn2">a键触发
为了在必要的情况下支持旧浏览器,Vue 提供了绝大多数常用的按键码的别名:
.enter
.tab
.delete
(捕获“删除”和“退格”键).esc
.space
.up
.down
.left
.right
有一些按键 (.esc
以及所有的方向键) 在 IE9 中有不同的 key
值, 如果你想支持 IE9,这些内置的别名应该是首选。
你还可以通过全局 config.keyCodes
对象自定义按键修饰符别名:
// 可以使用 `v-on:keyup.f1`
<div id="max">
<input type="text" @keydown.aaa='fn4'>
</div>
<script>
//单个定义
Vue.config.keyCodes.f1 = 112
//当以多个
Vue.config.keyCodes = {
aaa:65,
bbb:66
}
new Vue({
el: '#max',
methods: {
fn4(){
alert('a键被按下了');
}
}
})
</script>
系统修饰键
系统修饰键
.ctrl
.alt
.shift
.meta
注意:在 Mac 系统键盘上,meta 对应 command 键 (⌘)。在 Windows 系统键盘 meta 对应 Windows 徽标键 (⊞)。在 Sun 操作系统键盘上,meta 对应实心宝石键 (◆)。在其他特定键盘上,尤其在 MIT 和 Lisp 机器的键盘、以及其后继产品,比如 Knight 键盘、space-cadet 键盘,meta 被标记为“META”。在 Symbolics 键盘上,meta 被标记为“META”或者“Meta”。
<!-- Alt + C -->同时按下alt键和c键
<input v-on:keyup.alt.67="handler">
#请注意: 修饰键与常规按键不同,在和 keyup 事件一起用时,事件触发时修饰键必须处于按下状态。换句话说,只有在按住 ctrl 的情况下释放其它按键,才能触发 keyup.ctrl。而单单释放 ctrl 也不会触发事件。如果你想要这样的行为,请为 ctrl 换用 keyCode:keyup.17。
.exact
修饰符
2.5.0 新增
.exact
修饰符允许你控制由精确的系统修饰符组合触发的事件。
<!-- 只要按下的键中有ctrl键 事件就可以被触发 -->
<button v-on:click.ctrl="onClick">A</button>
<!-- 有且只有 Ctrl 被按下的时候才触发 -->
<button v-on:click.ctrl.exact="onCtrlClick">A</button>
<!-- 没有任何系统修饰符被按下的时候才触发 -->
<button v-on:click.exact="onClick">A</button>
鼠标按钮修饰符
2.2.0 新增
.left
.right
.middle
这些修饰符会限制处理函数仅响应特定的鼠标按钮。
当点击鼠标右键时才会触发事件
<button @click.right='fn()'>鼠标修饰符</button>
需求说明 使用常见表单元素布局注册页面 使用v-model指令完成对应数据的绑定 填写的表单内容可以显示在表单下方
需求说明 点击“Edit Me”,下方出现文本框,可以自行修改文本 输入框中的文字和页面中的文字保持一致 使用 v-show、v-on、v-model 指令
<video src="assets/点击重新编辑.mp4"></video>
需求说明 完成京东左侧菜单的页面布局 使用 v-for 指令遍历子分类名称,从而显示子分类的列表
需求说明: 点击导航条中的导航项目,当前被点击的项目内容会显示在下方绿色方块中,并且当前被点击项目的背景会变成红色 使用 v-for 指令遍历显示导航项目,使用v-on添加添加事件,使用v-bind指令动态绑定class和key属性
需求:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="./lib/vue.js"></script>
<style>
td{
height: 30px;
text-align: center;
}
</style>
</head>
<body>
<div id="app">
<div>
名称: <input type="text" v-model.trim="gName">
数量: <input type="text" v-model.number="gNum">
是否上架: <select v-model="gState">
<option value="true">上架</option>
<option value="false">下架</option>
</select>
<button @click="addGoods">新增商品</button>
</div>
<table border="1" width="800px">
<thead>
<th><input type="checkbox" @change="checkAll" v-model="allState"></th>
<th>编号</th>
<th>名称</th>
<th>状态</th>
<th>数量</th>
<th>操作</th>
</thead>
<tbody>
<tr v-for="(item,index) in goods">
<td><input type="checkbox" v-model="item.isChecked" @change="reverseChk"></td>
<td>{{item.id}}</td>
<td>{{item.name}}</td>
<td>
<span v-if="item.state">上架状态</span>
<span v-else>下架状态</span>
</td>
<td><button @click="add(item.id)">+</button><span>{{item.num}}</span><button @click="sub(item.id,index)">-</button></td>
<td>
<button @click="del($event,item.id)">删除</button>
<button v-if="item.state" @click="item.state=!item.state">点击下架</button>
<button v-else @click="item.state=!item.state">点击上架</button>
</td>
</tr>
</tbody>
</table>
<span>选中的商品的总数量:{{count}}</span>
</div>
<!-- <button onclick="alert()">点我</button> -->
</body>
<script>
/*
① 根据data数据渲染DOM结构
② 新增商品
③ 删除功能 根据id删除
④ 上下架功能 根据id修改上下架
⑤ 首先把数据中新增一个属性 isChecked
在把这个属性跟页面中的input框做双向数据绑定
全选:给全选框绑定事件
反选:给所有的复选框绑定事件
*/
new Vue({
el:'#app',
data:{
goods:[
{id:1,name:'苹果',state:true,num:5,isChecked:false},
{id:2,name:'香蕉',state:false,num:5,isChecked:false},
{id:3,name:'橘子',state:true,num:5,isChecked:true},
{id:4,name:'甘蔗',state:true,num:5,isChecked:false},
{id:5,name:'荔枝',state:true,num:5,isChecked:false}
],
//定义商品名称
gName:'',
//商品的数量
gNum:0,
//上下架的状态
gState:true,
//商品id
ids:5,
//全选状态
allState:false,
//记录选中的商品的总数量
//count:0
},
methods: {
//定义新增商品的方法/函数
addGoods(){
//1.先创建一个商品对象
let obj = {
id:++this.ids,
name:this.gName,
num:this.gNum,
state:this.gState
}
//2.把数据整体追加到 data中goods中
this.goods.push(obj);
},
//定义删除按钮
del(e,i){
//方式一:DOM方式 不推荐使用
//e.target.parentElement.parentElement.remove()
//e.target.parentNode.parentNode.remove()
//方式二:从数据的角度来删除
/* this.goods.forEach((item,index) => {
if(item.id==i){
//index表示删除的下标 1 表示删除的个数
this.goods.splice(index,1)
}
}); */
//使用数组的filter方法做过滤操作 拿到符合条件的所有结果
this.goods = this.goods.filter(item=>item.id!=i)
},
//定义修改状态的函数
/* changeState(i){
this.goods.forEach((item) => {
if(item.id==i){
//index表示删除的下标 1 表示删除的个数
item.state = !item.state
}
});
} */
//定义全选事件
checkAll(){
//全选:要把购物车中所有的选项的isChecked属性值都变成跟全选框一致
this.goods.forEach((item) => {
item.isChecked = this.allState
});
},
//定义反选事件
reverseChk(){
//点击每一个复选框时,都要对所有复选框做遍历,看里边是否存在isChecked为false的选项
//只要有false 那么allState也等于false
this.allState = this.goods.every(item=>item.isChecked==true)
},
//定义数量的增加方法
add(i){
this.goods.forEach((item) => {
if(item.id==i){
item.num+=1
}
});
},
//定义数量的减少方法
sub(i,a){
//如果数量为1的 就直接return
if(this.goods[a].num==1) return ;
this.goods.forEach((item) => {
if(item.id==i){
item.num-=1
}
});
}
},
computed: {
//计算选中结算的商品总数量
count(){
//先 筛选 出被选中的商品 再 计算中总数量赋值给count
return this.goods.filter(item=>item.isChecked==true).reduce((total,item)=>total+=item.num,0)
}
}
})
</script>
</html>
作业1:学生信息录入系统
作业2:任务列表案例
需求:观察视频中各项特效变化,完成效果。
<video src="assets/todolist.mp4"></video>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../js/vue.js"></script>
<style>
.active{
text-decoration: line-through;
color: gray;
}
</style>
</head>
<body>
<div id="app">
任务列表
<h4>任务总数{{sum()}}; 未完成{{daiban()}};已完成{{sum()-daiban()}}</h4>
<ol>
<li v-for='(item,index) in lists'>
<input :id="item.id" v-model='item.isChecked' type="checkbox">
<span :class="{active:item.isChecked}" @dblclick='showInp1(index)' v-show='item.isEdit'>{{item.content}}</span>
<input type="text" @blur='item.isEdit=true' v-model='item.content' v-show='!item.isEdit'>
</li>
</ol>
<input type="text" v-model.trim='msg'><button @click='add'>添加</button>
<button @click='del'>删除已完成任务</button>
</div>
<script>
let vm = new Vue({
el:'#app',
data:{
lists:[
{isChecked:false,content:'学习java',isEdit:true},
{isChecked:false,content:'学习html',isEdit:true},
{isChecked:false,content:'学习vue',isEdit:true},
{isChecked:false,content:'学习css',isEdit:true}
],
msg:'',
id:0
},
methods:{
//添加任务
add(){
let obj = {
id:++this.id,
isChecked:false,
content:this.msg,
isEdit:true
}
this.lists.push(obj);
},
//定义双击任务时显示input输入框
showInp1(i){
//如果任务是已完成状态此时无法再次编辑
if(this.lists[i].isChecked) return;
//改变当前编辑的数据的isedit的值
this.lists[i].isEdit = false;
},
//任务总数
sum(){
return this.lists.length;
},
//未完成的任务
daiban(){
let aaa = 0;
this.lists.forEach(obj => {
if(!obj.isChecked){
aaa++;
}
});
return aaa;
},
//删除已完成任务
del(){
//通过原生js的数组的fillter方法筛选出未完成的任务
this.lists = this.lists.filter((obj)=>{
return obj.isChecked!=true;
})
}
}
})
</script>
</body>
</html>