1.Vue双向绑定
Vue.js是一个MVVM框架,即数据双向绑定,即当数据发生变化的时候,视图也就发生变化,当视图发生变化的时候,数据也会同步变化。这就是Vue.js的精髓之处了。
可以使用v-model 指令在表单<input> ,<textarea> 以及<select> 元素上创建双向数据绑定。它会根据控件类型自动选取正确的方式来更新元素。
注意:v-model会忽略所有表单元素的value,checked,selected特性的初始值而总是将Vue实例的数据作为数据来源。应该通过js在组件的data选项中生命初始值。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
输入的文本:<input type="text" v-model="message">{{message}}
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<script>
var vm = new Vue({
el:"#app",
data:{
message: "123"
},
});
</script>
</body>
</html>
我们在更新文本框的时候,后面的message也能实现同步的更新,是因为我们实现了双向绑定
单选框
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<input type="radio" name="sex" v-model="checked" value="男">男
<input type="radio" name="sex" v-model="checked" value="女">女
<p>
选中了:{{checked}}
</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<script>
var vm = new Vue({
el:"#app",
data:{
checked:'女'
},
});
</script>
</body>
</html>
下拉框
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<select v-model="selected">
<option value="" disabled>--请选择--</option>
<option>A</option>
<option>B</option>
<option>C</option>
</select>
<p>
选中了:{{selected}}
</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<script>
var vm = new Vue({
el:"#app",
data:{
selected:''
},
});
</script>
</body>
</html>
2.Vue的组件
组件是可复用的Vue 实例,就是一组可以重复使用的模板,就跟JSTL的自定义标签,Thymeleaf的th:fragment 等框架有着异曲同工之妙。通常一个应用会以一颗嵌套的组件树的形式来组织
例如,你可能会有页头、侧边栏、内容区等组件,每个组件又包含了其它的像导航链接、博文之类的组件。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<adie v-for="item in items" v-bind:it="item"></adie>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<script>
Vue.component("adie",{
props: ['it'],
template: '<li>{{it}}</li>'
});
var vm=new Vue({
el: "#app",
data:{
items:["java","linux","前端"]
}
})
</script>
</body>
</html>
一个组件默认可以拥有任意数量的 prop,任何值都可以传递给任何 prop。
Prop 是你可以在组件上注册的一些自定义 attribute。当一个值传递给一个 prop attribute 的时候,它就变成了那个组件实例的一个 property。为了给博文组件传递一个标题,我们可以用一个 props 选项将其包含在该组件可接受的 prop 列表中:
Vue.component('blog-post', {
props: ['title'],
template: '<h3>{{ title }}</h3>'
})
一个组件默认可以拥有任意数量的 prop,任何值都可以传递给任何 prop。在上述模板中,你会发现我们能够在组件实例中访问这个值,就像访问 data 中的值一样。
当prop被注册后,可以这样把数据作为一个自定义attribute传递进来。
<blog-post title="My journey with Vue"></blog-post>
<blog-post title="Blogging with Vue"></blog-post>
<blog-post title="Why Vue is so fun"></blog-post>
此外,可能在data中有一个博文的数组
new Vue({
el: '#blog-post-demo',
data: {
posts: [
{ id: 1, title: 'My journey with Vue' },
{ id: 2, title: 'Blogging with Vue' },
{ id: 3, title: 'Why Vue is so fun' }
]
}
})
并想要为每篇博文渲染一个组件:
<blog-post
v-for="post in posts"
v-bind:title="post.title"
></blog-post>
我们可以使用 v-bind 来动态传递 prop
3.Axios异步通信
3.1.什么是Axios
Axios是一个开源的可以用在浏览器端和Node JS 的异步通信框架, 主要作用就是实现AJAX异步通信,其功能特点如下:
- 从浏览器中创建
XMLHttpRequests - 从node.js创建http请求
- 支持Promise API[JS中链式编程]
- 拦截请求和响应
- 转换请求数据和响应数据
- 取消请求
- 自动转换JSON数据
- 客户端支持防御XSRF(跨站请求伪造)
GitHub:https://github.com/axios/axios 中文文档:http://www.axios-js.com/
3.2.为什么要使用Axios
由于Vue.js 是一个视图层框架并且作者(尤雨溪) 严格准守SoC(关注度分离原则)所以Vue.js 并不包含AJAX的通信功能, 为了解决通信问题,作者单独开发了一个名为vue-resource 的插件, 不过在进入2.0版本以后停止了对该插件的维护并推荐了Axios 框架。少用jQuery, 因为它操作Dom太频繁。
3.3.第一个Axios应用程序
因为接口大部分都是json格式的数据,所以我们模拟一个json格式的数据用来测试 data.json
{
"name": "a碟",
"url": "https://blog.csdn.net/ladiez",
"page": 1,
"isNonProfit": true,
"address": {
"street": "人民东路",
"city": "湖南",
"country": "中国"
},
"links": [
{
"name": "bilibili",
"url": "https://blog.csdn.net/ladiez"
},
{
"name": "blog",
"url": "https://blog.csdn.net/ladiez"
},
{
"name": "百度",
"url": "https://blog.csdn.net/ladiez"
}
]
}
测试
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
[v-clock]{
display: none;
}
</style>
</head>
<body>
<div id="app" v-clock>
<div>{{info.name}}</div>
<a v-bind:href="info.url">点击</a>
</div>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<script>
var vm=new Vue({
el: "#app",
data(){
return{
info:{
name:null,
address:{
street:null,
city:null,
country:null
},
utl:null,
}
}
},
mounted(){
axios.get('../data.json').then(response=>(this.info=response.data))
}
})
</script>
</body>
</html>
说明:
- 在这里使用了v-bind将a:href的属性值与Vue实例中的数据进行绑定
- 使用axios框架的get方法请求AJAX并自动将数据封装进了Vue实例的数据对象中
- 我们在data中的数据结构必须和
Ajax 响应回来的数据格式匹配
4.Vue的生命周期
https://cn.vuejs.org/v2/guide/instance.html#生命周期图示
? Vue实例有一个完整的生命周期,也就是从开始创建初始化数据、编译模板、挂载DOM、渲染一更新一渲染、卸载等一系列过程,我们称这是Vue的生命周期。通俗说就是Vue实例从创建到销毁的过程,就是生命周期。 ??在Vue的整个生命周期中,它提供了一系列的事件,可以让我们在事件触发时注册JS方法,可以让我们用自己注册的JS方法控制整个大局,在这些事件响应方法中的this直接指向的是Vue的实例。
5.计算属性
计算属性的重点突出在属性 两个字上(属性是名词),首先它是个属性 其次这个属性有计算 的能力(计算是动词),这里的计算 就是个函数:简单点说,它就是一个能够将计算结果缓存起来的属性(将行为转化成了静态的属性),仅此而已;可以想象为缓存,节约开销。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<p>currentTime1 {{currentTime1()}}</p>
<p>currentTime2 {{currentTime2}}</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<script>
var vm = new Vue({
el:"#app",
data:{
message:"hello,adie"
},
methods:{
currentTime1:function () {
return Date.now();
},
},
computed:{
currentTime2:function () {
this.message
return Date.now();
}
}
});
</script>
</body>
</html>
可以看到上述案例,同样是返回一个时间戳的currentTime1和currentTime2。在浏览器中我们并没有发现有什么区别。但是如果我们在控制台中输出vm.message='a碟' .见以下案例
- methods:定义方法, 调用方法使用currentTime1(), 需要带括号
- computed:定义计算属性, 调用属性使用currentTime2, 不需要带括号:this.message是为了能够让currentTime2观察到数据变化而变化
- 只要方法中的值发生了变化,则缓存就会刷新。可以在控制台使用
vm.message=”a碟" , 改变下数据的值,可以看到上面的效果
结论: ??调用方法时,每次都需要讲行计算,既然有计算过程则必定产生系统开销,那如果这个结果是不经常变化的呢?此时就可以考虑将这个结果缓存起来,采用计算属性可以很方便的做到这点,计算属性的主要特性就是为了将不经常变化的计算结果进行缓存,以节约我们的系统开销;
6.插槽
插槽的用法很多,详细的了解可以前往官网查看。
在Vue.js 中我们使用<slot> 元素作为承载分发内容的出口,作者称其为插槽,可以应用在组合组件的场景中。
实例
比如准备制作一个待办事项组件(todo) ,该组件由待办标题(todo-title) 和**待办内容(todo-items)**组成,但这三个组件又是相互独立的,该如何操作呢?
1.定义一个待办事项的组件
我们需要让待办事项的标题和值实现动态绑定,所以在代码中留出来了一个插槽,即slot
因为我们有时需要多个插槽,对于这种情况,<slot> 有一个特殊的attribute:name 。这个attribute可以用来定义额外的插槽。
一个不带 name 的 <slot> 出口会带有隐含的名字“default”。
Vue.component("todo",{
template: '<div>\
<slot name="a"></slot>\
<ul>\
<slot name="b"></slot>\
</ul>\
</div>'
});
2.定义一个名为todo-title的待办事项标题和todo-items待办事项内容
Vue.component("todo-title",{
props: ['title'],
template: '<div>{{title}}</div>'
})
Vue.component("todo-items",{
props: ['item'],
template: '<li>{{item}}</li>'
})
3.实例Vue并初始化内容
var vm = new Vue({
el:"#app",
data:{
Title: "a碟",
todoItems: [
'Java',
'Linux',
'Python'
]
}
});
4.将这些值通过插槽传入
在向具名插槽提供内容的时候,我们可以在一个 <template> 元素上使用 v-slot 指令,并以 v-slot 的参数的形式提供其名称
现在 <template> 元素中的所有内容都将会被传入相应的插槽。任何没有被包裹在带有 v-slot 的 <template> 中的内容都会被视为默认插槽的内容。
注意 ** v-slot 只能添加在 <template> 上 ** (只有一种例外情况)
我在官网了解到以上template是最新的使用方法。而我学习时使用的方法好像是废弃的。下面是官网提供的最新的使用方法
<div id="app">
<todo>
<template v-slot:a>
<todo-title v-bind:title="Title"></todo-title>
</template>
<template v-slot:b>
<todo-items v-for="i in todoItems" v-bind:item="i"></todo-items>
</template>
</todo>
</div>
学习时的方法
<div id="app">
<todo>
<todo-title slot="a" v-bind:title="Title"></todo-title>
<todo-items slot="b" v-for="i in todoItems" v-bind:item="i"></todo-items>
</todo>
</div>
以上两种方法都是可以使用的
7.自定义事件
通以上代码不难发现,数据项在Vue的实例中,但删除操作要在组件中完成,那么组件如何才能删除Vue实例中的数据呢?此时就涉及到参数传递与事件分发了,Vue为我们提供了自定义事件的功能很好的帮助我们解决了这个问题;使用this.$emit('自定义事件名',参数) , 操作过程如下:
1.在Vue实例中增加了methods对象并定义了removeItems方法用来删除Vue实例中的数据
var vm = new Vue({
el:"#app",
data:{
Title: "a碟",
todoItems: [
'Java',
'Linux',
'Python'
]
},
methods:{
removeItems:function (index) {
console.log("删除了"+this.todoItems[index]+"OK")
this.todoItems.splice(index,1)
}
}
});
2.修改todo-items待办内容组件的代码,增加一个删除按钮,并且绑定事件
Vue.component("todo-items",{
props: ['item','ind'],
template: '<li>{{item}}<button @click="remove123">删除</button></li>',
methods: {
remove123:function (ind) {
this.$emit('remove',ind)
}
}
})
3.修改todo-items待办内容组件的HTML代码,增加一个自定义事件,可以叫remove,和组件的方法绑定,然后绑定到Vue的方法
<template v-slot:b>
<todo-items v-for="(i,index) in todoItems"
v-bind:item="i" :ind="index" v-on:remove="removeItems(index)" ></todo-items>
</template>
完整代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<todo>
<template v-slot:a>
<todo-title v-bind:title="Title"></todo-title>
</template>
<template v-slot:b>
<todo-items v-for="(i,index) in todoItems"
v-bind:item="i" :ind="index" v-on:remove="removeItems(index)" ></todo-items>
</template>
</todo>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<script>
Vue.component("todo",{
template: '<div>\
<slot name="a"></slot>\
<ul>\
<slot name="b"></slot>\
</ul>\
</div>'
});
Vue.component("todo-title",{
props: ['title'],
template: '<div>{{title}}</div>'
})
Vue.component("todo-items",{
props: ['item','ind'],
template: '<li>{{item}}<button @click="remove123">删除</button></li>',
methods: {
remove123:function (ind) {
this.$emit('remove',ind)
}
}
})
var vm = new Vue({
el:"#app",
data:{
Title: "a碟",
todoItems: [
'Java',
'Linux',
'Python'
]
},
methods:{
removeItems:function (index) {
console.log("删除了"+this.todoItems[index]+"OK")
this.todoItems.splice(index,1)
}
}
});
</script>
</body>
</html>
8.Vue入门小结
核心:数据驱动,组件化
优点:借鉴了AngularJS的模块化开发和React的虚拟Dom,虚拟Dom就是把Demo操作放到内存中执行;
常用的属性:
- v-if
- v-else-if
- v-else
- v-for
- v-on绑定事件,简写
@ - v-model数据双向绑定
- v-bind给组件绑定参数,简写
:
组件化:
- 组合组件slot插槽
- 组件内部绑定事件需要使用到
this.$emit("事件名",参数); - 计算属性的特色,缓存计算数据
遵循SoC关注度分离原则,Vue是纯粹的视图框架,并不包含,比如Ajax之类的通信功能,为了解决通信问题,我们需要使用Axios框架做异步通信;
说明
Vue的开发都是要基于NodeJS,实际开发采用Vue-cli脚手架开发,vue-router路由,vuex做状态管理;Vue UI,界面我们一般使用ElementUI(饿了么出品),或者ICE(阿里巴巴出品)来快速搭建前端项目
官网:
- https://element.eleme.cn/#/zh-CN
- https://ice.work/
|