Vue——基本理解
Vue的方便之处,在于强大的视图用法,在html标签上就可以标记标签和数据的对应关系
比如:
(1)根据vm中data的数据决定是否渲染
(2)根据vm中data的数据循环渲染
(3)指定标签的事件绑定什么样的函调函数
而没有vue的时候,我们用jq则需要在脚本里手动去建立标签和函数的关系以及标签和数据的关系,当数据发生变化的时候我们要手动用dom语法将数据刷新一次这样显然是冗余的代码,vue则是利用简洁的视图语法实现声明式函数,在标签上用视图语法就能实现关系建立,双向绑定,自动刷新;
Vue——牛刀小试
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://cdn.bootcss.com/vue/2.5.2/vue.min.js"></script>
</head>
<body>
<!-- 标签视图 -->
<div id="app">
{{firstName}}————————{{lastName}}
</div>
<script>
const vm = new Vue({//vm容器:数据、逻辑(函数)
/*
@EL选择器
用id选择器————选中哪个标签作为自己的vue视图,之外则没有任何影响
*/
el: '#app',
/*
@数据
*/
data: {
firstName: 'Hellow',
lastName: 'GodSchool(骆志峰)',
}
})
</script>
</body>
</html>
Vue——基本结构
var vm=new Vue({
el:"",
template:"",
【资源层】
data(){return {name:""}},《数据层》
methods: {},《方法层》
props: {},《公共层》
components:{},《子系层》
【工具层】
watch: {},《监听器》
computed: {},《计算器》
filters: {},《过滤器》
directives: {}《指令注册器》
【生命周期】
//初始化阶段
beforeCreate(){},
created(){},
beforeMount(){},
//加载完成后调用
mounted(){},
//更新阶段
beforeUpdate(){},
updated(){},
//死亡阶段
beforeDestroy(){},
beforeDestroy(){}
【工具】
,filters:{【局部过滤器】
dateFormat:function(data,pattern){
return ……
}
},watch:{【局部监听器】
firstName:function(value) {
this.fullName = value + ' ' + this.lastName;
}
},computed:{【局部计算器】
fullName: {
return this.firstName + ' ' + this.lastName;
}
}
})
Vue——视图语法
布尔
根据vm容器的某个值决定是否渲染
需求
男就显示骆志峰,是女就显示麦宝莹
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://cdn.bootcss.com/vue/2.5.2/vue.min.js"></script>
</head>
<body>
<!-- 标签视图 -->
<div id="app">
<div v-if="gender=='男'">
骆志峰
</div>
<div v-if="gender=='女'">
麦宝莹
</div>
</div>
<script>
const vm = new Vue({//vm容器:数据、逻辑(函数)
/*
@EL选择器
用id选择器————选中哪个标签作为自己的vue视图,之外则没有任何影响
*/
el: '#app',
/*
@数据
*/
data: {
gender: '男'
}
})
</script>
</body>
</html>
延伸(1)——双路分支
<div id="app">
<div v-if="gender=='男'">
骆志峰
</div>
<div v-else>
麦宝盈
</div>
</div>
<script>
const vm = new Vue({//vm容器:数据、逻辑(函数)
/*
@EL选择器
用id选择器————选中哪个标签作为自己的vue视图,之外则没有任何影响
*/
el: '#app',
/*
@数据
*/
data: {
gender: '啥玩意'
}
})
</script>
延伸(2)——多路分支
<!-- 标签视图 -->
<div id="app">
<div v-if="gender=='男'">
骆志峰
</div>
<div v-else-if="gender=='女'" >
麦宝盈
</div>
<div v-else-if="gender=='人妖'" >
金星
</div>
<div v-else-if="gender=='无'" >
雷神
</div>
</div>
<script>
const vm = new Vue({//vm容器:数据、逻辑(函数)
/*
@EL选择器
用id选择器————选中哪个标签作为自己的vue视图,之外则没有任何影响
*/
el: '#app',
/*
@数据
*/
data: {
gender: '无'
}
})
</script>
延伸(3)——其他布尔语法
布尔标签中v-if和v-show在使用上是差不多的,但是v-show只是css将标签做了隐藏显示,如果标签和组件仍然被渲染了存在内存中,而v-if如果是false则整个标签和组件都渲染,v-if更节约性能,如果设计中只是为了不显示,但是必要为了让组件存在提供其他功能,则才使用v-show,当然这种情况比较少,所以大部分情况我们还是用v-if,我们知道即可;
循环
遍历数组
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://cdn.bootcss.com/vue/2.5.2/vue.min.js"></script>
</head>
<body>
<!-- 标签视图 -->
<div id="app">
<ul>
<li v-for="user in users">
{{user.userId}}————————{{user.username}}——————————{{user.password}}</li>
</ul>
</div>
<script>
const vm = new Vue({//vm容器:数据、逻辑(函数)
el: '#app',
data: {
users:[
{
"username":"lzf",
"password":"lzf",
"userId":"1"
},
{
"username":"mby",
"password":"mby",
"userId":"2"
},
{
"username":"zzj",
"password":"zzj",
"userId":"3"
}
]
}
})
</script>
</body>
</html>
遍历数组(增强)
可以用()拼出一个index,获得了数组的下标也用于视图渲染
:key是为了让不同行数据刷新指定一个唯一key用于底层diff算法实现最新刷新,而不需要刷新整个数组,有时候我们的需求是指定id只刷新对应id的dom,但有时候比如分页中列表的下标都一样的,我们分页了不可能不刷新整个数组,那就得用每行数据的id作为key,而不是index
<!-- 标签视图 -->
<div id="app">
<ul>
<li v-for="(user,index) in users" :key="user.userId">
{{index}}——{{user.userId}}———{{user.username}}————{{user.password}}</li>
</ul>
</div>
<script>
const vm = new Vue({//vm容器:数据、逻辑(函数)
el: '#app',
data: {
users:[
{
"username":"lzf",
"password":"lzf",
"userId":"1"
},
{
"username":"mby",
"password":"mby",
"userId":"2"
},
{
"username":"zzj",
"password":"zzj",
"userId":"3"
}
]
}
})
</script>
遍历对象
遍历对象的需求一般比较少,都是给一个js对象给你,然后要求你遍历他所有的键,以及对应的value
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://cdn.bootcss.com/vue/2.5.2/vue.min.js"></script>
</head>
<body>
<!-- 标签视图 -->
<div id="app">
<ul>
<li v-for="(value, key,index) in user">
key的值:{{value}}
key的数组下标:{{index}}
key的key:{{key}}
</li>
</ul>
</div>
<script>
const vm = new Vue({//vm容器:数据、逻辑(函数)
el: '#app',
data: {
user:{
id:"1",
username:"lzf",
password:"lzf",
}
}
})
</script>
</body>
</html>
value, key,index是顺序参数
第一个value:key的值
第二个key:key的key
第三个index:key的数组下标
事件
牛刀小试
@事件=function名
这个function必须vm容器的methods属性内
<!-- 标签视图 -->
<div id="app">
<button @click="report">点击汇报vue里面的数据</button>
</div>
<script>
const vm = new Vue({//vm容器:数据、逻辑(函数)
el: '#app',
methods: {
report() {
alert(this.message)
}
},
data: {
message: "你好,我是vue里面的数据,哈哈哈"
}
})
</script>
列表练习(1)———遍历查看每个列表内的数据
<!-- 标签视图 -->
<div id="app">
<ul>
<li v-for="user in users">
{{user.userId}}————{{user.username}}—————{{user.password}}————<button @click="infoUser(user)"></button>
</li>
</ul>
</div>
<script>
const vm = new Vue({//vm容器:数据、逻辑(函数)
el: '#app',
methods:{
infoUser(row){
alert(JSON.stringify(row))
}
},
data: {
users:[
{
"username":"lzf",
"password":"lzf",
"userId":"1"
},
{
"username":"mby",
"password":"mby",
"userId":"2"
},
{
"username":"zzj",
"password":"zzj",
"userId":"3"
}
]
}
})
</script>
列表练习(2)———点就增加列表内的数据
<!-- 标签视图 -->
<div id="app">
<button @click="addUser">新增</button>
<ul>
<li v-for="user in users">
{{user.userId}}————{{user.username}}—————{{user.password}}
</li>
</ul>
</div>
<script>
const vm = new Vue({//vm容器:数据、逻辑(函数)
el: '#app',
methods: {
addUser(row) {
this.users.push({
"username": "新成员",
"password": "新成员",
"userId": "3"
})
}
},
data: {
users: [
{
"username": "lzf",
"password": "lzf",
"userId": "1"
},
{
"username": "mby",
"password": "mby",
"userId": "2"
},
{
"username": "zzj",
"password": "zzj",
"userId": "3"
}
]
}
})
列表练习(3)———点就删除每个列表内的数据
事件内容的更多修饰语法,详见后续的事件章节,入门不需要掌握,因为大部分是根据需求才需要去了解的,入门只需要掌握利用vue的核心设计思想
来完成组件设计
<!-- 标签视图 -->
<div id="app">
<ul>
<li v-for="user in users">
{{user.userId}}————{{user.username}}—————{{user.password}}————<button @click="deletUser(user)">删除</button>
</li>
</ul>
</div>
<script>
Array.prototype.remove = function (val) {
var index = this.indexOf(val);
if (index > -1) {
this.splice(index, 1);
}
};
const vm = new Vue({//vm容器:数据、逻辑(函数)
el: '#app',
methods: {
deletUser(row) {
this.users.remove(row)
}
},
data: {
users: [
{
"username": "lzf",
"password": "lzf",
"userId": "1"
},
{
"username": "mby",
"password": "mby",
"userId": "2"
},
{
"username": "zzj",
"password": "zzj",
"userId": "3"
}
]
}
})
</script>
列表练习(4)———点就增加修改列表内的数据
<!-- 标签视图 -->
<div id="app">
<ul>
<li v-for="user in users">
{{user.userId}}————{{user.username}}—————{{user.password}}————<button @click="editUser(user)">修改</button>
</li>
</ul>
</div>
<script>
const vm = new Vue({//vm容器:数据、逻辑(函数)
el: '#app',
methods: {
editUser(row) {
row.username="被我改啦,啊啊哈哈哈"
}
},
data: {
users: [
{
"username": "lzf",
"password": "lzf",
"userId": "1"
},
{
"username": "mby",
"password": "mby",
"userId": "2"
},
{
"username": "zzj",
"password": "zzj",
"userId": "3"
}
]
}
})
</script>
Vue——数据绑定(待更新)
单向数据绑定
就是当vm容器内的data发生了变化后,对应的视图dom就要刷新;但是dom内的改变则不会引起(比如事件的value值)data的变化
text绑定
<!-- 标签视图 -->
<div id="app">
<div v-html="string"></div>
<div v-text="string"></div>
<div>{{string}}</div>
</div>
<script>
const vm = new Vue({//vm容器:数据、逻辑(函数)
el: '#app',
data: {
string:"<h1>html标签</h1>",
}
})
</script>
attr绑定(罗列)
<!-- 动态url,如果容器内的url变化,则img标签的图片就会变化 -->
<img :src="url" />
<!-- 动态绑定class,如果容器的classes变化,整个标签的class也会变化-->
<h1 :class="claseeRed">claseeRed</h1>
<h1 :class="claseeGreen">claseeGreen</h1>
<h1 :class="claseeOrange">claseeOrange</h1>
<h1 :class="[claseeRed,claseeBackGroundSet,claseeOrange]">多个class组合</h1>
<!-- 动态style ,如果容器内的style发生变化则整个标签样式也会变化-->
<h1 :style="{color:varcolor,font:varfont}">varcolor</h1>
attr绑定(例子)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://cdn.bootcss.com/vue/2.5.2/vue.min.js"></script>
<style>
.red{
color: red;
}
.green{
color: green;
}
.orange{
color: orange;
}
.backGroundSet{
background-color: black;
}
</style>
</head>
<body>
<!-- 标签视图 -->
<div id="app">
<!-- 动态url,如果容器内的url变化,则img标签的图片就会变化 -->
<img :src="url" />
<!-- 动态绑定class,如果容器的classes变化,整个标签的class也会变化-->
<h1 :class="claseeRed">claseeRed</h1>
<h1 :class="claseeGreen">claseeGreen</h1>
<h1 :class="claseeOrange">claseeOrange</h1>
<h1 :class="[claseeRed,claseeBackGroundSet,claseeOrange]">多个class组合</h1>
<!-- 动态style ,如果容器内的style发生变化则整个标签样式也会变化-->
<h1 :style="{color:varcolor,font:varfont}">varcolor</h1>
</div>
<script>
const vm = new Vue({//vm容器:数据、逻辑(函数)
el: '#app',
data: {
url:"",
claseeRed:"red",
claseeGreen:"green",
claseeOrange:"orange",
claseeBackGroundSet:"backGroundSet",
varcolor:"pink",
varfont:800
}
})
</script>
</body>
</html>
双向绑定
表单绑定
只有表单才会产生事件激活v-model双向绑定,也只有变单才有意义,因为接收了用户的输入;
表单显示的内容就是input的内容
<!-- 标签视图 -->
<div id="app">
<input v-model="form.username">
</div>
<script>
const vm = new Vue({//vm容器:数据、逻辑(函数)
el: '#app',
created () {
setInterval(()=>{
console.log(this.form.username)
},2000);
},
data: {
form:{
username:"初始值"
}
}
})
</script>
用定时器观察input是否发生了变化
<!-- 标签视图 -->
<div id="app">
<input v-model="form.username">
<button @click="changeForm">改变表单的值</button>
</div>
<script>
const vm = new Vue({//vm容器:数据、逻辑(函数)
el: '#app',
methods:{
changeForm(){
this.form.username="输入框的值被改变了"
}
},
data: {
form:{
username:"初始值"
}
}
})
</script>
数据修饰
对数据做一层处理,再回传给vm容器
<input v-model.number="age" type="number">
<input v-model.trim="msg">
<input v-model.lazy="msg" >
计算绑定
input框其实就是一个input的dom元素;由于他是html底层元素,我们看不到他的内部结构,所以我们先剖析以下他的内部结构才让我们双向绑定更加理解;
【 input框的内部结构】
(1)input的显示:value值决定了显示的内容是什么
(2)input的原生输入:input的原生事件是输入……的时候就直接改变value值
(3)input的改变输出:当value改变的时候,此时另外一个事件激活change则可以对外提供,我改变的内容是什么
(4)input的强制输入:我们之前学过dom直接拿到dom之后操作value值也可以改变value值和显示,但这个方法不会激活改变输出的回调
【计算方法的引入】
有时候我们有这样的一个需求,某个表单组件是双向绑定两个data值,并进行处理组合后输入给input框,因此我们就要拦截对表达组件的输出方法(get)和输出方法(set),这一系列是借助vue的计算属性完成的
<!-- 标签视图 -->
<div id="app">
全名<input type="text" placeholder="全名" v-model="fullName"><br>
First Name<input type="text" placeholder="First Name" v-model="firstName"><br>
Last Name<input type="text" placeholder="Last Name" v-model="lastName"><br>
</div>
<script>
const vm = new Vue({
el: '#app',
data: {
firstName: 'A',
lastName: 'B',
},
computed: {
fullName: {
/*
监听this.firstName、 this.lastName
发生改变的时候去调用input的【强制输入】改变fullName的value值
*/
get() {
return this.firstName + '-' + this.lastName
},
/*
接受input的【原生输入】,并反向改变firstName、lastName
程序中这是自己设计的,就是可以接收input的原生事件做一个拦截处理
*/
set(value) {
const names = value.split('-')
this.firstName = names[0]
this.lastName = names[1]
}
}
}
})
</script>
结尾
后续我们将拆解每个表单组件的事件绑定机制和改变机制,双向绑定主要就是针对表单组件