Vue入门(一)
1. 概述
推荐看官方文档:https://cn.vuejs.org/v2/guide/
前端发展历史:https://blog.csdn.net/qq_46138160/article/details/111028492
-
Soc原则:关注点分离原则
-
Vue 的核心库只关注视图层,方便与第三方库或既有项目整合。
-
HTML + CSS + JS : 视图 : 给用户看,刷新后台给的数据
-
网络通信 : axios
-
页面跳转 : vue-router
-
状态管理:vuex
-
Vue-UI : ICE , Element UI
2. 第一个Vue程序
2.1 什么是 MVVM
MVVM(Model-View-ViewModel)是一种软件设计模式,由微软WPF(用于替代WinForm,以前就是用这个技术开发桌面应用程序的)和Silverlight(类似于Java Applet,简单点说就是在浏览器上运行WPF)的架构师Ken Cooper和Ted Peters开发,是一种简化用户界面的事件驱动编程方式。由John Gossman(同样也是WPF和Sliverlight的架构师)与2005年在他的博客上发表。
MVVM源自于经典的MVC(Model-View-Controller)模式。MVVM的核心是ViewModel层,负责转换Model中的数据对象来让数据变得更容易管理和使用。其作用如下:
-
该层向上与视图层进行双向数据绑定
-
向下与Model层通过接口请求进行数据交互
当下流行的MVVM框架有Vue.js,Anfular JS
2.2 为什么要使用 MVVM
-
低耦合:视图(View)可以独立于Model变化和修改,一个ViewModel可以绑定到不同的View上,当View变化的时候Model可以不变,当Model变化的时候View也可以不变。
-
可复用:你可以把一些视图逻辑放在一个ViewModel里面,让很多View重用这段视图逻辑。
-
独立开发:开发人员可以专注于业务逻辑和数据的开发(ViewMode),设计人员可以专注于页面设计。
-
可测试:界面素来是比较难以测试的,而现在测试可以针对ViewModel来写。
View层展现的不是Model
层的数据, 而是ViewModel
的数据, 由ViewModel
负责与Model
层交互, 这就完全解耦了View
层和Model
层, 这个解耦是至关重要的, 它是前后端分离方案实施的重要一环。
2.3 第一个Vue程序
【说明】IDEA可以安装Vue的插件!
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--3. 将数据绑定到页面元素-->
<!--view层,模板-->
<div id="app">
{{message}}
</div>
<!--1. 导入Vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<!--2. 创建一个Vue实例-->
<script type="text/javascript">
var vm = new Vue({
el:"#app",
/*Model:数据*/
data:{
message:"hello,vue!"
}
});
</script>
</body>
</html>
3. 基础语法指令
3.1 v-bind:绑定元素特性
简写:冒号 :
title绑定message元素使得鼠标悬停可以显示
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<span v-bind:title="message">鼠标悬浮</span>
</div>
<!--导入vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<script>
var vm=new Vue({
el:'#app',
data: {
message: "hello world"
}
});
</script>
3.2 v-if, v-else
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<span v-bind:title="message">鼠标悬浮</span>
<h1 v-if="ok">yes</h1>
<h1 v-else>no</h1>
<h1 v-if="type==='A'">a</h1>
<h1 v-else-if="type==='B'">b</h1>
<h1 v-else-if="type==='C'">c</h1>
</div>
<!--导入vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<script>
var vm=new Vue({
el:'#app',
data: {
message: "hello world",
ok: true,
type: 'A'
}
});
</script>
</body>
</html>
3.3 v-for
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<ul>
<li v-for="item in items">{{ item.name }}</li>
</ul>
<ul>
<li v-for="(item,index) in items">{{ item.name }}--{{ index }}</li>
</ul>
</div>
<!--导入vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<script>
var vm=new Vue({
el:'#app',
data: {
items: [
{name: "java"},
{name: "Linux"},
{name: "Vue"}
]
}
});
</script>
</body>
</html>
3.4 v-on 监听事件
缩写:@
<!DOCTYPE html>
<html lang="en" xmlns:v-on="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<button v-on:click="sayHi">点我</button>
</div>
<script src="../js/vue.js"></script>
<script type="text/javascript">
var vm = new Vue({
el:"#app",
data:{
message:'Hello World'
},
methods:{
sayHi:function(event){
//'this'在方法里面指向当前Vue实例
alert(this.message);
}
}
});
</script>
</body>
</html>
4. Vue双向绑定 v-model
4.1 什么是双向绑定
-
Vue.js是一个MVVM框架,即数据双向绑定,即当数据发生变化的时候,视图也就发生变化,当视图发生变化的时候,数据也会跟着同步变化。
-
值得注意的是,我们所说的数据双向绑定,一定是对于UI控件来说的,非UI控件不会涉及到数据双向绑定。
4.2 在表单中使用双向数据绑定
v-model会忽略所有元素的value、checked、selected特性的初始值而总是将Vue实例的数据作为数据来源,你应该通过JavaScript在组件的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 }}
<br/>
性别:<input type="radio" name="sex" value="男" v-model="choose" >男
<input type="radio" name="sex" value="女" v-model="choose" >女
<p>
选择了谁:{{choose}}
</p>
下拉框 :<select v-model="selected">
<option value="" disabled>--请选择--</option>
<option>A</option>
<option selected>B</option>
<option>C</option>
</select>
<span>下拉框选中了:{{selected}}</span>
</div>
<!--导入vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<script>
var vm=new Vue({
el:'#app',
data: {
message: "你好",
checked: false,
choose: '',
selected: ''
},
});
</script>
</body>
</html>
5. Vue组件
在实际开发中,我们并不会用以下方式开发组件,而是采用vue-cli创建,vue模板文件的方式开发,以下方法只是为了让大家理解什么是组件。
组件是可复用的Vue实例,说白了就是一组可以重复使用的模板,跟JSTL的自定义标签、Thymeleaf的th:fragment 等框架有着异曲同工之妙。
【组件demo】
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<!--组件:传递个组件的值:props-->
<test v-for="(item,index) in items" v-bind:lu="item"></test>
</div>
<!--导入vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<script>
//定义一个Vue组件
Vue.component("test",{
props: ['lu'],//接收参数
template:"<li>{{lu}}</li>"
});
var vm=new Vue({
el:'#app',
data: {
items: ["java","Linux","前端"]
}
});
</script>
</body>
</html>
6. Axios通信
6.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/
6.2 第一个Axios应用程序
【data.json】
{
"name": "狂神说Java",
"url": "https://blog.kuangstudy.com",
"page": 1,
"isNonProfit": true,
"address": {
"street": "含光门",
"city": "陕西西安",
"country": "中国"
},
"links": [
{
"name": "bilibili",
"url": "https://space.bilibili.com/95256449"
},
{
"name": "狂神说Java",
"url": "https://blog.kuangstudy.com"
},
{
"name": "百度",
"url": "https://www.baidu.com/"
}
]
}
【测试代码】
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!--v-cloak 解决闪烁问题-->
<style>
[v-cloak] {
display: none;
}
</style>
</head>
<body>
<div id = "vue" v-cloak>
<div>名称:{{info.name}}</div>
<div>地址:{{info.address.country}}-{{info.address.city}}-{{info.address.street}}</div>
<!-- <div>链接:<a v-bind:href="info.url" target="_blank">{{info.url}}</a> </div>-->
<div v-for="link in info.links">
{{link.name}}--<a v-bind:href="link.url" target="_blank">{{link.url}}</a>
</div>
</div>
<!--引入 JS 文件-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script type="text/javascript">
var vm = new Vue({
el: '#vue',
data() {
return {
info: {
name: null,
address: {
country: null,
city: null,
street: null
},
url: null,
links: [{name:null, url:null},
{name:null, url:null},
{name:null, url: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响应回来的数据格式匹配!
6.3 Vue的生命周期
7. 计算属性、内容分发、自定义事件
7.1 Vue计算属性
计算属性的重点突出在属性两个字上(属性是名词),首先它是个属性其次这个属性有计算的能力(计算是动词),这里的计算就是个函数;简单点说,它就是一个能够将计算结果缓存起来的属性(将行为转化成了静态的属性),仅此而已;可以想象为缓存!
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
<!--v-clock解决闪烁问题-->
[v-cloak ]{
display: none !important;
}
</style>
</head>
<body>
<div id="app" v-cloak>
<p>methods:{{currentTime1()}}</p>
<p>computed:{{currentTime2}}</p>
</div>
<!--导入vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<!--导入axios-->
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
var vm=new Vue({
el:'#app',
data: {
message :"helloworld"
},
methods: {
currentTime1:function () {
return Date.now();//返回个时间戳
}
},
computed: { //计算属性 methods 和computed 的方法名不建议同名 同名时 method的优先级更高
currentTime2:function () {
return Date.now();//返回个时间戳
}
}
});
</script>
</body>
</html>
7.2 内容分发 slot
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
</head>
<body>
<div id="vue">
<todo>
<todo-title slot="todo-title" :title="title"></todo-title>
<todo-items slot="todo-items" v-for="item in todoItems" :item="item" ></todo-items>
</todo>
</div>
<script type="text/javascript">
//slot: 插槽
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>"
});
var vm = new Vue({
el:"#vue",
data:{
title:"秦老师系列课程",
todoItems:['java','linux','python']
}
});
</script>
</body>
</html>
7.3 自定义事件内容分发
vue.component组件不能直接删除vue实例下的属性,前端可以通过methods里的自定义方法通过绑定元素删除vue的属性,组件通过this.emit()
(‘自定义事件名’, 参数)分发调用前端的自定义方法删除vue实例的元素
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--view层,模板-->
<div id="vue">
<todo>
<todo-title slot="todo-title" :title="title_text"></todo-title>
<todo-items slot="todo-items" v-for="(item,index) in todoItems"
:item_p="item" :index_p="index" v-on:remove="removeItems(index)" :key="index"></todo-items>
</todo>
</div>
<!--1.导入Vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script type="text/javascript">
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>'
});
//这里的index,就是数组的下标,使用for循环遍历的时候,可以循环出来!
Vue.component("todo-items",{
props:["item_p","index_p"],
template:"<li>{{index_p+1}}------{{item_p}} <button @click='remove_methods'>删除</button></li>",
methods:{
remove_methods:function (index) {
//this.$emit 自定义事件分发
this.$emit('remove',index);
}
}
});
var vm = new Vue({
el:"#vue",
data:{
title_text:"秦老师系列课程",
todoItems:['java','linux','python']
},
methods:{
removeItems:function(index){
console.log("删除了"+this.todoItems[index]+"OK");
this.todoItems.splice(index,1);
}
}
});
</script>
</body>
</html>