Vue.js 介绍
- vue.js是当下很火的一个JavaScript MVVM库,它是以数据驱动和组件化的思想构建的。相比于Angular.js,Vue.js提供了更加简洁、更易于理解的API,使得我们能够快速地上手并使用Vue.js。
什么是MVVM模式?
- ViewModel是Vue.js的核心,它是一个Vue实例。Vue实例是作用于某一个HTML元素上的,这个元素可以是HTML的body元素,也可以是指定了id的某个元素。
当创建了ViewModel后,双向绑定是如何达成的呢?
- 从View侧看,ViewModel中的DOM Listeners工具会帮我们监测页面上DOM元素的变化,如果有变化,则更改Model中的数据.
- 从Model侧看,当我们更新Model中的数据时,Data Bindings工具会帮我们更新页面中的DOM元素。
下面展示一下栗子:
- vue的使用是从一个对象开始的,先创建一个js的对象
new Vue
-
el
查找标签的参数 -
data
存放数据的参数 -
methods
封装函数的参数
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<!--这是我们的View-->
<div id="app">
{{ message }}
</div>
</body>
<script src="js/vue.js"></script>
<script>
// 这是我们的Model
var exampleData = {
message: 'Hello World!'
}
// 创建一个 Vue 实例或 "ViewModel"
// 它连接 View 与 Model
new Vue({
el: '#app',
data: exampleData
})
</script>
</html>
- 使用Vue的过程就是定义MVVM各个组成部分的过程的过程。
- 1:定义View
- 2:定义Model
- 3:创建一个Vue实例或者
ViewModel
,它用于连接View和Model
- 在创建Vue实例时,需要传入一个选项对象,选项对象可以包含
数据
、挂载元素
、方法
、模生命周期钩子
等等。
- 1.选项对象的el属性指向
View
,el: '#app'
表示该Vue实例将挂载到<div id="app">...</div>
这个元素;data属性指向Model
,data: exampleData
表示我们的Model是exampleData对象 - 2.Vue.js有多种数据绑定的语法,最基础的形式是·
文本插值(也叫大胡子)
,使用一对大括号语法,在运行时{{ message }}
会被数据对象
的message属性
替换,所以页面上会输出”Hello World!”。
下面举一个双向绑定栗子:
- MVVM模式本身是实现了双向绑定的,在Vue.js中可以使用
v-model
指令在表单元素上创建双向数据绑定。
<!--这是我们的View-->
<div id="app">
<p>{{ message }}</p>
<input type="text" v-model="message"/>
</div>
- 可以把上面的代码,给它包含在< body>标签中进行一下运行,能更深刻的理解一下
v-model
指令的双向绑定。
Vue.js的常用指令
什么是vue.js的指令呢?
- Vue.js的指令是以
v-开头的
,它们作用于HTML元素,指令提供了一些特殊的特性,将指令绑定在元素上时,指令会为绑定的目标元素添加一些特殊的行为,我们可以将指令看作特殊的HTML特性
v-if指令
v-if
是条件渲染指令,它根据表达式的真假来删除和插入元素,它的基本语法如下:
v-if="content"
v-if取值为false不是隐藏 是删除标签(销毁标签)
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<div id="app">
<h1>Hello, Vue.js!</h1>
<h1 v-if="yes">Yes!</h1>
<h1 v-if="no">No!</h1>
<h1 v-if="age >= 25">Age: {{ age }}</h1>
<h1 v-if="name.indexOf('fe') >= 0">Name: {{ name }}</h1>
</div>
</body>
<script src="vue.js"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
yes: true,
no: false,
age: 28,
name: 'fe_cow'
}
})
</script>
</html>
- 大家能想象出来下面的页面哪些数据不会出现么 ?
- 我们需要注意的是:yes, no, age, name这4个变量都来源于Vue实例选项对象的data属性。
- 数据的
yes
属性为true,所以“YES!”会被输出。 - 数据的
no
属性为false,所以”No!”不会被输出。 - 运算式
age >= 25
返回true,所以”Age: 28”会被输出。 - 运算式
name.indexOf('fe') >= 0
返回false,所以”Name: fe_cow”会被输出。
v-if指令是根据条件表达式的值(v-if='xxx')来执行元素的插入或者删除行为。
v-else指令
- 可以用
v-else
指令为v-if
或v-show
添加一个“else块”。v-else
元素必须立即跟在v-if
或v-show
元素的后面——否则它不能被识别。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<div id="app">
<h1 v-if="age >= 25">Age: {{ age }}</h1>
<h1 v-else>Name: {{ name }}</h1>
<h1>---------------------分割线---------------------</h1>
<h1 v-show="name.indexOf('1') >= 0">Name: {{ name }}</h1>
<h1 v-else>Sex: {{ sex }}</h1>
</div>
</body>
<script src="vue.js"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
age: 28,
name: 'fe_cow',
sex: 'cow'
}
})
</script>
</html>
v-else
元素是否渲染在HTML中,取决于前面使用的是v-if
还是v-show
指令。v-if
为true,后面的v-else
不会渲染到HTML;v-show
为true,但是后面的v-else
仍然可以渲染到HTML中。
v-show 指令
v-show
也是条件渲染指令,和v-if指令不同的是,使用v-show
指令的元素始终会被渲染到HTML,它只是简单地为元素设置CSS的style属性。- 下面我们举个栗子:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<div id="app">
<h1>Hello, Vue.js!</h1>
<h1 v-show="yes">Yes!</h1>
<h1 v-show="no">No!</h1>
<h1 v-show="age >= 25">Age: {{ age }}</h1>
<h1 v-show="name.indexOf('fe') >= 0">Name: {{ name }}</h1>
</div>
</body>
<script src="vue.js"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
yes: true,
no: false,
age: 28,
name: 'fe_cow'
}
})
</script>
</html>
- 可能有同学会发现,这不是更上面的
v-if
没有什么区别么?指示命令换成了v-show
- 打开浏览器(chrome)按F12,找到Elements,找到你内容的标签,查看没有展现出来的代码变成了
<h1 >No!</h1>
,发现跟上面的v-if
的区别了吧。 - 如果一个标签要么显示要么隐藏 为了
提高代码执行效率
可以用v-show
,但是如果是多个标签
之前切换显示隐藏只能用v-if。
v-for指令
v-for
指令基于一个数组渲染一个列表,它和JavaScript的遍历语法相似:
- v-for:列表和字典
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="js/vue.js"></script>
</head>
<body>
<!-- v-for: 列表 和 字典 -->
<div id="app">
<ul>
<!-- i就是各个数据 -->
<li v-for="i in mylist"> {{ i }}</li>
</ul>
<!-- 下标、数据 -->
<!-- ()书写两个临时变量,第一个表示数据,第二个表示下标 -->
<ul>
<li v-for="(i, j) in mylist">{{j+1}}、{{ i }}</li>
</ul>
<ul>
<!-- 只有一个临时变量表示的是value值 -->
<li v-for="i in mydict">{{ i }}</li>
</ul>
<ul>
<!-- 如果小括号写两个临时变量:第一个是value值,第二个是key值 -->
<li v-for="(i, j) in mydict">{{ j }}:{{i}}</li>
</ul>
</div>
<script>
var vm = new Vue({
el:'#app',
data:{
mylist: ['邪不压正1', '邪不压正2', '邪不压正3'],
mydict: {'name':'laowang', 'age':38}
}
})
</script>
</body>
</html>
- 我们在选项的
data属性
中定义了一个mylist数组
,mydicct字典
,然后在#app元素
内使用v-for
遍历mylist数组和mydict字典。数组可以输出索引
,字典也可以输出键值
,这点跟python中拆包
很像。
v-bind指令
- v-bind指令:
控制html内容
和控制html属性
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="js/vue.js"></script>
</head>
<body>
<!-- 数据显示的方式:控制html内容 控制html属性 -->
<div id="app">
<div>{{ num }}</div>
<div>{{ str }}</div>
<div>{{ num + 1}}</div>
<div>{{ str.split('').reverse().join('') }}</div>
<!-- 三元运算符或三元表达式 条件?条件成立的命令:条件不成立的命令 -->
<div>{{ bool?'成立':'不成立' }}</div>
<!-- 完整写法v-bind:html属性 化简写法 :html属性 -->
<!-- v-xxx : 都是vue的指令:具有特殊功能的语法规则 -->
<a v-bind:href="url1" class="box">控制html属性href</a>
<a :href="url2">控制html属性href 淘宝</a>
</div>
<script>
var vm = new Vue({
el:'#app',
data:{
num:1,
str:'abcdefg',
bool:false,
url1:'http://www.baidu.com',
url2:'http://www.taobao.com'
}
})
</script>
</body>
</html>
绑定class html属性
- 将v-bind指令也可以绑定class html属性, 如果
isclass1
是true的话,就会绑定class1
这个类。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="app">
<!-- 对象(存到vm对象中,直接标签身上写) 和 数组 -->
<!-- 取值是true添加这个类,否则不添加 -->
<div :class="{class1:isclass1, class2:isclass2}">1111111111111</div>
<div :class="myobject1">222222222</div>
<!-- 数组 -->
<div :class="[myclass3, myclass4]">333333</div>
<!-- ***** 三元运算符 -->
<div :class="[isclass2?'aa':'bb']">44444444</div>
</div>
<script>
var vm = new Vue({
el:'#app',
data:{
isclass1:true,
isclass2:false,
myobject1:{
active:false,
current:true
},
myclass3:'class3',
myclass4:'class4'
}
})
</script>
</body>
</html>
v-on指令
v-on
指令用于给监听DOM事件,它的用语法和v-bind是类似的,例如监听< a>元素的点击事件:
- < a v-on:click=”doSomething”>
- 有两种形式调用方法:绑定一个方法(让事件指向方法的引用),或者使用内联语句。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<div id="app">
<p><input type="text" v-model="message"></p>
<p>
<!--click事件直接绑定一个方法 没有参数后面就不需要跟小括号-->
<button v-on:click="greet">Greet</button>
</p>
<p>
<!--click事件使用内联语句 hi 是参数传入进去 有参数就有小括号-->
<button v-on:click="say('Hi')">Hi</button>
</p>
</div>
</body>
<script src="js/vue.js"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
message: 'Hello, Vue.js!'
},
// 在 `methods` 对象中定义方法
methods: {
greet: function() {
// // 方法内 `this` 指向 vm
alert(this.message)
},
say: function(msg) {
alert(msg)
}
}
})
</script>
</html>
v-bind和v-on的缩写
- Vue.js为最常用的两个指令
v-bind
和v-on
提供了缩写方式。v-bind指令可以缩写为一个冒号
,v-on指令可以缩写为@符号
。
<!--完整语法-->
<a href="javascripit:void(0)" v-bind:class="activeNumber === n + 1 ? 'active' : ''">{{ n + 1 }}</a>
<!--缩写语法-->
<a href="javascripit:void(0)" :class="activeNumber=== n + 1 ? 'active' : ''">{{ n + 1 }}</a>
<!--完整语法-->
<button v-on:click="greet">Greet</button>
<!--缩写语法-->
<button @click="greet">Greet</button>
v-model 表单数据绑定
- 每个表单的
name
代表的是key,value
代表输入的值。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="js/vue.js"></script>
</head>
<body>
<!-- 表单数据:双向数据绑定:数据从html中来到vue,又可以从vue传递到html中 -->
<div id="app">
<input type="text" v-model="txt">
<div>{{ txt }}</div>
<select v-model="sel">
<option value="0">北京</option>
<option value="1">上海</option>
<option value="2">广州</option>
</select>
<div>{{sel}}</div>
<!-- 单选框 -->
<input type="radio" value="nan" v-model="rad">男 <input type="radio" value="nv" v-model="rad">女
<div>{{ rad }}</div>
</div>
<script>
var vm = new Vue({
el:'#app',
data:{
txt:'请输入用户名',
sel:0,
rad:'nv'
}
})
</script>
</body>
</html>
Vue中的样式绑定:
- 第一种方式 Vue中的class
对象
绑定:
!this.xxxx :取反的意思
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue中class对象绑定</title>
<script src="js/vue.js"></script>
<style>
.activated{
color: red;
}
</style>
</head>
<body>
<div id="app">
<div @click="handleDivClick"
:class="{activated: isActivated}">
hello world
</div>
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
isActivated: false
},
//!this.isActivated 取反的意思
methods: {
handleDivClick: function () {
this.isActivated = !this.isActivated
}
}
})
</script>
</body>
</html>
- 第二种方式 Vue种class中
数组
:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue中class数组绑定</title>
<script src="js/vue.js"></script>
<style>
.activated{
color: red;
}
</style>
</head>
<body>
<div id="app">
<div @click="handleDivClick"
:class="[activated, activatedOne]">
hello world
</div>
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
activated: '',
activatedOne: 'activated-one'
},
// 三元表达式? 如果this.activated不为空字符串的时候,就给它变成空
methods: {
handleDivClick: function () {
this.activated = this.activated === 'activated'? '':'activated'
}
}
})
</script>
</body>
</html>
- 第三种方式:通过style对象和数组来表达:
- 还可以在style数组中给它添加一个样式:
:style="[styleObj, {fontSize:'20px'}]"
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue中style 对象和数组绑定</title>
<script src="js/vue.js"></script>
<style>
.activated{
color: red;
}
</style>
</head>
<body>
<div id="app">
<div @click="handleDivClick"
:style="[styleObj, {fontSize:'20px'}]">
hello world
</div>
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
styleObj: {
color: 'black'
}
},
// 三元表达式? 如果this.activated不为空字符串的时候,就给它变成空
methods: {
handleDivClick: function () {
this.styleObj.color = this.styleObj.color === 'black'? 'red':'black'
}
}
})
</script>
</body>
</html>
Vue中条件渲染:
- 每次循环的时候,循环标签中最好都带有
:key='item.id'
值,会提高性能。 - 当想要修改数组的内容的时候,不能通过修改下边的
vm.list[0] = {id:'111',text:'222'}
执行,应该采用·数组的变异方法:(push,pop,shift,unshift,splice,sort,reverse)
- vm.splice(下标, 删除几条,{新增内容})
- 通过改变数组的
引用
:vm.list = [{},{},{}]
- 通过Vue.set方法:
Vue.set(vm.对象名, 1下标, 5更改的名字)
- 通过Vue的实例:
vm.$set(vm.对象名, 1下标, 5更改的名字)
- template:模板占位符
- 给对象添加数据:
Vue.set
(vm.对象名, “address”,”beijing’) 就可以了- 通过Vue实例方法实现:`vm.$set(vm.对象名, ”address’,’beijing’)
实例生命周期:
- 每个Vue实例在被创建时都要经过一系列的初始化过程——例如,需要设置数据监听、编译模板、将实例挂载到DOM并在数据变化时更新 DOM 等。同时在这个过程中会自动运行一些叫做
生命周期钩子
的函数,我们可以使用这些函数,在实例的不同阶段加上我们需要的代码,实现特定的功能。
beforeCreate:
- 在
实例初始化之后
,数据观测 (data observer)
和event/watcher 事件配置之前
被调用。
created:
- 在
实例创建完成
后被立即调用。在这一步,实例已完成以下的配置:数据观测 (data observer),属性和方法的运算,watch/event 事件回调
。然而,挂载阶段还没开始。
beforeMount:
- 在
挂载开始之前
被调用:相关的render 函数首次
被调用。
mounted:
- 在
实例挂载到dom之后
被调用,可以当成是vue对象的ready方法
来使用,一般用它来做dom的初始化操作
。
beforeDestroy:
- 在
组件被销毁之前
调用。
destroyed:
- 在
组件销毁之后调用
。
beforeUpdate:
- 在
数据发生变化前
调用。
updated:
- 在
数据发生变化后
调用 。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>VUE实例生命周期函数</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="app">
</div>
<script>
// 生命周期函数就是vue实例在某一个时间点会自动执行的函数
var vm = new Vue({
el:'#app',
template:"<div>{{test}}</div>",
data: {
test:'hello word'
},
// 在实例初始化之后调用
beforeCreate: function () {
console.log("beforCreate")
},
//在实例创建完成后立即调用
created: function () {
console.log("created")
},
// 在挂载开始之前被调用 在有template模板的时候不渲染
beforeMount: function(){
console.log(this.$el)
console.log("beforeMount")
},
// 在挂载之后可以调用 在实例中有tempalte模板的时候渲染里面的内容
mounted: function () {
console.log(this.$el)
console.log("mounted")
},
// 在组件被销毁之前它会被执行 在控制台打vm.$destroy()就会执行这俩个方法
beforeDestroy: function () {
console.log("beforeDestroy")
},
// 在组件被销毁之后它会执行
destroyed:function () {
console.log("destroyed")
},
// 在数据被改变之前会执行 在控制台输入: vm.test="dell" beforeUpdate 和 updated就会被调用
beforeUpdate: function () {
console.log("beforeUpdate")
},
// 在数据被改变之后会执行
updated:function () {
console.log("updated")
}
})
</script>
</body>
</html>
模板语法:
- 第一种:插值表达式
{{}}
- 第二种:在 < div v-text=’name’> < /div>
- 第三种:在< div v-html=’name’> < /div>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>模板语法</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="app">
<div>{{name + 'fe_cow'}}</div>
<div v-text="name + 'fe_cow'"></div>
<div v-html="name + 'fe_cow'"></div>
</div>
<script>
var vm = new Vue({
el:'#app',
data: {
name:'fe_cow'
// name:'<h1>fe_cow</h1>'
}
})
</script>
</body>
</html>
计算属性:
- 模板内的表达式非常便利,但是设计它们的初衷是用于简单运算的。在模板中放入太多的逻辑会让模板过重且难以维护。计算属性还有
缓存
机制, 计算属性有返回值
。例如:
- 第一种写法:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>计算属性 computed方法 缓存机制</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="app">
<div>{{fullName}}</div>
<div>{{age}}</div>
</div>
<script>
var vm = new Vue({
el:'#app',
data: {
firstName: 'Fe',
lastName: 'Cow',
age: 27
},
// 计算属性的缓存, 在控制台中打vm.age = 28 可以观察看,并没有走fullName这里,因为fullName中的this.firstName 和 lastName都没有发生改变
computed: {
fullName: function () {
console.log('执行了一次计算')
return this.firstName + this.lastName
}
}
})
</script>
</body>
</html>
- 使用
methods
方法 差值表达式后面有()
也能达到计算属性,但是建议不使用,因为它没有缓存:
- 第二种写法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>计算属性 methods 不建议使用 没有缓存机制</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="app">
<div>{{fullName()}}</div>
<div>{{age}}</div>
</div>
<script>
var vm = new Vue({
el:'#app',
data: {
firstName: 'Fe',
lastName: 'Cow',
age: 27
},
methods: {
fullName: function () {
console.log('执行了一次计算')
return this.firstName + this.lastName
}
}
})
</script>
</body>
</html>
计算属性的setter 和 getter
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>计算属性的setter 和 getter</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="app">
<div>{{fullName}}</div>
<div>{{age}}</div>
</div>
<script>
var vm = new Vue({
el:'#app',
data: {
firstName: 'Fe',
lastName: 'Cow',
age: 27
},
computed: {
// 在控制台打 vm.fullName = 'hello word' 改变了fullName的值,set中的value就会接收到 进行切割,重新给firstName 和 lastName重新赋值
fullName:{
get: function () {
return this.firstName + this.lastName
},
// value set接收到get中 fullName中的值
set: function (value) {
console.log('进入了Set里面')
var arr = value.split(' ')
this.firstName = arr[0]
this.lastName = arr[1]
}
}
}
})
</script>
</body>
</html>
侦听属性:
- 侦听属性的作用是侦听
某属性值的变化
,从而做相应的操作,侦听属性是一个对象
,它的键
是要监听的对象
或者变量
,值一般是函数
,当你侦听的元素发生变化时,需要执行的函数,这个函数有两个形参,第一个是当前值
,第二个是变化后的值
。
- 下面栗子是侦听
data
中的fullName
,如果firstName发生改变,就会调用watch方法,就会改变fullName的值。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>监听属性 watch</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="app">
<div>{{fullName}}</div>
<div>{{age}}</div>
</div>
<script>
var vm = new Vue({
el:'#app',
data: {
firstName: 'Fe',
lastName: 'Cow',
fullName: 'Fe_cow',
age: 27
},
watch: {
firstName:function(){
console.log('执行一次')
this.fullName = this.firstName + this.lastName
},
lastName: function () {
console.log('执行二次')
this.fullName = this.firstName + this.lastName
}
}
})
</script>
</body>
</html>
过滤器:
- Vue.js允许你自定义过滤器,可被用于一些常见的文本格式化。过滤器可以用在两个地方:
双花括号插值
和v-bind 表达式
。
<!-- 在双花括号中 -->
{{ prize | RMB }}
<!-- 在v-bind中 -->
<div v-bind:id="rawId | formatId"></div>
- 过滤器实际上是一个函数,可以在一个组件的选项中定义组件内部过滤器:
filters:定义的是局部变量
:需要在实例内部定义
:
filters:{
RMB:function(value){
if(value=='')
{
return;
}
return '¥ '+value;
}
}
- 或者在创建 Vue 实例之前
全局定义过滤器
: Vue.filter('名字',匿名函数){}:定义全局变量:
Vue.filter('Yuan',function(value){
if(value=='')
{
return;
}
return value+'元';
});
- 总体的栗子如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="js/vue.js"></script>
</head>
<body>
<!-- 作用:格式化文本用的 -->
<div id="app">
<!-- 数据 | 过滤器名字 | 2 |3 -->
<div>{{ price1 | yuan | RMB}}</div>
<div>{{ price2 | yuan | RMB}}</div>
</div>
<div id="box">
<div>{{ price1 | RMB }}</div>
<div>{{ price2 |RMB }}</div>
</div>
<script>
// 全局过滤器:作用于所有对象 -- 要求全局过滤器必须定义再所有对象的上面
// Vue.filter(名字,function(){})
Vue.filter('RMB', function(vals){
if(vals == 0){
return vals
}
return '¥' + vals
})
var box = new Vue({
el:'#box',
data:{
price1:999,
price2:0
}
})
var vm = new Vue({
el:'#app',
data:{
price1:99,
price2:0
},
filters:{
// mingzi:function(){}
yuan:function(vals){
if(vals == 0)
{
return vals
}
return vals +'元'
}
}
})
</script>
</body>
</html>
组件简介:
- 组件系统是Vue.js其中一个重要的概念,它提供了一种抽象,让我们可以使用独立可复用的小组件来构建大型应用,任意类型的应用界面都可以抽象为一个组件树 :
- 组件(Component)是Vue.js最强大的功能之一。组件可以扩展 HTML 元素,封装可重用的代码。所有的 Vue 组件同时也都是 Vue 的实例,所以可接受相同的选项对象 (除了一些根级特有的选项) 并提供相同的生命周期钩子。
组件的创建和注册
- 基本步骤:
- Vue.js的组建的使用有3个步骤:1.创建组件构造器 2.注册组件 3.使用组件。
- 调用
Vue.extend()方法
创建组件构造器。 - 调用
Vue.compoent()方法
注册组件。 - 在
Vue实例
的作用范围内使用组件。 - 下面举一个栗子:
<!DOCTYPE html>
<html>
<body>
<div id="app">
<!-- 3. #app是Vue实例挂载的元素,应该在挂载元素范围内使用组件-->
<my-component></my-component>
</div>
</body>
<script src="js/vue.js"></script>
<script>
// 1.创建一个组件构造器 模板是div标签组成的
var myComponent = Vue.extend({
template: '<div>This is my first component!</div>'
})
// 2.注册组件,并指定组件的标签,组件的HTML标签为<my-component>
Vue.component('my-component', myComponent)
new Vue({
el: '#app'
});
</script>
</html>
理解组件的创建和注册
- 接下来我们用以下几个步骤来理解组件的创建和注册:
- 1.
vue.extend()
是Vue构造器的扩展,调用vue.extend
创建一个组件构造器。 - 2.
vue.extend()
构造器有一个选项对象,选项对象的template
属性用于定义组件要渲染的HTML。 - 3.使用
Vue.component()
注册组件时,需要提供2个参数,第1个参数是组件的标签,第2个参数是组件构造器。 - 4.组件应该挂载到某个Vue实例下,否则它不会生效。
<!DOCTYPE html>
<html>
<body>
<div id="app1">
<my-component></my-component>
</div>
<div id="app2">
<my-component></my-component>
</div>
<!--该组件不会被渲染-->
<my-component></my-component>
</body>
<script src="js/vue.js"></script>
<script>
var myComponent = Vue.extend({
template: '<div>This is a component!</div>'
})
Vue.component('my-component', myComponent)
var app1 = new Vue({
el: '#app1'
});
var app2 = new Vue({
el: '#app2'
})
</script>
</html>
给组件绑定原生事件:
- 在子组件中绑定原生事件:
@click.native="handleClick"
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>给组件绑定原生事件</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="root">
<child @click.native="handleClick"></child>
</div>
<script>
Vue.component('child',{
template: '<div>Child</div>div>'
})
var vm = new Vue({
el:'#root',
methods:{
handleClick:function () {
alert('handleClick')
}
}
})
</script>
</body>
</html>
非父子组件间的传值:
.bus
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>非父子组件间传值(Bus/总线/发布订阅者模式/观察者模式)</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="root">
<child content="Fe"></child>
<child content="cow"></child>
</div>
<script>
Vue.prototype.bus = new Vue()
Vue.component('child',{
// 进行赋值
data: function() {
return {
selfCountent: this.content
}
},
// 把父组件传递过来的参数 进行校验
props: {
content: String
},
template: '<div @click="handleClick">{{selfCountent}}</div>div>',
// 点击子组件触发的事件
methods:{
handleClick: function () {
this.bus.$emit('change', this.selfCountent)
}
},
mounted: function () {
var this_ = this
this.bus.$on('change', function (msg) {
this_.selfCountent = msg
})
}
})
var vm = new Vue({
el:'#root'
})
</script>
</body>
</html>
Vue中的插槽:
- 子组件中,引入新的标签,可以在标签中引入
slot='head'
属性,然后在子组件的template:<slot name='head'></slot>
给插槽占位。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue中的插槽</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="app">
<body-comtent>
<div class="head" slot="head">head</div>
<div class="footer" slot="footer">footer</div>
</body-comtent>
</div>
<script>
Vue.component('body-comtent', {
template:'<div>' +
'<slot name="head"></slot>' +
'<div class="content">content</div>' +
'<slot name="footer"></slot>' +
'</div>'
})
var vm = new Vue({
el:'#app'
})
</script>
</body>
</html>
Vue中的插槽的作用域:
- 应用场景:在子组件中需要使用循环时,父组件控制子组件:
- 1:在子组件中使用循环遍历的时候在slot标签中定义
:item=item
将数据传递给父组件。 - 2:父组件通过
slot-scope="props"
它应该定义在tempalte
标签中。 - 3:父组件在使用的时候{{props.item}}就可以将子组件中的循环数据,传递到父组件中。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue中的插槽作用域</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="app">
<body-comtent>
<template slot-scope="props">
<h1>{{props.item}}</h1>
</template>
</body-comtent>
</div>
<script>
Vue.component('body-comtent', {
data:function(){
return{
list: [1,2,3,4]
}
},
template:'<div><ul><slot v-for="item of list" :item=item></slot></ul></div>'
})
var vm = new Vue({
el:'#app'
})
</script>
</body>
</html>
data 必须是函数:
- 组件就是vue的实例,所有vue实例中属性和方法,组件中也可以用,但是data属性必须是一个函数,因为组件会重复使用在多个地方,为了使用在多个地方的组件数据相对独立,data属性需要用一个函数来返回值。
// 定义组件
Vue.component('simple-counter', {
template: '<button v-on:click="counter += 1">{{ counter }}</button>',
data: function () {
return {
counter: 0
}
}
})
// 使用组件
<div id="example-2">
<simple-counter></simple-counter>
<simple-counter></simple-counter>
<simple-counter></simple-counter>
</div>
......
new Vue({
el: '#example-2'
})
组件中< style>标签中 scoped:
- css:
scoped
表示是接下来的css只针对这个组件生效。 - 记住单文组件写js,必须是模块导出的形式:
export default{ }
。 @
符:就是src
文件夹。
全局注册和局部注册
- 调用
vue.component()
注册组件时,组件的注册是全局的,这意味着该组件可以在任意Vue示例下使用。 - 如果不需要全局注册,或者是让组件使用在其它组件内,可以用选项对象的
components
属性实现局部注册。
<!DOCTYPE html>
<html>
<body>
<div id="app">
<!-- 3. my-component只能在#app下使用-->
<my-component></my-component>
</div>
</body>
<script src="js/vue.js"></script>
<script>
// 1.创建一个组件构造器
var myComponent = Vue.extend({
template: '<div>This is my first component!</div>'
})
new Vue({
el: '#app',
components: {
// 2. 将myComponent组件注册到Vue实例下
'my-component' : myComponent
}
});
</script>
</html>
父组件和子组件
- 我们可以在组件中定义并使用其他组件,这就构成了父子组件的关系。
<!DOCTYPE html>
<html>
<body>
<div id="app">
<parent-component>
</parent-component>
</div>
</body>
<script src="js/vue.js"></script>
<script>
var Child = Vue.extend({
template: '<p>This is a child component!</p>'
})
var Parent = Vue.extend({
// 在Parent组件内使用<child-component>标签
template :'<p>This is a Parent component</p><child-component></child-component>',
components: {
// 局部注册Child组件,该组件只能在Parent组件内使用
'child-component': Child
}
})
// 全局注册Parent组件
Vue.component('parent-component', Parent)
new Vue({
el: '#app'
})
</script>
</html>
- 分析一下代码:
- 1.
var Child = Vue.extend(...)
定义一了个Child组件构造器。 - 2.
var Parent = Vue.extend(...)
定义一个Parent组件构造器。 - 3.
components: { 'child-component': Child }
,将Child组件注册到Parent组件,并将Child组件的标签设置为child-component
。 - 4.
template :'<p>This is a Parent component</p><child-component></child-component>'
,在Parent组件内以标签的形式使用Child组件。 - 5.
Vue.component('parent-component', Parent)
全局注册Parent组件。 - 6.在页面中使用标签渲染Parent组件的内容,同时Child组件的内容也被渲染出来。
- Child组件是在Parent组件中注册的,它只能在Parent组件中使用,确切地说:子组件只能在父组件的template中使用。
- 举两个错误的栗子:
- 以子标签的形式在父组件中使用:
- 因为当子组件注册到父组件时,Vue.js会编译好父组件的模板,模板的内容也决定了父组件将要渲染的HTML。
-
<parent-component>…</parent-component>
相当于运行时,它的一些子标签只会被当作普通的HTML来执行。 - 不是标准的HTML标签,会被浏览器直接忽视掉。
- 在父组件标签外使用子组件 :
<div id="app">
<parent-component>
</parent-component>
<child-component>
</child-component>
</div>
组件注册语法糖
- 以上组件注册的方式有些繁琐,Vue.js为了简化这个过程,提供了注册语法糖。
- 使用Vue.component()直接创建和注册组件:
// 全局注册,my-component1是标签名称
Vue.component('my-component1',{
template: '<div>This is the first component!</div>'
})
var vm1 = new Vue({
el: '#app1'
})
Vue.component()
的第1个参数是标签名称
,第2个参数是一个选项对象
,使用选项对象的template属性定义组件模板。使用这种方式,Vue在背后会自动地调用Vue.extend()
。- 在选项对象的components属性中实现局部注册:
var vm2 = new Vue({
el: '#app2',
components: {
// 局部注册,my-component2是标签名称
'my-component2': {
template: '<div>This is the second component!</div>'
},
// 局部注册,my-component3是标签名称
'my-component3': {
template: '<div>This is the third component!</div>'
}
}
})
使用scrip或template标签:
- 尽管语法糖简化了组件注册,但在template选项中拼接HTML元素比较麻烦,这也导致了HTML和JavaScript的高耦合性。 庆幸的是,Vue.js提供了两种方式将定义在JavaScript中的HTML模板分离出来。
- 使用
< script>
标签
<!DOCTYPE html>
<html>
<body>
<div id="app">
<my-component></my-component>
</div>
<script type="text/x-template" id="myComponent">
<div>This is a component!</div>
</script>
</body>
<script src="js/vue.js"></script>
<script>
// 相当于给template模板定义了scrpt标签,通过id进行一个绑定
Vue.component('my-component',{
template: '#myComponent'
})
new Vue({
el: '#app'
})
// template选项现在不再是HTML元素,而是一个id,Vue.js根据这个id查找对应的元素,然后将这个元素内的HTML作为模板进行编译
</script>
</html>
- 使用< script>标签时,
type指定为text/x-template
,意在告诉浏览器这不是一段js脚本,浏览器在解析HTML文档时会忽略< script>标签内定义的内容。 - 使用
< template>
标签 - 如果使用
<template>
标签,则不需要指定type属性。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<div id="app">
<my-component></my-component>
</div>
<template id="myComponent">
<div>This is a component!</div>
</template>
</body>
<script src="js/vue.js"></script>
<script>
Vue.component('my-component',{
template: '#myComponent'
})
new Vue({
el: '#app'
})
</script>
</html>
- 在理解了组件的创建和注册过程后,我建议使用
组件的el和data选项
- 传入Vue构造器的多数选项也可以用在
Vue.extend()
或Vue.component()
中,不过有两个特例:data
和el
。 - Vue.js规定:在定义组件的选项时,
data
和el
选项必须使用函数。
使用Props
- 组件实例的作用域是孤立的。这意味着不能并且不应该在子组件的模板内直接引用父组件的数据。可以使用 props 把数据传给子组件。
props基础示例:
- 下面的代码定义了一个子组件my-component,在Vue实例中定义了data选项。
var vm = new Vue({
el: '#app',
data: {
name: 'keepfool',
age: 28
},
components: {
'my-component': {
template: '#myComponent',
props: ['myName', 'myAge']
}
}
})
- 如果我们想使父组件的数据,则必须先在子组件中定义props属性,也就是
props: ['myName', 'myAge']
这行代码。 - 定义子组件的HTML模板:
<template id="myComponent">
<table>
<tr>
<th colspan="2">
子组件数据
</th>
</tr>
<tr>
<td>my name</td>
<td>{{ myName }}</td>
</tr>
<tr>
<td>my age</td>
<td>{{ myAge }}</td>
</tr>
</table>
</template>
- 将父组件数据通过已定义好的props属性传递给子组件:
<div id="app">
<my-component v-bind:my-name="name" v-bind:my-age="age"></my-component>
</div>
- 在子组件中定义prop时,使用了camelCase命名法。由于HTML特性不区分大小写,camelCase的prop用于特性时,需要转为 kebab-case(短横线隔开)。例如,在prop中定义的myName,在用作特性时需要转换为my-name。
- 在父组件中使用子组件时,通过一下语法将数据传递给子组件:
<child-component v-bind:子组件prop="父组件数据属性"></child-component>
prop的绑定类型
单向绑定
- 既然父组件将数据传递给了子组件,那么如果子组件修改了数据,对父组件是否会有所影响呢?
- 我们将子组件模板和页面HTML稍作更改:
<div id="app">
<table>
<tr>
<th colspan="3">父组件数据</td>
</tr>
<tr>
<td>name</td>
<td>{{ name }}</td>
<td><input type="text" v-model="name" /></td>
</tr>
<tr>
<td>age</td>
<td>{{ age }}</td>
<td><input type="text" v-model="age" /></td>
</tr>
</table>
<my-component v-bind:my-name="name" v-bind:my-age="age"></my-component>
</div>
<template id="myComponent">
<table>
<tr>
<th colspan="3">子组件数据</td>
</tr>
<tr>
<td>my name</td>
<td>{{ myName }}</td>
<td><input type="text" v-model="myName" /></td>
</tr>
<tr>
<td>my age</td>
<td>{{ myAge }}</td>
<td><input type="text" v-model="myAge" /></td>
</tr>
</table>
</template>
- 修改了子组件的数据,没有影响父组件的数据。
- 修改了父组件的数据,同时影响了子组件。
- prop默认是单向绑定:当父组件的属性变化时,将传导给子组件,但是反过来不会。这是为了防止子组件无意修改了父组件的状态 。
双向绑定
- 可以使用
.sync
显式地指定双向绑定,这使得子组件的数据修改会回传给父组件。
<my-component v-bind:my-name.sync="name" v-bind:my-age.sync="age"></my-component>
单次绑定
- 可以使用
.once
显式地指定单次绑定,单次绑定在建立之后不会同步之后的变化,这意味着即使父组件修改了数据,也不会传导给子组件
<my-component v-bind:my-name.once="name" v-bind:my-age.once="age"></my-component>
数据交互:
- vue.js没有集成
ajax功能
,要使用ajax功能
,可以使用vue官方推荐的axios.js库来做ajax的交互
。
axios完整写法:
axios({
method: 'post',
url: '/user/12345',
data: {
firstName: 'Fred',
lastName: 'Flintstone'
}
});
- axios请求的写法也写成
get方式
后post方式
。
执行get请求:
-
.then就是请求成功
、.catch就是请求失败
- 有两种写法,可以用
params
来进行传参。
// 为给定 ID 的 user 创建请求
// then是请求成功时的响应,catch是请求失败时的响应
axios.get('/user?ID=12345')
// .then 就是请求成功
.then(function (response) {
console.log(response);
})
// .catch就是请求失败
.catch(function (error) {
console.log(error);
});
// 可选地,上面的请求可以这样做
axios.get('/user', {
params: {
ID: 12345
}
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
执行post请求:
- 里面的参数就是key, value形式。
axios.post('/user', {
firstName: 'Fred',
lastName: 'Flintstone'
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
ES6语法
- ES6是JavaScript语言的新版本,它也可以叫做ES2015,之前学习的JavaScript属于ES5,ES6在它的基础上增加了一些语法,ES6是未来JavaScript的趋势,而且vue组件开发中会使用很多的ES6的语法,所以掌握这些常用的ES6语法是必须的 。
变量声明let和const
- let和const是新增的声明变量的开头的关键字,在这之前,变量声明是用var关键字,这两个关键字和var的区别是,它们声明的变量没有预解析,let和const的区别是,
let声明的是一般变量
,const申明的常量
,不可修改
。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script>
// alert(num1)
var num1 = 1
num1 = 10
// let const
// alert(num2)
let num2 = 2
num2 = 20
// alert(num3)
const num3 = 3 // 常量:不能修改值的变量
num3 = 30
</script>
</head>
<body>
</body>
</html>
箭头函数:
- 可以把箭头函数理解成
匿名函数
的第二种写法,箭头函数的作用是可以在对象中绑定this
,解决了JavaScript中this指定混乱的问题。 var fn3(函数名) = (参数) => {命令}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script>
// function fn1(a, b){
// var rs = a + b
// alert(rs)
// }
// fn1(1, 2)
var fn2 = function(a, b){
var rs = a + b
alert(rs)
}
// fn2(1, 2)
// var fn3 = (参数) => {命令}
var fn3 = (a, b) => {
var rs = a + b
alert(rs)
}
// fn3(1, 2)
// 一个参数写法
var fn4 = a =>{
alert(a)
}
// fn4(1)
// 没有参数写法
var fn5 = () => {
alert('ok')
}
fn5()
</script>
</head>
<body>
<!-- 作用:修正this指向问题bug -->
<!-- 箭头函数是从匿名函数改写而来 -->
</body>
</html>
对象的简写
- javascript对象在ES6中可以做一些简写形式,了解这些简写形式,才能方便我们读懂一些在javascript代码中简写的对象。
- 下面的栗子:’laowang’的name和’laowang2’的name, key和value相等时,可以保留一个
name
单词。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script>
// var laowang = {
// name:'laowang',
// age:38
// }
var name = 'laowang'
var age = 38
// var laowang2 = {
// name:name,
// age:38
// }
// es6如果遇到k和v的值相等,省略只保留一个单词也可以
var laowang2 = {
name,
age:38
}
alert(laowang2.name)
alert(laowang2.age)
</script>
</head>
<body>
</body>
</html>
模块导入import和导出export
- javascript之前是没有模块的功能的,之前做js模块化开发,是用的一些js库来模拟实现的,在ES6中加入了模块的功能,和python语言一样,python中一个文件就是一个模块,ES6中,
一个js文件就是一个模块
,不同的是,js文件中需要先导出(export)后
,才能被其他js文件导入(import)
。
// model.js文件中导出
var person = {name:'tom',age:18}
export default {person}
// index.js文件夹中导入
import person from 'js/model.js'
// index.js中使用模块
person.name
person.age
/*
上面导出时使用了default关键字,如果不使用这个关键字,导入时需要加大括号:
import {person} from 'js/model.js'
*/
页面结构说明:
- 1.index.html 首先加载的首页面
- 2.main.js 在加载main.js 文件
- 3.App.vue 路由
- 4.各个组件
- 总结就是:
- 整个项目是一个主文件
index.html
,index.html中会引入src文件夹
中的main.js
,main.js中会导入顶级单文件组件App.vue
,App.vue中会通过组件嵌套或者路由来引用components文件夹中
的其他单文件组件
。
组件嵌套:
- 将单文件组件组合在一起有两种方式,一种是嵌套方式,一种用路由的方式。嵌套的方式代码如下:
下图示中,假设组件A中要嵌入组件B。
`<template>
// 在A组件中使用B组件
<B_zujian></B_zujian>
</template>
<script>
// 先导入B组件,其中'@'表示src目录,组件后的vue扩展名可以省略
import B_zujian from '@/components/B_zjian'
export default{
name:'A_zujian',
data:function(){
return {
iNum:0
}
},
// 接着在components属性选项中注册
components:{
B_zujian
}
}
</script>`
路由:
- 可以通过路由的方式在一个组件中加载其他组件,要使用路由功能,需要在
main.js
中先导入路由的包
,然后在组件对象中还需要包含它。
import router from './router'
new Vue({
.....
router
})
- 组件中通过路由标签来加载其他的路由:
- 有简写的办法:
<!-- 路由标签 -->
<router-view></router-view>
<!-- 简写成下面一个标签的形式: -->
<router-view/>
- 路由标签里面加载哪个组件呢?在router文件中的index.js文件中设置:
import Vue from 'vue'
import Router from 'vue-router'
// 导入对应组件 '@' 表示src文件夹
import MainList from '@/components/MainList'
import UserList from '@/components/UserList'
import UpDate from '@/components/UpDate'
// 使用路由模块的固定写法
Vue.use(Router)
// path为'/'表示路由默认加载的组件
// 这些路由默认设置的是App.vue中的路由标签加载的组件
export default new Router({
routes: [
{
path: '/',
name: 'MainList',
component: MainList
},
{
path: '/user',
name: 'UserList',
component: UserList
},
{
path: '/update',
name: 'UpDate',
component: UpDate
}
]
})
- 通过链接可以切换路由标签里面对应的组件,链接的地址是上面index.js文件中定义的path值,不过链接标签是
"router-link"
,链接地址用'to'来定义
:
<router-link to="/">内容</router-link>
<router-link to="/user">内容</router-link>
- 链接地址中可以传递参数,格式如下:
// name对应的是路由中定义的一个path对应的name属性
<router-link :to='{name:"UpDate",params:{code:item.code}}'>
- 有时候需要在组件的js中跳转页面,也就是改变路由,改变路由有下面这些方式:
// 当前页面重新加载
this.$router.go('/user');
// 跳转到另外一个路由
this.$router.push({path:'/user'});
// 获取当前的路由地址
var sPath = this.$route.path;
数据请求及跨域:
数据请求:
- 数据请求使用的是ajax,在
vue中使用的axios.js
,这个文件可以在index.html文件中引入
,也可以作为模块导入,在main.js中导入这个模块
,然后将它绑定在Vue类的原型上:
import axios from 'axios'
Vue.prototype.axios = axios
- 重点:
在组件的js代码中使用axios
:
this.axios({......})
跨域请求:
- vue的自动化工具提供了开发的服务器,我们在这个服务器环境下开发,改动代码可以马上更新显示,错误了还有代码提示,非常方便,但是,如果我们组件中需要数据,而且数据在另一个服务器环境下运行,我们就需要跨域请求数据,vue工具中可以使用代理来跨域请求,设置的方法是:在项目的
config文件夹中
,打开index.js
,在proxyTable
一项中设置:
- ’/apis’
自定义的代理名
- target
代理的服务器
- changeOrigin
是否允许跨域请求
- pathRewrite
匹配首个页面
// 'http://localhost:7890' 表示的是要跨域请求的地址
// 如果请求的地址是:'http://localhost:7890/index_data'
// 在请求时就可以写成: '/apis/index_data'
'/apis': {
target: 'http://localhost:7890',
changeOrigin: true,
// 我们是以index开头,所以给它清空就好
pathRewrite: {
'^/apis': ''
}
}
杂文:
- vue监听回车执行的函数
@keyup.enter.native
- 弹性:
type="flex"
justify="space-between" // 留有空白的意思
:gutter="20" // gutter的实现方式是设置el-col的style
- label 元素内点击文本,就会触发此控件。就是说,当用户选择该标签时,浏览器就会自动将焦点转到和标签相关的表单控件上。