Vue是一个MVVM模式的实现者,MVVM核心是ViewModel,ViewModel就是一个观察者。
Vue概括:
核心:数据驱动和组件化。
优点:借鉴了AngulaJS的模块化开发和React虚拟DOM,虚拟DOM就是把DOM操作放到内存执行。
常用的。
常用的自定义属性:
v-if
v-else-if
v-else
v-for
v-on 绑定事件
v-model 数据双向绑定
v-bind 为组件绑定参数
组件化:
组合组件slot插槽
组键内部绑定事件需要用到this.$emit(‘事件名’,参数);
遵循SoC关注度分离原则,Vue是纯粹的视图框架,它并不包含比如AJAX之类的通信功能,为了解决通信问题,我们需要使用Axios框架做异步通信。
自己的特色:
计算属性computed:里面写的还是函数,只是将计算结果相同的方法做静态存储
Vue 实战:
- 开发都要基于NodeJS。
- 实际开发采用vue-cli脚本架开发。
- vue-router 路由。
- vuex状态管理。
Vue UI
- ElementUI 饿了么出品
- iview
- ice 飞冰,阿里巴巴出门
各种自定义属性的实践
- v-if v-else-if v-else
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
<div v-if="type == 'A'">a</div> #两个等于三个等于都行,不知道是不是我还有情况没试
<div v-else-if="type == 'B'">b</div>
<div v-else>NO</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.js"></script>
<script type="text/javascript">
var vm = new Vue({
el: '#app', #绑定id为APP的div
data: {
type: "b"
}
})
</script>
</body>
</html>
判断data中type的值,来改变页面显示哪个div。
源码中写了三个div,但是判断之后最后只有一个div输出。
- v-for
<body>
<div id="app">
<ul>
<li v-for="item in items">
{{item}} #取数据需要{{}}两个花括号。
</li>
</ul>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.js"></script>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
items:['zzz','xxx','ccc']
}
})
</script>
</body>
擦好看代码可知在data中有个列表items,通过v-for循环将其中的数据打印出来,结果如下:
由结果可以知道,for循环最终生成了三个li标签,并将数据依次放置在li标签中。
事件
点击弹窗事件
<body>
<div id="app">
<button v-on:click="sayHi">点我</button> #绑定点击事件,函数为sayHi
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.js"></script>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
message: 'Hello Message'
},
methods: {
sayHi: function (event) { sayHi方法
alert(this.message); this是代表这整个变量 }
}
})
</script>
</body>
结果:
由结果可知点击会弹出一个弹窗,其中的内容是data中的message内容。
组件
在Vue中万物都是组件,整个页面就是组件的容器,实现就是创建组件的容器,然后再创建适合的组件插入容器中。
<body>
<div id="app">
<ul>
<my-component-li v-for="item in items" v-bind:item="item"></my-component-li>
</ul>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.js"></script>
<script type="text/javascript">
Vue.component("my-component-li", {
props: ['item'],
template: '<li>{{item}}</li>'
} );
var vm = new Vue({
el: '#app',
data: {
items: ['zs','ls','ww']
}
});
</script>
</body>
首先再div中创建my-component标签,这个标签就是一个容器,,之后在Vue.component创建指定的组件插入进去,内容为[‘item’],组件模板为’li{{item}}/li’。v-for循环将data中items的值取出来。
v-bind就是为组件绑定参数。
结果:
表单
什么是双向数据绑定
Vue.js是一个MVVM框架,即数据双向绑定,就是当数据发生改变的时候,视图也就发生变化,当视图发送变化的时候,数据也会跟着同步变化,数据双向绑定一般是对于UI控件来说的,非UI控件不会涉及数据双向绑定。
使用数据双向绑定的优点
在全局性数据流使用表项,方便追踪,局部性数据流使用双向,简单易操作。
在表单中使用双向数据绑定
用v-model指令在表单<input>,<textarea>,<select>
元素上创建双向数据绑定,他会更具控件类型自动选取正确的方法来更新元素。v-model本质上是语法糖。它负责监听用户的输入事件以更新数据,并对一些极端场景进行一些特殊处理。
v-model会忽略所有表单元素的value、checked。selected特性的初始值
下拉框、输入框例子
<body>
<div id="app">
<input type="text" v-model="message" value="hello"> Input内容:{{message}} <!--实现双向绑定-->
<br><br><br>
<div>
下拉框:
<select v-model="selected">
<option disabled value="">请选择</option>
<option >A</option>
<option >B</option>
<option >C</option>
</select>
<span>选中的值:{{selected}}</span>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.js"></script>
<script type="text/javascript">
var vm = new Vue({
el:'#app',
data: {
message: 'hello vue',
selected:'',
}
})
</script>
</body>
代码中写了一个输入框和下拉框,实现的是在输入框内的数据和后面的数据相匹配。
在输入框中的value属性是无效的,v-model会忽略其中的值
结果
计算属性
什么是计算属性:
首先计算属于属性,属性是名词,但是计算属于动词,它的意思是将行为转化为静态的属性。
用一个获取时间的方法观察区别。
<body>
<div id="app">
<div>获取时间:{{getCurrentTime()}}</div>
<div>获取属性:{{getCurrentTime1}}</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.js"></script>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
methods: {
getCurrentTime: function () {
return Date.now();
}
},
computed: {
getCurrentTime1: function () {
return Date.now();
}
}
})
</script>
由上段代码可知{{getCurrent Time()}}
和{{getCurrentTIme}}
分别是函数和方法,方法每次获取的时候都会运行,属性则为定值。
结果
由上可知,函数每次运行 时间都会变化,因为函数一直在运行,每获取一次都会运行,而下面的属性则为开始运行一次,之后一直保存为属性,每次调用都是提取数据。
内容分发与自定义事件
<body>
<!--创建插槽-->
<div id="app">
<todo>
<todo-title slot="todo-title" v-bind:title="title"></todo-title>
<todo-items slot="todo-items" v-for="item in todoItems" v-bind:item="item"></todo-items>
</todo>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.js"></script>
<script type="text/javascript">
// 创建一个名为todo的事件组件
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>{{title}}</div>"
});
//创建组件中的内容组件
Vue.component("todo-items", {
props: ['item'],
template: "<li>{{item}}</li>"
});
//实例化Vue并初始化数据
var vm = new Vue({
el: '#app',
data: {
title: '姓名',
todoItems: ['zs','ls','ww'],
}
})
</script>
</body>
结果如图:
上面就完成了创建一个插槽,并创建一个大组件,里面包含了两个小组件。
自定义事件
目标是在上面代码的基础上增加一个删除键,能够将数据删除,这样就需要一个参数对数据执行标记。
<body>
<!--创建插槽-->
<div id="app">
<todo>
<todo-title slot="todo-title" v-bind:title="title"></todo-title>
<todo-items slot="todo-items" v-for="(item, index) in todoItems" v-bind:item="item" v-bind:index="index" v-on:remove="removeItem(index);"></todo-items>
<!--for循环将数据标上号,给出index,v-bind对index进行绑定,v-on将数据传入vm变量中 -->
</todo>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.js"></script>
<script type="text/javascript">
// 创建一个名为todo的事件组件
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>{{title}}</div>"
});
//创建组件中的内容组件
Vue.component("todo-items", {
props: ['item'],
template: "<li>{{index}} -{{item}} <button @click='remove(index);'>删</button></li>",//在该组件中定义的函数方法只能调用当前的,调其他的需要转接,点击的时候获取index
methods: {
remove: function (index) {
this.$emit('remove',index) //指向<div>中绑定的removeItem方法并将index传入。
}
}
});
//实例化Vue并初始化数据
var vm = new Vue({
el: '#app',
data: {
title: '姓名',
todoItems: ['zs','ls','ww'],
},
methods: {
removeItem: function(index) { //index时v-on传入的数据
this.todoItems.splice(index, 1); //切片,将数据按照index为起点,后面数字为个数进行切片
}
}
});
</script>
</body>
首先在v-for时增加一个index索引,将每个数据标号。
然后依次将数据传入,最后根据编号删除数据。
结果
开始
删除后: