02 . Vue入门基础之条件渲染,列表渲染,事件处理器,表单控件绑定
vue基础
前端渲染
将数据填充到HTML标签中
插值表达式
/*
作用:会将绑定的数据实时的显示出来:
通过任何方式修改所绑定的数据,所显示的数据都会被实时替换
{{js表达式、三目运算符、方法调用等}}
不能写 var a = 10; 分支语句 循环语句
*/
Example1
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Examples</title>
<meta name="description" content="">
<meta name="keywords" content="">
<link href="" rel="stylesheet">
<script type="text/javascript" src="lib/vue.js"></script>
</head>
<body>
<div id="app">
<!-- 插值表达式 -->
{{ count }}
<!-- 三目运算符 -->
<p>{{ age > 18 ?'成年' :'未成年' }}</p>
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
count: 100,
age: 15
},
methods: {
}
})
</script>
</body>
</html>
指令
指令 (Directives) 是带有
v-
前缀的特殊特性。指令特性的值预期是单个 JavaScript 表达式(
v-for
是例外情况,稍后我们再讨论)。指令的职责是,当表达式的值改变时,将其产生的连带影响,响应式地作用于 DOM。
指令的本质就是自定义属性
/*
1. Vue框架提供的语法
2. 扩展了HTML的能力
3. 减少DOM操作
*/
Example1
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Examples</title>
<meta name="description" content="">
<meta name="keywords" content="">
<link href="" rel="stylesheet">
<script type="text/javascript" src="lib/vue.js"></script>
</head>
<body>
<!--
指令
作用:
增强了html标签功能
所有指令都是v-开头
所有指令代码位置,标签的开始标签位置
所有指令都是取代之前的DOM操作
-->
<div id="app">
<!-- 插值表达式 -->
{{ count }}
<button v-on:click="fn1()">点我</button>
<!-- 三目运算符 -->
<p>{{ age > 18 ?'成年' :'未成年' }}</p>
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
count: 100,
age: 15
},
methods: {
fn1(){
console.log(this.count)
}
}
})
</script>
</body>
</html>
v-clock
/*
1. 插值表达式存在的问题: "闪动"
2. 如何解决该问题: 使用v-cloak指令
3. 解决该问题的原理: 先隐藏,替换好值之后再显示最终的值
*/
Example
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Examples</title>
<meta name="description" content="">
<meta name="keywords" content="">
<link href="" rel="stylesheet">
<script type="text/javascript" src="lib/vue.js"></script>
</head>
<body>
<div id="app">
<div v-cloak>{{ msg }}</div>
</div>
<script>
/*
v-clock指令用法
1. 提供样式
[v-cloak]{
display: none;
}
2. 在插值表达式所在的标签中添加v-cloak指令
背后的原理: 先通过样式隐藏内容,然后在内存中进行值的替换,替换好之后再显示最终的结果.
*/
var vm = new Vue({
el: '#app',
data: {
msg: 'hello vue12'
}
});
</script>
</body>
</html>
数据绑定指令V-text,v-html,v-pre
很像innerText和innerHTML
/*
v-text 填充纯文本
相比插值表达式更加简洁
v-html 填充HTML片段
1. 存在安全问题
2. 本网站内部数据可以使用,来自第三方网站数据不可以用
v-pre 填充原始信息
1. 显示原始信息,跳过编译过程
*/
x-html
更新元素的
innerHTML
。注意:内容按普通 HTML 插入 - 不会作为 Vue 模板进行编译。如果试图使用v-html
组合模板,可以重新考虑是否通过使用组件来替代。在网站上动态渲染任意 HTML 是非常危险的,因为容易导致 XSS 攻击。只在可信内容上使用
v-html
,永不用在用户提交的内容上。在单文件组件里,
scoped
的样式不会应用在v-html
内部,因为那部分 HTML 没有被 Vue 的模板编译器处理。如果你希望针对v-html
的内容设置带作用域的 CSS,你可以替换为 CSS Modules 或用一个额外的全局<style>
元素手动设置类似 BEM 的作用域策略。
Example
自定义指令
内置指令不满足要求
Vue.directive('focus' {
inserted: function(el) {
// 获取元素的焦点
el.focus();
}
})
Example
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="app">
<input type="text" v-focus />
</div>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
/*
自定义指令
*/
Vue.directive('focus',{
inserted: function(el){
// el表示指令所绑定的元素
el.focus()
}
})
var vm = new Vue({
el: '#app',
data: {
},
methods: {
}
})
</script>
</body>
</html>
带参数的自定义指令
改变元素背景色
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="app">
<input type="text" v-color='msg'>
</div>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
/*
自定义指令 - 带参数
*/
Vue.directive('color', {
bind: function(el, binding) {
// 根据指令的参数设置背景色
// console.log(binding.value.color)
el.style.backgroundColor = binding.value.color
}
})
var vm = new Vue({
el: '#app',
data: {
msg: {
color: 'blue'
}
},
methods: {
handle: function() {
}
}
})
</script>
</body>
</html>
局部指令
如果想注册局部指令,组件中接受一个directives的选项,位于vue实例参数里面,局部指令只能在本组件使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="app">
<input type="text" v-color='msg'>
<input type="text" v-focus />
</div>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
/*
自定义指令 - 带参数
*/
Vue.directive('color', {
bind: function(el, binding) {
// 根据指令的参数设置背景色
// console.log(binding.value.color)
el.style.backgroundColor = binding.value.color
}
})
var vm = new Vue({
el: '#app',
data: {
msg: {
color: 'blue'
}
},
methods: {
handle: function() {
}
},
directives: {
color: {
bind: function(el,binding){
el.style.backgroundColor = binding.value.color
}
},
focus: {
inserted: function(el){
el.focus()
}
}
}
})
</script>
</body>
</html>
声明式渲染
Vue.js 的核心是一个允许采用简洁的模板语法来声明式地将数据渲染进 DOM 的系统
Example1
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Examples</title>
<meta name="description" content="">
<meta name="keywords" content="">
<link href="" rel="stylesheet">
<script type="text/javascript" src="lib/vue.js"></script>
</head>
<body>
<div id="box">
{{ 10+203 }}
<p>{{ myname }}</p>
</div>
<div>
{{ 10+20 }}
</div>
<script>
var vm = new Vue({
el:"#box", // vue 渲染开始的地方
data:{
myname:"kerwin"
} // 状态
})
</script>
</body>
</html>
我们已经成功创建了第一个 Vue 应用!看起来这跟渲染一个字符串模板非常类似,但是 Vue 在背后做了大量工作。现在数据和 DOM 已经被建立了关联,所有东西都是响应式的。我们要怎么确认呢?打开你的浏览器的 JavaScript 控制台 (就在这个页面打开),并修改
app.message
的值,你将看到上例相应地更新。注意我们不再和 HTML 直接交互了。一个 Vue 应用会将其挂载到一个 DOM 元素上 (对于这个例子是
#app
) 然后对其进行完全控制。那个 HTML 是我们的入口,但其余都会发生在新创建的 Vue 实例内部。
除了文本插值,我们还可以像这样来绑定元素 attribute:
<div id="app-2">
<span v-bind:title="message">
鼠标悬停几秒钟查看此处动态绑定的提示信息!
</span>
</div>
var app2 = new Vue({
el: '#app-2',
data: {
message: '页面加载于 ' + new Date().toLocaleString()
}
})
这里我们遇到了一点新东西。你看到的
v-bind
attribute 被称为指令。指令带有前缀v-
,以表示它们是 Vue 提供的特殊 attribute。可能你已经猜到了,它们会在渲染的 DOM 上应用特殊的响应式行为。在这里,该指令的意思是:“将这个元素节点的title
attribute 和 Vue 实例的message
property 保持一致”。如果你再次打开浏览器的 JavaScript 控制台,输入
app2.message = '新消息'
,就会再一次看到这个绑定了title
attribute 的 HTML 已经进行了更新。
数据响应式
/*
如何理解响应式
1.html5中的响应式(屏幕尺寸的变化导致样式的变化)
2.数据的响应式(数据的变化导致页面内容的变化)
什么是数据绑定
1.数据绑定: 将数据填充到标签中
v-once 只编译一次
显示之后不再具有响应式功能
应用场景:
如果显示的信息后续不需要再修改,可以使用v-once,这样可以提高性能
*/
条件与循环
Example1
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="app">
<div v-if="score>=90">优秀</div>
<div v-else-if="score<90&&score>=80">良好</div>
<div v-else-if="score<80&&score>60">一般</div>
<div v-else>差</div>
<div v-show="flag">测试v-show</div>
<button v-on:click="handle">按钮</button>
</div>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
/*
分支结构
v-show的原理: 控制元素样式是否显示 display: none
*/
var vm = new Vue({
el: '#app',
data: {
score: 9,
flag: false
},
methods: {
handle: function() {
this.flag = !this.flag
}
}
})
</script>
</body>
</html>
Example2
<div id="app-3">
<p v-if="seen">现在你看到我了</p>
</div>
var app3 = new Vue({
el: '#app-3',
data: {
seen: true
}
})
继续在控制台输入
app3.seen = false
,你会发现之前显示的消息消失了。这个例子演示了我们不仅可以把数据绑定到 DOM 文本或 attribute,还可以绑定到 DOM 结构。此外,Vue 也提供一个强大的过渡效果系统,可以在 Vue 插入/更新/移除元素时自动应用过渡效果。
还有其它很多指令,每个都有特殊的功能。例如,
v-for
指令可以绑定数组的数据来渲染一个项目列表:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Examples</title>
<meta name="description" content="">
<meta name="keywords" content="">
<link href="" rel="stylesheet">
<script type="text/javascript" src="lib/vue.js"></script>
</head>
<body>
<div id=app-4>
<ol>
<li v-for="todo in todos">
{{ todo.text }}
</li>
</ol>
</div>
<script>
var app4 = new Vue({
el: '#app-4',
data: {
todos: [{
text: '学习js'
},
{
text: '学习vue'
},
{
text: '整个厉害项目'
}
]
}
})
</script>
</body>
</html>
循环结构
/*
v-for 遍历数组
<li v-for='item in list'>{{ item }}</li>
<li v-for='{item,index} in list'>{{ item }}+ '---' + {{ index }}</li>
v-for 遍历对象
<div v-for='(value,key,index) in '>
key的作用: 帮助vue区分不同的元素,从而提高性能
<li :key='item.id' v-for='{ item,index } in list'>{{item}}+'----'{{index}}</li>
*/
Example1
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="app">
<div>水果列表</div>
<ul>
<li v-for='item in fruits'>{{ item }}</li>
<li v-for='(item,index) in fruits'>{{ item + '---'+index }}</li>
<li :key='item.id' v-for="(item,index) in myFruits">
<span>{{ item.ename }}</span>
---
<span>{{ item.cname }}</span>
</li>
</ul>
</div>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
fruits: ['apple', 'oragen', 'banana'],
myFruits: [{
id: 1,
ename: 'apple',
cname: '苹果'
}, {
id: 2,
ename: 'orange',
cname: '橘子'
}, {
id: 3,
ename: 'banner',
cname: '香蕉'
}],
},
methods: {
}
})
</script>
</body>
</html>
v-if和v-for结合使用
<div v-if>
</div>
Example2
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="app">
<div v-if='v==13' v-for='(v,k,i) in obj'>{{v + '---' + k + '---' + i}}</div>
</div>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
// 使用原生js遍历对象
var obj = {
uname: 'lisi',
age: 12,
gender: 'male'
}
for (var key in obj) {
console.log(key, obj[key])
}
/*
循环结构
*/
var vm = new Vue({
el: '#app',
data: {
obj: {
uname: 'zhangsan',
age: 13,
gender: 'female'
}
}
});
</script>
</body>
</html>
处理用户输入
为了让用户和你的应用进行交互,我们可以用
v-on
指令添加一个事件监听器,通过它调用在 Vue 实例中定义的方法:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Examples</title>
<meta name="description" content="">
<meta name="keywords" content="">
<link href="" rel="stylesheet">
<script type="text/javascript" src="lib/vue.js"></script>
</head>
<body>
<div id="app-5">
<p>{{ message}}</p>
<button v-on:click="reverseMessage">反转消息</button>
</div>
<script>
var app5 = new Vue({
el: '#app-5',
data: {
message: 'Hello Vue.js!'
},
methods: {
reverseMessage: function() {
this.message = this.message.split('').reverse().join('')
}
}
})
</script>
</body>
</html>
双向数据绑定
/*
什么是双向数据绑定?
1.当数据发生变化的时候,视图也就发生变化
2.当视图发生变化的是后,数据也会跟着同步变化
双向绑定的使用场景?
v-model实现的双向绑定
v-model是一个指令,限制在<input>,<select>,<textarea>,components(组件中使用)
*/
v-model的本质
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="app">
<div>{{ msg }}</div>
<input type="text" v-bind:value="msg" v-on:input="handle" />
<input type="text" v-bind:value="msg" v-on:input="msg=$event.target.value" />
<!-- 通过v-bind绑定value值,v-on绑定input事件,监听输入域有变化就将变化的值传给msg ->
<input type="text" v-model="msg" />
</div>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
/*
v-model的本质
*/
var vm = new Vue({
el: '#app',
data: {
msg: 'hello'
},
methods: {
// 使用输入域中的最新的数据覆盖原来的数据
handle: function(event) {
this.msg = event.target.value
}
}
})
</script>
</body>
</html>
模板语法
vue插值(v-if和v-show)
/*
文本{{}}
纯HTML
v-html, 防止XSS,csrf (
(1)前端过滤
(2)后台转义(<> < >)
(3)给cookie加上属性http
)
指令
v-html
v-show
v-if与v-show区别
v-if控制元素是否渲染到页面
v-show控制元素是否显示(已经渲染到了页面)
*/
Example1
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Examples</title>
<meta name="description" content="">
<meta name="keywords" content="">
<link href="" rel="stylesheet">
<script type="text/javascript" src="lib/vue.js"></script>
</head>
<body>
<div id="box">
{{ 10+20 }}
{{ 10>20? 'aaa':'bbb' }}
{{ myname}}
<!-- 指令 -->
{{ myhtml }}
<div v-html="myhtml"></div>
</div>
<script type="text/javascript">
// console 中可以 vm.isShow=false隐藏
new Vue({
el: "#box",
data: {
myname: "youmen",
myhtml: "<b>11111</b>"
}
})
</script>
</body>
</html>
vue如何动态处理属性
/*
v-bind指令用法
<a v-bind:href='url'>跳转</a>
缩写形式
<a :href='url'>跳转</a>
*/
Example1
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="app">
<a :href="url">百度</a>
<button v-on:click="handle">切换</button>
</div>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
url: 'http://www.baidu.com'
},
methods: {
handle: function() {
// 修改url地址
this.url = 'http://www.zcj.net.cn'
}
}
})
</script>
</body>
</html>
条件渲染
Vue-class绑定
/*
对象语法
<div v-bind:class="{ active: isActive }"></div>
数组语法
<div v-bind:class="[activeClass,errorClass]"></div>
*/
Example1
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style type="text/css">
.active {
border: 1px solid red;
width: 100px;
height: 100px;
}
.error {
background-color: orange;
}
</style>
</head>
<body>
<div id="app">
<div v-bind:class="{active: isActive,error: isError}">123</div>
<button v-on:click="handle">切换</button>
</div>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
isActive: true,
isError: true
},
methods: {
handle: function() {
// 控制isActive的值在true和false进行切换
this.isActive = !this.isActive;
this.isError = !this.isError;
}
}
})
</script>
</body>
</html>
Example2
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style type="text/css">
.active {
border: 1px solid red;
width: 100px;
height: 100px;
}
.error {
background-color: orange;
}
</style>
</head>
<body>
<div id="app">
<div v-bind:class="[activeClass,errorClass]">测试样式</div>
<button v-on:click="handle">切换</button>
</div>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
activeClass: 'active',
errorClass: 'error'
},
methods: {
handle: function() {
this.activeClass = '';
this.errorClass = '';
}
}
})
</script>
</body>
</html>
Vue-style绑定
Example2
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Examples</title>
<meta name="description" content="">
<meta name="keywords" content="">
<link href="" rel="stylesheet">
<script type="text/javascript" src="lib/vue.js"></script>
<style>
.red {
background-color: red;
}
.yellow{
background-color: yellow;
}
.aaa{
}
.bbb{
}
</style>
</head>
<body>
<div id="box">
<button @click="handleClick()">click</button>
<div :class="isActive?'red':'yellow'">我是动态绑定class-三目写法</div>
<div :class="classobj">我是动态绑定class-对象写法</div>
<div :class="classarr">我是动态绑定class-数组写法</div>
<div :style="'background:'+(isActive?'red':'yellow')">我是动态绑定style-三目写法</div>
<div :style="styleobj">我是动态绑定style-对象写法</div>
<div :style="stylearr">我是动态绑定style-数组写法</div>
</div>
<script type="text/javascript">
var vm = new Vue({
el: "#box",
data: {
isActive: true,
classobj: {
a: true,
b: true
// a b, class名字
},
classarr: ["a", "b"],
styleobj: {
backgroundColor: "red"
},
stylearr: []
},
methods: {
handleClick() {
this.isActive = !this.isActive
}
}
})
</script>
</body>
</html>
样式绑定相关语法细节
/*
1. 对象绑定和数组绑定可以结合使用
2. class绑定的值可以简化操作
3. 默认的class如何处理? 默认的class可以保留
*/
Example1
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style type="text/css">
.active {
border: 1px solid red;
width: 100px;
height: 100px;
}
.error {
background-color: orange;
}
.base {
font-size: 28px;
}
</style>
</head>
<body>
<div id="app">
<div v-bind:class="[activeClass,errorClass,{test: isTest}]">测试样式</div>
<div v-bind:class="arrClasses"></div>
<div v-bind:class="objClasses"></div>
<div class="base" v-bind:class="objClasses"></div>
<button v-on:click="handle">切换</button>
</div>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
activeClass: 'active',
errorClass: 'error',
isTest: true,
arrClasses: ['active','error'],
objClasses: {
active: true,
error: true
}
},
methods: {
handle: function() {
// this.isTest = false
this.objClasses.error = false
}
}
})
</script>
</body>
</html>
条件渲染
Example1
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Examples</title>
<meta name="description" content="">
<meta name="keywords" content="">
<link href="" rel="stylesheet">
<script type="text/javascript" src="lib/vue.js"></script>
</head>
<body>
<div id="box">
<button @click="handleClick()">click</button>
<div v-if="isCreated">动态创建和删除-1</div>
<div v-else>动态创建和删除-2</div>
<ul v-if="datalist.length">
<li v-for="data in datalist">
{{ data }}
</li>
</ul>
<div v-else>
购物车空空如也
</div>
<div v-if="which==1">
111
</div>
<div v-else-if="which==2">
2222
</div>
<div v-else>
3333
</div>
</div>
<script type="text/javascript">
var vm = new Vue({
el:"#box",
data:{
isCreated:false,
datalist:[],
which:1,
},
methods: {
handleClick(){
this.isCreated = !this.isCreated
this.datalist = ["111","222","333"]
}
}
})
</script>
</body>
</html>
列表渲染
我们可以用
v-for
指令基于一个数组来渲染一个列表。v-for
指令需要使用item in items
形式的特殊语法,其中items
是源数据数组,而item
则是被迭代的数组元素的别名。
v-for
还支持一个可选的第二个参数,即当前项的索引。也可以用of代替in作为分隔符,因为她更接近javascript迭代器的语法
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Examples</title>
<meta name="description" content="">
<meta name="keywords" content="">
<link href="" rel="stylesheet">
<script type="text/javascript" src="lib/vue.js"></script>
<style>
.active{
background-color: red;
}
</style>
</head>
<body>
<div id="box">
<ul>
<li v-for="(data,index) in datalist">
{{ data }}--{{ index }}
</li>
</ul>
<ul>
<li v-for="(data,key) of obj">
{{ data }}--{{key}}
</li>
</ul>
</div>
<script type="text/javascript">
var vm = new Vue({
el: "#box",
data:{
datalist:["111","222","333"],
obj:{
name:"youmen",
age:100,
location:"youmen"
}
}
})
</script>
</body>
</html>
列表key值设置和列表数组检测
/*
1. v-for(特殊v-for="n in 10")
a.in
b.of
2. key
*跟踪每个节点的身份,从而复用和重新排序现有元素
*理想的key值是每项都有且唯一的id,data.id
3. 数组更新检测
a. 使用以下方法操作数组,可以检测变动
push() pop() shift() unshift() splice() sort() reverse()
b. filter(),concat()和slice(),map(),新数组替换旧数组,并不会导致原数组受到影响并更新
vm.datalist.concat(["666","777"])
c. 不能检测以下变动的数组
vm.items[indexOfitem] = newValue
"解决"
1. Vue.set(example1.items,index()fltem,newValue)
2. splice
vm.datalist.splice(0,1,"youmen")
*/
vue列表过滤应用
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Examples</title>
<meta name="description" content="">
<meta name="keywords" content="">
<link href="" rel="stylesheet">
<script type="text/javascript" src="lib/vue.js"></script>
</head>
<body>
<div id="box">
<input type="text" @input="handleInput()" v-model="mytext" />
<ul>
<li v-for="data in datalist">
{{ data }}
</li>
</ul>
</div>
<script type="text/javascript">
var vm = new Vue({
el: "#box",
data: {
mytext: "",
datalist: ["aaa", "bbb", "ccc", "ddd", "eee", ],
list: ["aaa", "bbb", "ccc", "ddd", "eee", ]
},
methods: {
handleInput() {
// console.log(this.mytext)
// console.log("只要value改变,就会触发")
// 利用输入框的字符,过滤包含字符的元素
// filter 过滤
var newlist = this.list.filter(item => item.indexOf(this.mytext) > -1)
this.datalist = newlist;
// 计算属性
}
}
})
var arr = [1, 2, 3, 4, 5]
var newlist = arr.filter(item => item >= 3)
console.log(newlist)
console.log(newlist)
</script>
</body>
</html>
事件处理
vue如何处理事件
/*
v-on指令用法
<input> type= 'button' v-on:click='num++'/>
v-on简写形式
<input type='button'@click='num++'/>
*/
事件传参
Example1
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="app">
<div>{{ num }}</div>
<button v-on:click='num++'>点击1</button>
<button @click='num++'>点击2</button>
<!-- 参数传递
1. 如果事件直接绑定函数名称,那么默认会传递对象作为事件函数第一个参数
2. 如果事件绑定函数调用,那么事件对象必须作为最后一个参数
-->
<button @click='handle(1,2,$event)'>点击2</button>
</div>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
/*
事件绑定
*/
var vm = new Vue({
el: '#app',
data: {
num: 0
},
methods: {
handle: function(p1, p2, event) {
console.log(p1, p2, event.target.innerHTML)
this.num++;
}
}
})
</script>
</body>
</html>
事件处理器
可以用
v-on 指令监听 DOM 事件,并在触发时运行一些 JavaScript 代码
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Examples</title>
<meta name="description" content="">
<meta name="keywords" content="">
<link href="" rel="stylesheet">
<script type="text/javascript" src="lib/vue.js"></script>
</head>
<body>
<div id="box">
<button @click="handleClick">click1</button>
<button @click="handleClick()">click2</button>
<button @click="isShow=!isShow">click3</button>
<div v-show="isShow">111</div>
</div>
<script type="text/javascript">
new Vue({
el: "#box",
data:{
isShow:false
},
methods:{
handleClick(){
this.isShow=!this.isShow
}
}
})
</script>
</body>
</html>
事件修饰符
/*
1. 监听事件-直接出发代码
2. 方法事件处理器-写函数名 handleClick
3. 内联处理器方法-执行函数表达式 handleClick($event) $event 事件对象
.stop 阻止冒泡
<a v-on:click.stop="handle">跳转</a>
.prevent阻止默认行为
<a v-on:click.prevent="handle>跳转</a>
*/
修饰符
/*
.stop - 调用 event.stopPropagation()。
.prevent - 调用 event.preventDefault()。
.capture - 添加事件侦听器时使用 capture 模式。
.self - 只当事件是从侦听器绑定的元素本身触发时才触发回调。
.{keyCode | keyAlias} - 只当事件是从特定键触发时才触发回调。
.native - 监听组件根元素的原生事件。
.once - 只触发一次回调。
.left - (2.2.0) 只当点击鼠标左键时触发。
.right - (2.2.0) 只当点击鼠标右键时触发。
.middle - (2.2.0) 只当点击鼠标中键时触发。
.passive - (2.3.0) 以 { passive: true } 模式添加侦听器
*/
Example1
阻止冒泡,默认行为
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Examples</title>
<meta name="description" content="">
<meta name="keywords" content="">
<link href="" rel="stylesheet">
<script type="text/javascript" src="lib/vue.js"></script>
</head>
<body>
<div id="box">
<button @click="handleClick">click1</button>
<button @click="handleClick($event)">click2</button>
<button @click="isShow=!isShow">click3</button>
<div v-show="isShow">111</div>
<ul @click.self="handleClick()">
<li @click.stop="handleClick($event)">111</li>
<li @click.stop="handleClick()">222</li>
<li @click.once="handleClick()">333</li>
</ul>
<a href="http://www.baidu.com" @click.prevent="handleChangePage()">changepage</a>
</div>
<script type="text/javascript">
new Vue({
el: "#box",
data: {
isShow: false
},
methods: {
handleClick(ev) {
console.log(ev.target); // ev就是事件对象
this.isShow = !this.isShow
},
handleClick(ev) {
// ev.stopPropagation();
console.log("li click")
},
handleClick() {
console.log("ul click")
},
handleChangePage() {
console.log("handleChangePage")
}
}
})
</script>
</body>
</html>
Example2
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="app">
<div>{{ num }}</div>
<div v-on:click="handle0">
<button @click.stop="handle1">点击1</button>
</div>
<div>
<a href="http://www.baidu.com" @click.prevent="handle2">百度</a>
</div>
</div>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
num: 0
},
methods: {
handle0: function() {
this.num++;
},
handle1: function(event) {
// 阻止冒泡
// event.stopPropagation()
this.num++;
},
handle2: function(event) {
// 阻止默认行为
// event.preventDefault();
}
}
})
</script>
</body>
</html>
按键修饰符
/*
.enter回车键
<input v-on:keyup.enter='submit'>
.delete删除键
<input v-on:keyup.delete='handle'>
*/
Example1
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Examples</title>
<meta name="description" content="">
<meta name="keywords" content="">
<link href="" rel="stylesheet">
<script type="text/javascript" src="lib/vue.js"></script>
</head>
<body>
<div id="box">
<input type="text" @keyup.enter="handleKeyup($event)" />
</div>
<script type="text/javascript">
new Vue({
el: "#box",
methods: {
handleKeyup(ev) {
console.log("执行todolist 添加成功")
// if(ev.keyCode==13){
// console.log("执行todolist添加成功")
// 可以自定义按键修饰符,找到每个按键对应的数字即可
// }
}
}
})
</script>
</body>
</html>
Example2
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="app">
<form action="">
<div>
用户名:
<input type="text" v-on:keyup.delete='clearContent' v-model="uname" />
</div>
<div>
密码:
<input type="text" v-model="pwd" />
</div>
<div>
<input type="button" v-on:click="handleSubmit" value="提交" />
</div>
</form>
</div>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
uname: '',
pwd: ''
},
methods: {
handleSubmit: function() {
console.log(this.uname, this.pwd)
},
clearContent: function() {
this.uname = ''
}
}
})
</script>
</body>
</html>
案例
计算器
/*
1. 通过v-model指令实现数值a和数值b的绑定
2. 给计算按钮绑定事件,实现计算逻辑
3. 将计算结果绑定到对应位置
*/
Example1
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="app">
<h1>计算器</h1>
<div>
<span>数值A:</span>
<span>
<input type="text" v-model="a" />
</span>
</div>
<div>
<span>数值B:</span>
<span>
<input type="text" v-model="b" />
</span>
</div>
<div>
<button v-on:click="handle">计算</button>
</div>
<div>
<span>计算结果</span>
<span>{{ result }}</span>
</div>
</div>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
a: '',
b: '',
result: ''
},
methods: {
handle: function() {
// 实现计算逻辑
this.result = parseInt(this.a) + parseInt(this.b)
}
}
})
</script>
</body>
</html>
Tab选项卡
/*
1. 实现静态UI效果
用传统方式实现标签结构和样式
2. 基于数据重构UI效果
将静态的结构和样式重构为基于Vue模板语法的样式
处理事件绑定和js控制逻辑
*/
Example
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style type="text/css">
.tab ul {
overflow: hidden;
padding: 0;
margin: 0;
}
.tab ul li {
box-sizing: border-box;
padding: 0;
float: left;
width: 100px;
height: 45px;
line-height: 45px;
list-style: none;
text-align: center;
border-top: 1px solid blue;
border-right: 1px solid blue;
cursor: pointer;
}
.tab ul li:first-child {
border-left: 1px solid blue;
}
.tab ul li.active {
background-color: orange;
}
.tab div {
width: 500px;
height: 300px;
display: none;
text-align: center;
font-size: 30px;
line-height: 300px;
border: 1px solid blue;
border-top: 0px;
}
.tab div.current {
display: block;
}
</style>
</head>
<body>
<div id="app">
<div class="tab">
<ul>
<li v-on:click="change(index)" :class='currentIndex==index?"active":""' :key='item.id' v-for="(item,index) in list">{{ item.title }}</li>
</ul>
<div :class='currentIndex==index?"current":""' :key='item.id' v-for="(item,index) in list">
<img :src="item.path" />
</div>
</div>
</div>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
currentIndex: 0, // 选项卡当前的索引
list: [{
id: 1,
title: 'apple',
path: 'img/apple.png'
}, {
id: 2,
title: 'orange',
path: 'img/orange.png'
}, {
id: 3,
title: 'lemon',
path: 'img/lemon.png'
},
]
},
methods: {
change: function(index) {
// 在这里实现选项卡切换操作,本质就是操作类名
// 如何操作类名: 通过currentIndex
this.currentIndex = index;
}
}
})
</script>
</body>
</html>
表单控件绑定
表单操作
/*
基于vue的表单操作
1. input 单行文本
2. textarea 多行文本
3. select 下拉多选
4. radio 单选框
5. checkbox 多选框
*/
基础用法-文本
你可以用
v-model
指令在表单<input>
、<textarea>
及<select>
元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素。尽管有些神奇,但v-model
本质上不过是语法糖。它负责监听用户的输入事件以更新数据,并对一些极端场景进行一些特殊处理。
v-model
会忽略所有表单元素的value
、checked
、selected
attribute 的初始值而总是将 Vue 实例的数据作为数据来源。你应该通过 JavaScript 在组件的data
选项中声明初始值。
v-model
在内部为不同的输入元素使用不同的 property 并抛出不同的事件:
/*
text 和 textarea 元素使用 value property 和 input 事件;
checkbox 和 radio 使用 checked property 和 change 事件;
select 字段将 value 作为 prop 并将 change 作为事件。
*/
对于需要使用输入法 (如中文、日文、韩文等) 的语言,你会发现
v-model
不会在输入法组合文字过程中得到更新。如果你也想处理这个过程,请使用input
事件。
文本 Example1
<input v-model="message" placeholder="edit me">
<p>Message is: {{ message }}</p>
多行文本
<span>Multiline message is:</span>
<p style="white-space: pre-line;">{{ message }}</p>
<br>
<textarea v-model="message" placeholder="add multiple lines"></textarea>
在文本区域插值 (
) 并不会生效,应用
v-model 来代替。
基础用法-复选框
单个复选框,绑定到布尔值:
<input type="checkbox" id="checkbox" v-model="checked">
<label for="checkbox">{{ checked }}</label>
案例
Example1
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Examples</title>
<meta name="description" content="">
<meta name="keywords" content="">
<link href="" rel="stylesheet">
<script type="text/javascript" src="lib/vue.js"></script>
</head>
<body>
<div id="box">
<input type="text" v-model="mytext" />
{{mytext}}
<textarea v-model="mytext"></textarea>
<input type="checkbox" v-model="isChecked" />记录用户名
<p>你喜欢的运动?
<input type="checkbox" v-model="checkgroup" value="游泳" />游泳
<input type="checkbox" v-model="checkgroup" value="滑冰" />滑冰
<input type="checkbox" v-model="checkgroup" value="长跑" />长跑
</p>
{{ checkgroup }}
<p>你喜欢的开发语言?
<input type="radio" v-model="picked" value="Python" />Python
<input type="radio" v-model="picked" value="Go" />Go
<input type="radio" v-model="picked" value="js" />js
</p>
{{ picked }}
</div>
<script type="text/javascript">
var vm = new Vue({
el: "#box",
data: {
mytext: "",
isChecked: true,
checkgroup: [],
picked: "js",
}
})
</script>
</body>
</html>
Example2-购物车
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Examples</title>
<meta name="description" content="">
<meta name="keywords" content="">
<link href="" rel="stylesheet">
<script type="text/javascript" src="lib/vue.js"></script>
</head>
<body>
<div id="box">
<input type="checkbox" @change="handleChange" v-model="isAllChecked" />
<ul>
<li v-for="data in datalist">
<!-- 此处的:value是动态绑定,data后面.是什么就会去取列表里面对应值 -->
<input type="checkbox" v-model="checkgroup" :value="data" @change="handleLiChange" />
{{data}}
<button @click="handleDelClick(data)">del</button>
{{ data.nuber }}
<button @click="data.number++">add</button>
</li>
</ul>
{{ checkgroup }}
<!-- 函数表达式 -->
<p>总金额计算: {{ getSum() }}</p>
</div>
<script type="text/javascript">
var vm = new Vue({
el: "#box",
data: {
checkgroup: [],
isAllChecked: false,
datalist: [{
name: "商品1",
price: 10,
number: 1,
id: "1",
},
{
name: "商品2",
price: 20,
number: 2,
id: "2",
},
{
name: "商品3",
price: 30,
number: 3,
id: "3",
}
]
},
methods: {
getSum() {
// 函数计算中的状态改变后,函数会自动执行一次
var sum = 0;
for (var i in this.checkgroup) {
sum += this.checkgroup[i].number * this.checkgroup[i].price
}
return sum
},
handleChange() {
console.log("改变了", this.isAllChecked)
if (this.isAllChecked) {
this.checkgroup = this.datalist
} else {
this.checkgroup = []
}
},
handleLiChange() {
console.log("handleLiChange-判断是不是都勾选")
if (this.checkgroup.length === this.datalist.length) {
this.isAllChecked = true
} else {
this.isAllChecked = false
}
},
handleDelClick(data) {
// console.log(data)
var number = data.number--;
if (number == 1) {
data.number = 1;
}
}
}
})
</script>
</body>
</html>
Example3
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style type="text/css">
form div {
height: 40px;
line-height: 40px;
}
form div:nth-child(4) {
height: auto;
}
form div span:first-child {
display: inline-block;
width: 100px;
}
</style>
</head>
<body>
<div id="app">
<form action="http://www.zcj.net.cn">
<div>
<span>姓名:</span>
<span>
<input type="text" v-model="uname" />
</span>
</div>
<div>
<span>性别:</span>
<span>
<input type="radio" id="male" value="1" v-model="gender" />
<label for="male">男</label>
<input type="radio" id="female" value="2" v-model="gender" />
<label for="female">女</label>
</span>
</div>
<div>
<span>爱好</span>
<input type="checkbox" id=ball value="1" v-model="hobby" />
<label for="ball">篮球</label>
<input type="checkbox" id=sing value="2" v-model="hobby" />
<label for="sing">唱歌</label>
<input type="checkbox" id="code" value="3" v-model="hobby" />
<label for="code">写代码</label>
</div>
<div>
<span>职业</span>
<!-- multiple加上就是支持多选, 但注意在样式加入form div:nth-child(4) -->
<select v-model="occupation" multiple="true">
<option value="0">请选择职业</option>
<option value="1">教师</option>
<option value="2">软件工程师</option>
<option value="3">律师</option>
</select>
</div>
<div>
<span>个人简介:</span>
<textarea v-model="desc"></textarea>
</div>
<div>
<input type="submit" value="提交" @click.prevent="handle" />
</div>
</form>
</div>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
uname: 'list',
gender: 2,
hobby: ["2", "3"],
occupation: ["1"],
desc: "nihao"
},
methods: {
handle: function() {
// console.log(this.uname)
// console.log(this.gender)
// console.log(this.hobby)
console.log(this.occupation)
}
}
})
</script>
</body>
</html>
表单修饰符
表单域修饰符
/*
number: 转化为数值
trim: 去掉开始和结尾的空格
lazy: 将input事件转化为change事件
<input v-model.number="age" type="number">
*/
Example1
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Examples</title>
<meta name="description" content="">
<meta name="keywords" content="">
<link href="" rel="stylesheet">
<script type="text/javascript" src="lib/vue.js"></script>
</head>
<body>
<div id="box">
<!-- v-model.lazy 不会让浏览器实时更新,只有失去焦点才会更新 -->
<input type="text" v-model.lazy="mytext" />
{{ mytext }}
<!-- 限制用户输入出去数字外的其他字符 -->
<input type="number" v-model.number="mynumber" />
{{ mynumber }}
<!-- 去除首,尾空格 -->
<input type="text" v-model.trim="myusername"/>
| {{ myusername }} |
</div>
<script>
new Vue({
el: "#box",
data: {
mytext: "",
mynumber: 0,
myusername: ""
}
})
</script>
</body>
</html>
Example2
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="app">
<input type="text" v-model.number="age" />number
<input type="text" v-model.trim="info" />info
<input type="text" v-model.lazy="msg" />change
<div>{{ msg}}</div>
<button @click="handle">点击</button>
</div>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
/*
表单域修饰符
*/
var vm = new Vue({
el: '#app',
data: {
age: "",
info: '',
msg: ''
},
methods: {
handle: function() {
console.log(this.age + 13)
console.log(this.info.length)
}
}
})
</script>
</body>
</html>