vue 学习 01 —— 基本语法
vue 学习 02 —— vue-cli项目、Webpack、vue-router
vue 学习 03 —— ElementUI
Vue
Vue(读音 /vjuː/,类似于 view)是一套用于构建用户界面的渐进式框架,发布于2014年2月。与其他大型框架不同,Vue被设计为自底向上逐层应用。Vue的核心库只关注视图层(HTML、CSS、JS),不仅易于上手,还便于与第三方库(如vue-router:跳转、vue-resource:通信、vuex:管理)或既有项目整合。
官网:https://cn.vuejs.org/v2/guide/
MVVM模式的实现者
在MVVM架构中,不允许数据和视图直接通信,只能通过ViewModel来通信,而ViewModel就是定义了一个Observer观察者。
ViewModel能观察到数据的变化,并对视图对应的内容进行更新,同时它还能监听到视图的变化,能通知数据发送改变。简单点说,就是当数据变化后,界面上就会及时改变。
1、新建一个文件夹vue/vue-first
2、用IDEA打开这个文件
3、新建文件 chapter-1/demo1.html
4、编写代码
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
{{message}}
div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js">script>
<script>
let vm = new Vue({
el:"#app",
//model层 数据,JS中{}表示一个对象,[]表示数组
data:{
message:"hello,vue"
}
})
script>
body>
html>
5、打开页面,可直接修改内容。
说明:在没有刷新页面的情况下,我们完成了页面数据的修改。以前如果想要修改一般是通过DOM来操作标签的内容,现在Vue利用ViewModel将数据和视图双向绑定,当数据被修改时,视图也会即时改变。
前面我们已经创建了第一个Vue应用,看起来和Thymeleaf 模板引擎很像,数据和DOM已经建立了关联,所有东西都是响应式的,界面可以实时更新。
我们还能使用v-bind来绑定元素
<html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="app">
<span v-bind:title="message">鼠标悬停试试~span>
div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js">script>
<script>
let vm = new Vue({
el:"#app",
//model层 数据
data:{
message:"hello,vue"
}
})
script>
body>
html>
这种v-bind
带有前缀v-
的指令,都属于Vue提供的。该指令是将这个元素节点(span)的title
和Vue的实例message
绑定。
我们可以再去浏览器的JavaScript控制台,输入app.message=“新内容”,将title的值改变。
效果:
就是判断语句,效果直接看代码。
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue判断语句title>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js">script>
head>
<body>
<div id="app">
<h1 v-if="ok">YESh1>
<h1 v-else>NOh1>
div>
<script type="text/javascript">
// 创建好一个对象Vue,绑定至元素app(#app是ID选择器)
let vm = new Vue({
el:'#app',
data:{
ok: true
}
});
script>
body>
html>
效果:
下面演示下v-else-if
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue判断语句title>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js">script>
head>
<body>
<div id="app">
<h1 v-if="type==='A'">Ah1>
<h1 v-else-if="type==='B'">Bh1>
<h1 v-else="type==='C'">Ch1>
div>
<script type="text/javascript">
// 创建好一个对象Vue,绑定至元素app(#app是ID选择器)
let vm = new Vue({
el:'#app',
data:{
type: 'A'
}
});
script>
body>
html>
效果:
遍历指令:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue循环语句title>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js">script>
head>
<body>
<div id="app">
<li v-for="item in items">
{{item.message}}
li>
div>
<script type="text/javascript">
let vm = new Vue({
// 绑定至元素app(#app是ID选择器)
el:'#app',
//数据是一个对象(花括号表示一个对象{})
data: {
//对象中有一个数组(方括号表示数组[])
items: [
//数组有三个元素,每个元素都是对象。对象内容是字符串
{message: 'Java'},
{message: '前端'},
{message: '运维'}
]
}
});
script>
body>
html>
效果:
v-on可将元素绑定到事件上。
<html lang="en" xmlns:v-on="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>绑定事件title>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js">script>
head>
<body>
<div id="app">
<button v-on:click="method1">按钮button>
div>
<script>
let vm = new Vue({
el: '#app',
data: {
message: '这是一条消息'
},
//所有的方法要写在methods对象中
methods: {
//方法名为method1的效果是 弹出一个对话框,对话框内容来自message
method1: function () {
alert(this.message);
}
}
});
script>
body>
html>
效果:
Vue.js是一个MVVM框架,能双向绑定,即当数据变化时视图也会相应变化。
我们可以使用v-model
对、
标签进行双向绑定。
注意:v-model会忽略标签的value、checked、selected的初始值,它总是根据Vue实例里的data属性值来确定。
<html lang="en" xmlns:v-on="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>双向绑定title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js">script>
head>
<body>
<div id="app">
<div>
<input type="text" v-model="message"/> {{message}}
div>
<div>
性别:
<input type="radio" name="sex" value="男" v-model="sex">男
<input type="radio" name="sex" value="女" v-model="sex">女<br>
选中的性别:{{sex}}
div>
<div>
下拉框:
<select v-model="select">
<option value="" disabled>--请选择--option>
<option>Aoption>
<option>Boption>
<option>Coption>
select>
选中的值:{{select}}
div>
div>
<script>
let vm = new Vue({
el: '#app',
data: {
message: '该内容会及时改变',//input value的默认内容
sex: '女',//radio 默认选中女性
select: '',//select 默认是第一个内容,即 请选择
}
});
script>
body>
html>
效果:
组件(Component)是 Vue.js 最强大的功能之一。
组件可以扩展 HTML 元素,封装可重用的代码。
组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的应用的界面都可以抽象为一个组件树:
注册一个全局组件语法格式如下:
Vue.component(tagName, options)
tagName 为组件名,options 为配置选项。注册后,我们可以使用以下方式来调用组件:
<tagName>tagName>
在实际开发中并不会用以下方式开发组件,而是采用vue-cli创建.vue模板文件的方式,下面只是为了便于理解什么是组件。
<html lang="en">
<head>
<meta charset="UTF-8">
<title>组件title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js">script>
head>
<body>
<div id="app">
<component v-for="item in items" v-bind:param1="item">component>
div>
<script>
/** 定义一个Vue组件:
* 标签名是component(不要用驼峰命名),模板(内容)是template,形式参数props(用于接收实参)
*/
Vue.component("component",{
props: ['param1'],
template: '{{param1}} '
});
let vm = new Vue({
el: '#app',
data: {
items: ["Java", "前端", "运维"]
}
});
script>
body>
html>
效果:
Axios是一个开源的可以用在浏览器端和NodeJS的异步通信框架,她的主要作用就是实现Ajax异步通信,其特点如下:
GitHub:
中文文档:http://www.axios-js.com/
由于Vue.js
是一个视图层框架,且其作者(尤雨溪)严格遵守Soc(关注度分离原则),因此Vue.js
并不包含Ajax的通信功能,为了解决这个问题,其作者单独开发了一个名为vue-resource
的插件,但在Vue 2.0后停止了维护并推荐使用Axios框架。一般不会用jQuery,因为它操作Dom太频繁了。
菜鸟教程:https://www.runoob.com/vue2/vuejs-ajax-axios.html
{
"name":"love似baby",
"url": "http://baidu.com",
"page": "1",
"isNonProfit":"true",
"address": {
"street": "天安门",
"city":"北京",
"country": "中国"
},
"links": [
{
"name": "B站",
"url": "https://www.bilibili.com/"
},
{
"name": "4399",
"url": "https://www.4399.com/"
},
{
"name": "百度",
"url": "https://www.baidu.com/"
}
]
}
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Axiostitle>
<script src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.1/axios.min.js">script>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js">script>
head>
<body>
<div id="app">
<div>{{info.name}}div>
<div>{{info.address.street}}div>
<div>{{info.links.name}}div>
div>
<script type="text/javascript">
let vm = new Vue({
el:'#app',
//注意这里的data是函数
data () {
return{
info: null
}
},
//钩子函数
mounted(){
axios
.get('./data.json')//通过GET方式请求
.then(response=>(this.info = response.data))//response.data将JSON数据给info(对象)
.catch(function (error) { // 请求失败处理
console.log(error);
});
}
})
script>
body>
html>
效果:
计算属性的重点就是属性,它首先是一个属性且具有计算能力,这里的计算就是个函数。简单的说,它就是一个能够将计算结果缓存起来的属性。
下面进行演示:写两个方法,一个在methods里,一个在computed里。调用时,methods里的是作为方法,所以需要括号,而computed里的是计算属性,本质是属性,所以不用括号。
同时,computed里的是一种缓存,最后的演示效果中,我们反复调用,它不会更新值。当我们对其进行更改后,它会刷新。(类似MyBatis的缓存,进行update后,值就会改变)
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js">script>
head>
<body>
<div id="app">
<div>{{currentTime1()}}div>
<div>{{currentTime2}}div>
div>
<script type="text/javascript">
let vm = new Vue({
el:'#app',
data: {
message: "hello, vue"
},
methods: {
currentTime1: function () {
return new Date().toLocaleString();//返回当前时间戳
}
},
//计算属性【这里面的方法不能和methods的重名,会优先调用methods的】
computed: {
currentTime2: function () {
return new Date().toLocaleString();//返回当前时间戳
}
}
})
script>
body>
html>
效果:
结论
调用方法时,每次都需要进行计算,这就会产生系统开销。如果结果是不经常变化的,就可以考虑用缓存。计算属性的主要特性就是将不经常变化的计算结果缓存起来,节约系统开销。
在Vue.js
中,通过
插槽来承载分发内容的出口,可以应用在组合组件的场景中。
<html lang="en">
<head>
<meta charset="UTF-8">
<title>插槽title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js">script>
head>
<body>
<div id="app">
<my>
<my-title slot="my-title" v-bind:param1="title" >my-title>
<my-items slot="my-items" v-for="item in myItems" v-bind:param2="item">my-items>
my>
div>
<script type="text/javascript">
//slot:插槽,实现动态拔插,相当于slot位置可以插入任意其他的内容。
Vue.component("my",{
template:
'' +
' '+
''
+
' ' +
'' +
''
});
//下面两个组件插入到上面的组件的两个插槽里
Vue.component("my-title", {
props: ['param1'],
template:
'{{param1}}'
});
Vue.component("my-items", {
props: ['param2'],
template:
'{{param2}} '
});
let vm = new Vue({
el:'#app',
data: {
title: '书籍列表',
myItems: ['Java', 'Python', 'Linux']
},
})
script>
body>
html>
效果:
父组件是使用 props 传递数据给子组件,但如果子组件要把数据传递回去,就需要使用自定义事件!
我们可以使用 v-on 绑定自定义事件, 每个 Vue 实例都实现了事件接口(Events interface),即:
$on(eventName)
监听事件$emit(eventName)
触发事件另外,父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。
<html lang="en">
<head>
<meta charset="UTF-8">
<title>插槽title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js">script>
head>
<body>
<div id="app">
<my>
<my-title slot="my-title" v-bind:param1="title" >my-title>
<my-items slot="my-items" v-for="(item,index) in myItems"
v-bind:param2="item" v-bind:param3="index" v-on:remove="removeItems(index)">my-items>
my>
div>
<script type="text/javascript">
//slot:插槽,实现动态拔插,相当于slot位置可以插入任意其他的内容。
Vue.component("my",{
template:
'' +
' '+
''
+
' ' +
'' +
''
});
//下面两个组件插入到上面的组件里
Vue.component("my-title", {
props: ['param1'],
template: '{{param1}}'
});
Vue.component("my-items", {
//param2:各个书籍项目,param3:接收的下标index
props: ['param2', 'param3'],
//绑定按钮到remove函数,即点击按钮就会触发remove函数。
template: '{{param3}}--{{param2}} ',
//单独的data函数,不会影响到vm对象的data
data:function(){
return{
counter: 0
}
},
methods: {
//remove函数会触发removeItems函数(事件)
remove: function () {
console.log("触发了remove()"+(this.counter++));
//props:父组件传数据给子组件,子组件传给父组件: $emit(eventName) 触发事件、 $on(eventName) 监听事件
this.$emit('remove');
}
}
});
let vm = new Vue({
el:'#app',
data: {
title: '书籍列表',
myItems: ['Java', 'Python', 'Linux']
},
methods: {
removeItems: function (index) {
console.log("删除了"+this.myItems[index]);
this.myItems.splice(index,1);//一次删除一个元素
}
}
})
script>
body>
html>
效果: