第一个Vue程序
导入在线cdn
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<!-- 从vue对象中取出message-->
<!-- view层就变成了一个模板-->
{{message}}
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script>
var vm = new Vue({
//id选择器选中div元素
el:"#app",
//数据都是以键值对的形式存放的
data:{//model层处理数据
message:"hello,vue!"
}
})
</script>
</html>
最终出来的效果
那么viewmodel层应该如何理解,实际viewmodel就是一个双向绑定的东西,一边绑定了view的样式一边绑定了model的数据,具有即时编译的特性可以实现数据的实时监听,不用刷新页面也可以更新数据。
这里我们尝试对数据进行修改
回车!数据刷新了,但这个过程中我们的页面并没有刷新。而是通过虚拟dom来完成的。虚拟dom是一层对真实dom的抽象,这些抽象出来的属性最终映射到真实dom中。在实际开发中频繁操作真实dom容易导致浏览器卡顿用户体验差。
Vue的基本语法
-
v-bind
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="app"> <span v-bind:title="message"> hhhhhhhhh <label v-text="message"/> </span> </div> </body> <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script> <script> var vm = new Vue({ el:"#app", data:{ message:"hello,vue!" } }) </script> </html>
-
v-if
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="app"> <h1 v-if="type=='A'">A</h1> <h1 v-else-if="type=='B'">B</h1> <h1 v-else>C</h1> </div> </body> <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script> <script> var vm = new Vue({ el:"#app", data:{ type:"A" } }) </script> </html>
-
v-for
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="app"> <li v-for="a in array"> 姓名:{{a.name}} 年龄:{{a.age}} </li> </div> </body> <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script> <script> var vm = new Vue({ el:"#app", data:{ array:[ {name:'zjq',age:18} , {name:'aaa',age:90}, {name:'bbb',age: 12} ] } }) </script> </html>
-
v-on
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="app"> <button v-on:click="sayHi">CLICK ME</button> </div> </body> <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script> <script> var vm = new Vue({ el:"#app", data:{ message:"dianwo" }, methods:{ //方法需要放在methods域中 sayHi:(function (event) {//传入事件on-click alert(this.message)//绑定数据 }) } }) </script> </html>
数据的双向绑定
v-bind只是单向绑定,是数据绑定到视图。双向绑定是通过视图改变数据,然后数据最终影响视图。这需要用v-model完成。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<input v-model="message">
<!-- 视图绑定到数据 这个输入框中输入的文字会被绑定到message-->
<br>
{{message}}
<!-- 数据绑定到视图 message改动视图也会跟着改动-->
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script>
var vm = new Vue({
el:"#app",
data:{
message:""
}
})
</script>
</html>
刚开始是这样的
随着往当中写入数据下面一行会实时更新我写入的数据
Vue组件
组件就是h1、input这类标签被称之为组件,我们可以自定义我的自己的组件,在代码中实现复用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<my-comp v-for="item in array" v-bind:arg="item">
</my-comp>
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script>
//插入一个组件 第一个参数是组件的名字第二个是组件的实体,实体中包含需要接收的参数和模板
Vue.component("my-comp",{
props:['arg'],
template:'<h1>{{arg}}</h1>'
});
var vm = new Vue({
el:"#app",
data:{
array:[
"aaa",
"bbb",
"ccc"
]
}
})
</script>
</html>
Vue计算属性
计算属性是将方法的返回值作为一个结果保存在内存中,相当于缓存。当数据刷新时重新计算对应的值。相较于方法更加节省运行空间。vue的计算属性叫computed。计算属性里的方法可以不加括号调用,因为他是一个属性,但是methods里的方法就不可以了。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<p>{{c()}}</p>
<p>{{h}}</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script>
var vm = new Vue({
el:"#app",
data:{
message:'zjq'
},
methods:{
c: function(){
return Date.now();
}
},
computed:{
h:function(){
return Date.now();
}
}
});
</script>
</body>
</html>
插槽
插槽就是动态的留出一个口来进行组件的拔插,通过留一个<slot></slot>
来留出一个空,用name属性绑定对应的组件。组件间使用props传递数据,模板部分还需要slot属性绑定指定组件。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<todo>
<todo-title slot="todo-title" :title="title"></todo-title>
<todo-items slot="todo-items" v-for="item in items" :item="item"></todo-items>
</todo>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script>
Vue.component("todo",{
props: ['title','items'],
template: '<div>' +
'<slot name="todo-title" ></slot>' +
'<ul>' +
'<slot name="todo-items" ></slot>'+
'</ul>'+
'</div>'
});
Vue.component("todo-title",{
props: ['title'],
template: '<div>' +
'<h1>{{title}}</h1>'+
'</div>'
});
Vue.component("todo-items",{
props: ['item'],
template:
'<li>{{item}}</li>'
});
var vm = new Vue({
el:"#app",
data:{
title:'今天要干的事',
items:["111","222","333"]
}
});
</script>
</body>
</html>
自定义事件的分发
假设这样一个需求,我们需要在一个组件中去删除vue实例中的数据。由于组件和vue实例时同级的,所以是无法操作其中的数据的。这时候就需要一个中间商,组件和实例都是可以和前端模板绑定的。
具体操作如下:
- 在vue实例中定义一个方法为删除元素,传入元素下标。
- 在组件中定义一个方法调用自定义事件,传入事件名和参数。该组件的模板中button也要绑定该事件。
- 在前端模板使用v-on:事件名=”实例中定义的方法(传入的参数)“进行自定义事件的绑定。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<todo>
<todo-title slot="todo-title" :title="title"></todo-title>
<todo-items slot="todo-items" v-for="(item,index) in todoItems"
:item="item" :key="index" :index="index" v-on:remove="removeItem(index)"></todo-items>
</todo>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script>
Vue.component("todo",{
template: '<div>' +
'<slot name="todo-title" ></slot>' +
'<ul>' +
'<slot name="todo-items" ></slot>'+
'</ul>'+
'</div>'
});
Vue.component("todo-title",{
props: ['title'],
template: '<div>' +
'<h1>{{title}}</h1>'+
'</div>'
});
Vue.component("todo-items",{
props: ['item','index'],
template:
'<li>{{index}}--{{item}}<button @click="remove" >delete</button></li>'
,
methods:{
remove:function (index) {
this.$emit('remove',index)//调用自定义事件,第一个参数时自定义事件的名字,第二个是传递的参数
}
}
});
var vm = new Vue({
el:"#app",
data:{
title:'今天要干的事',
todoItems:["111","222","333"]
},
methods: {
removeItem:function (index) {
console.log("已删除第"+index+"个元素")
this.todoItems.splice(index,1)
}
}
});
</script>
</body>
</html>