基础介绍
1.Vue在html中引用的固定格式
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--在body中写相关的Html布局标签 -->
<div> </div>
<!--引入Vue -->
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<script type="text/javascript">
//在script 中创建Vue的实例对象
new Vue ({
el:'#app2',
data: {
}
})
</script>
</body>
</html>
2.Vue的声明式渲染
使用双大括号的形式{{ … }}来把数据渲染进DOM系统 , 举例如下:
<div id="app">
<p>{{msg}}</p>
</div>
<script type="text/javascript">
//在script 中创建Vue的实例对象
new Vue ({
el:'#app',
data: {
msg:20
}
})
</script>
3.Vue基本属性介绍
3.1 “el”
“el” : 提供一个页面上存在的DOM元素来作为挂载目标,DOM元素用使用id,el中写入对应DOM元素的”#+id”就可以和其进行挂载
3.2”data”
“data”用来定义数据,与对应标签中引用到的数据进行绑定
Vue 实例的数据对象。Vue 会递归地把 data 的 property 转换为 getter/setter,从而让 data 的 property 能够响应数据变化。对象必须是纯粹的对象 (含有零个或多个的 key/value 对):浏览器 API 创建的原生对想象,原型上的 property 会被忽略。大概来说,data 应该只能是数据 - 不推荐观察拥有状态行为的对象。
实例创建之后,可以通过 vm.$data
访问原始数据对象。Vue 实例也代理了 data 对象上所有的 property,因此访问 vm.a
等价于访问 vm.$data.a
。并且会自动无时无刻的检测data中的属性,这是Vue默认的检测,不用使用watch也在检测,当data里的数据一变就去页面上更新相关的数据。
3.3 “Methods”
methods 将被混入到 Vue 实例中。可以直接通过 VM 实例访问这些方法,或者在指令表达式中使用。方法中的 this
自动绑定为 Vue 实例。
你可以Vue vm = new Vue
,并使用vm.method()来调用你所定义的函数,或者在指令表达式中使用<Button @click="method"/>
来进行函数的执行
3.4 “watch”
watch可以用来监视某一属性是否发生改变,并在它改变的时候自定义方法来执行回调,并在页面中展示修改后的所有属性值。 它的属性值后面可以跟一个函数体也可以是函数名(函数名的函数在Methods中实现相关函数)。
例如
a: function (val, oldVal) {
console.log('new: %s, old: %s', val, oldVal)
},
// 方法名
b: 'someMethod',
// 该回调会在任何被侦听的对象的 property 改变时被调用,不论其被嵌套多深
c: {
handler: function (val, oldVal) { /* ... */ },
deep: true
},
// 该回调将会在侦听开始之后被立即调用
d: {
handler: 'someMethod',
immediate: true
},
3.5 “computed”
模板内的表达式非常便利,但是设计它们的初衷是用于简单运算的。在模板中放入太多的逻辑会让模板过重且难以维护,所以,对于任何复杂逻辑,你都应当使用计算属性。
例子:实现一个字符串转换成大写
<div id="root">
<h2 v-upper-text="name"></h2>
<h2 v-lower-text="name"></h2>
<h2>{{Uppername}}</h2>
</div>
<script type="text/javascript">
new Vue({
el:'#root',
data:{
name:'hello HELLO'
},
computed:{
Uppername:function () {
return this.name.toUpperCase()
}
},
</script>
由其实际效果可知,功能的实现实际可以使用method来实现,但是二者存在着区别:
不同的是计算属性是基于它们的响应式依赖进行缓存的。只在相关响应式依赖发生改变时它们才会重新求值。这就意味着只要 message
还没有发生改变,多次访问 reversedMessage
计算属性会立即返回之前的计算结果,而不必再次执行函数。
相比之下,每当触发重新渲染时,调用方法将总会再次执行函数。
我们为什么需要缓存?假设我们有一个性能开销比较大的计算属性 A,它需要遍历一个巨大的数组并做大量的计算。然后我们可能有其他的计算属性依赖于 A。如果没有缓存,我们将不可避免的多次执行 A 的 getter!如果你不希望有缓存,请用方法来替代。
Vue指令
1.常见的指令
1.1 v-bind (简写为 “:”)
- 介绍
动态将属性绑定或者一个组件prop到表达式,标签中“”内的值不再是单纯的String,而是一个表达式,具体的值要去到对应的Vue中的data中去找,
如果绑定的是Class或者style的class时,也可以支持数组或对象
在绑定prop时,prop必须在子组件中声明,可以使用修饰符来指定不同的绑定类型
(prop可以查看对应props章节)
- 示例 ```html
`<img :src="'/path/to/images/' + fileName">` 在`v-bind中添加''`单引号内的内容为真实字符串,而不是表达式
<a name="pLQta"></a>
### 1.2 v-on (简写为 "@")
- **介绍**
将事件监听器进行绑定,事件的类型由其参数来决定,它可以去写一个方法,也可以直接把语句写在里面,同时可以在事件上来增加修饰符来实现一定的效果。<br />用在普通元素上时,只能监听原生DOM事件。用在自定义元素组件上时,也可以监听子组件触发的**自定义事件**。
- **修饰符**
- `.stop` - 调用 `event.stopPropagation()`。
- `.prevent` - 调用 `event.preventDefault()`。
- `.capture` - 添加事件侦听器时使用 capture 模式。
- `.self` - 只当事件是从侦听器绑定的元素本身触发时才触发回调。
- `.{keyCode | keyAlias}` - 只当事件是从特定键触发时才触发回调。
- `.native` - 监听组件根元素的原生事件。
- `.once` - 只触发一次回调。
- `.left` - (2.2.0) 只当点击鼠标左键时触发。
- `.right` - (2.2.0) 只当点击鼠标右键时触发。
- `.middle` - (2.2.0) 只当点击鼠标中键时触发。
- `.passive` - (2.3.0) 以 `{ passive: true }` 模式添加侦听器
- **示例**
```html
<!-- 方法处理器 -->
<button v-on:click="doThis"></button>
<!-- 动态事件 (2.6.0+) -->
<button v-on:[event]="doThis"></button>
<!-- 内联语句 event-->
<button v-on:click="doThat('hello', $event)"></button>
<!-- 缩写 -->
<button @click="doThis"></button>
<!-- 动态事件缩写 (2.6.0+) -->
<button @[event]="doThis"></button>
<!-- 停止冒泡 -->
<button @click.stop="doThis"></button>
<!-- 阻止默认行为 -->
<button @click.prevent="doThis"></button>
<!-- 阻止默认行为,没有表达式 -->
<form @submit.prevent></form>
<!-- 串联修饰符 -->
<button @click.stop.prevent="doThis"></button>
<!-- 键修饰符,键别名 当触发对应事件的时候执行onEnter方法 -->
<input @keyup.enter="onEnter">
<!-- 键修饰符,键代码 -->
<input @keyup.13="onEnter">
<!-- 点击回调只会触发一次 -->
<button v-on:click.once="doThis"></button>
<!-- 对象语法 (2.4.0+) -->
<button v-on="{ mousedown: doThis, mouseup: doThat }"></button>
<script type="text/javascript">
new Vue({
el : '#app',
data:{
},
methods:{
//参数根据在标签中指定的时候来定和执行
doThis() {
//方法里要执行的代码内容
}
}
})
1.3 v-model
- 介绍
来进行数据的双向绑定,同时对其控件进行监听,当发生改变时来做出对应变化。例如大概就是在中输入的值可以影响着data中的数据,当data中数据改变的时候,对应的控件中的值也会发生改变。
修饰符
[.lazy](https://cn.vuejs.org/v2/guide/forms.html#lazy)
- 取代input
监听change
事件[.number](https://cn.vuejs.org/v2/guide/forms.html#number)
- 输入字符串转为有效的数字[.trim](https://cn.vuejs.org/v2/guide/forms.html#trim)
- 输入首尾空格过滤
示例
<input v-model="message" placeholder="edit me">
<p>Message is: {{ message }}</p>
2.条件指令
2.1 v-if
- 介绍
根据条件值来进行对应的渲染和操作,如果if表达式内的值为true,则显示,false则不显示。
2.2 v-else-if / v-else
介绍
v-else-if和v-else 都是跟在v-if后来进行使用的,单独使用将不被允许,它的执行顺序和其他语言一样,同样当执行到true的时候,才会将对应的内容进行渲染展示,否则将看不到对应内容。
注意:( v-if / v-else-if / v-else 在表达式为false的时候是将元素销毁,当变为true再重新创立 )举例
<div v-if="type === 'A'">
A
</div>
<div v-else-if="type === 'B'">
B
</div>
<div v-else-if="type === 'C'">
C
</div>
<div v-else>
Not A/B/C
</div>
2.3 v-show
- 介绍
v-show也是通过条件来判断是否渲染展示元素的
注意:( 带有 v-show 条件判断的元素无论为true还是false,元素始终都会保留在DOM中 )
- 举例
<h1 v-show="ok">Hello!</h1>
2.4 v-show 和 v-if
v-if
是“真正”的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。v-if
也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。
相比之下,v-show
就简单得多——不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换。
一 般来说,v-if
有更高的切换开销,而 v-show
有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用 v-show
较好;如果在运行时条件很少改变,则使用 v-if
较好。
3.其他指令
3.1 v-for
- 介绍
v-for同样用在标签中用来对指定的元素进行遍历
遍历的期待对象可以是:Array | Object | number | string | Iterable (2.6 新增)
- 示例
/
v-for的主要用法就是 (自定义元素名 in 需要遍历的对象名字)
例如:
<div v-for="item in array"> <!-- array 就是待遍历的数组或者其他类型,item就是拿到的数组中的值-->
{{ item.text }}
</div>
<li v-for="(p,index) in filterpersons" key="index" //遍历数组
> {{index}}----{{p.name}}----{{p.age}} //p为数组元素,p.name为对象属性值
</li>
<div v-for="(item, index) in items"></div>
<div v-for="(value, key) in object"></div> //遍历对象,将对象中的属性值全部输出
//其中的value为对应具体值,key为对应名称
- key
如果在v-for中指定了key(最好习惯性指定一个)它会基于 key 的变化重新排列元素顺序,并且会移除 key 不存在的元素。
它也可以用于强制替换元素/组件而不是重复使用它。当你遇到如下场景时它可能会很有用:
- 完整地触发组件的生命周期钩子
- 触发过渡
当<transition>
<span :key="text">{{ text }}</span>
</transition>
text
发生改变时,<span>
总是会被替换而不是被修改,因此会触发过渡。3.2 v-text
<span v-text="msg"></span>
<!-- 上下二者是一样的效果-->
<span>{{msg}}</span>
3.3 v-html
<span v-html="msg"></span>
此时在组件中间插入的不再是单纯的文本,而是普通html内容(不会作为vue模板来进行编译),浏览器会将其进行解析并进行展示。
在网站上动态渲染任意 HTML 是非常危险的,因为容易导致 XSS 攻击。只在可信内容上使用 v-html
,永不用在用户提交的内容上。
3.4 v-slot(插槽标签 为vue2.6.0新特性,取代了slot组件)
Vue的生命周期
1.Vue生命周期图
在整个生命周期中,都要以New Vue()为开端,如果连Vue的实例都没有的话,所有的一切都不能谈起。
2.常用的钩子函数
2.1 created()
在实例创建完成后被立即调用。在这一步,实例已完成以下的配置:数据观测 (data observer),property 和方法的运算,watch/event 事件回调。然而,挂载阶段还没开始,$el
property 目前尚不可用。
在这个钩子函数了,可以去做一些自己的初始化操作,
2.2 mounted()
2.3 updated()
当界面刷新的时候回发生回调,执行里面的代码
2.4 activated()
2.5 deactivated()
Vue组件
1.ref和props
ref:可以使用其来访问一个子组件。
1.给组件标签指定ref : <Demo ref="xxxx"/>
, 可以获取到的是组件的实例对象vc
2.给html标签来指定ref:<input ref = "xxxx"/>
, 可以获取到的是真实的DOM节点
3.通过this.$refs
来获取
props:可以是数组或对象,用于接收来自父组件的数据
1.在对一个自定义标签来加入props时候,要去对应的实例对象中去找接收,并且需要自己申明接收,否则是接收不到的(即在脚本文件中添加props:{}并在里面根据需求加入一些限定)
例如:
<School :carname="carName"/>
<!--下面是School里的配置-->
<script>
//Props必须声明接收
export default {
name :'School',
//配置数据
data (){
return {
name: '西安电子科技大学',
address :'陕西省西安市'
}
},
props:{
carname:{
type:String, //接收数据的类型
required:true, //限定该props是否为必填项,设定为true时,若没有加入props时则会抛出异常
default:'哈哈哈' //指定一个默认值,如果Props没有被传入则换做这个值
}
}
在实例对象中进行申明后,并将props传入后,这个数据会直接加载到data中,成为一个在子组件中的数据项。
如果在使用中并不去限制任何东西,则可以使用最简洁的写法:
<script>
export default {
props:['username','age']
}
Vue-router (前端路由)
1.路由介绍
路由器提供了两种机制:路由和转送
- 路由是决定数据包从**来源**到**目的地**的路径
- 转送将**输入端**的数据转移到合适的**输出端**
路由表:
本质是一个映射表,决定了数据包的指向。
2.前端路由、后端路由区分
2.1 后端路由
后端渲染
早期:在服务器接收到发来的url请求时候,会对url路径进行解析来判断你想要访问的是哪一个页面,然后再后面的库中取出(例如JSP、PHP文件),里面会放有html+css+java , java语言主要用来获取数据库中的数据并动态的展示到页面上,后端在完成渲染后,传给浏览器html+css进行展示。
上面这个例子可以看到,在每一个url都会有一个映射关系从而来找到一个对应的文件,取出渲染展示到浏览器。
所以,后端处理URL和页面之间的映射关系的路由就被称为后端路由
2.2 前端路由
前端渲染
前后端分离阶段:随着AJax的出现,逐渐形成后端只负责处理提供数据,不负责其他任何阶段的内容。在用户输入url时候,先再静态资源服务器中拿到对应的html+css+js文件,然后在浏览器中执行js代码,当执行到$.Ajax()的请求时,才会根据接口来调用服务,获取数据,拿到数据后其他js代码再将数据渲染到浏览器中。
浏览器中显示网页中的大部分内容,都是在前端写的js代码中执行,最终渲染出来最终的网页。
SPA(单页富应用)页面阶段:整个页面之后一个html页面。当输入一个url之后,会请求下来一个html+css+js,这个文件在静态资源服务器中只有一个,但里面包含了所有资源。在想要将一整个整合的资源分割开,就需要用来前端路由
前端路由:用来将url映射到整体js文件中的其中部分,并进行渲染展示。
3.router-link
3.1 router的index.js
在使用的时候需要先去到index.js文件中添加路由属性
其中:
- mode:”history” :将使用的方式转变为html5,也就是没有#的情况
- linkActiveClass: 可以在配置中添加该属性并制定一个样式,那它会自动把
router-link-active
中的样式改变 - path:表示一个相对路径,就是在url上显示在后面的名字
localhost:8080/home
- redirect:重定位,当path为给出的路径时候,重定位到redirect后面所给路径
- name:名称
- component:来确定该path的route所对应的Vue组件,从而将相应的东西展示到页面上
3.2router-link
这是一个在使用脚手架的时候,自动帮助建立好的一个全局组件,可以在任意位置调用,如果想要去进行使用,则直接使用这个标签。
其中的属性:
- to: 设定好to属性中的值后,当点击这个标签时,网页会跳转到对应的url下,并根据之前在index.js中配置的Vue进行渲染
- active-class: 当
<router-link>
对应的路由匹配成功时,会自动给当前元素设置一个router-link-active
的class,通过设置active-class
可以修改默认的名称(一般情况下不会修改,使用默认的名称) - tag: 可以指定
<router-link>
之后渲染为什么组件,例如加上tag='li'
就会将其渲染成 - 元素而不是默认的元素
- replace: 不会留下history记录,后退键不能返回到上一个页面中
另一种方式:利用代码来实现对路由的选择,例如:
<script>
methods:{
gotoshouye(){
this.$router.push("/Home")
},
gotoguanyu(){
this.$router.push("/about")
}
}
此方法中的$router
所指的是一整个路由对象,然后调用其push方法,如果想要不能返回则调用其replace
方法即可
4.router-view
也是一个标签<router-view/>
使用其将router-link
渲染好的页面进行展示。
5.动态路由
在开发中通常会运用到动态路由,比如在网页中通常会https://localhost:8080/user/123123
后面的123123就是一般会传输的一个userId
,这个数据可以接收到之后来进行一定的处理,所以要实现这种动态的效果就需要用到动态路由
方法:
1. 在index.js
文件中的子路由的path
下追加user/:roleId
后面的roleId就是可以被动态指定的
2. 在使用<router-link>
的时候将path中前面的user设置为默认字符串,而后面的内容使用{{userid}},来进行数据绑定,后面我们只用对该数据进行更改,那么就可以动态的改变该属性值
3. 在跳到对应的页面时候,想要拿到对应的userid,通过语句this.$route.params.roleId
就可以拿到对应的值了
注意:这里的$route
指的是当前活跃的路由,我们在index.js
里会注册很多路由,这个标签指定的是其中一个活跃的路由。roleId
与前面在index.js
文件中定义在后面的名称相同
6.路由懒加载
就是在需要的时候才进行加载,而不是全部加载。在这个路由被访问到的时候才进行加载。
原因:
- 当打包构建应用的时候,JS包会很大,影响页面的加载
- 我们可以将不同的路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就更加高效了。
懒加载的方式:
方式一:AMD写法
(resolve) => require(['@/views/system/role/authUser'], resolve)
方式二:const ``User ``= ()=>``import``(``"../components/User"``)
7.路由守卫
Promise异步处理
1.什么情况下使用Promise
一般情况下是在有异步操作的时候,使用Promise来对这个异步操作来进行封装.
比如在进行一些请求资源等网路操作的耗时操作的时候,为了在请求时不发生堵塞,就需要用到异步操作,也就类似于多线程。
2.Promise的使用方法
第一种处理形式:
<script>
new Promise((resolve,reject)=>{
setTimeout(()=>{
//操作去请求数据
resolve("data"); //如果请求成功,执行下面的then函数
reject('error data')
},1000) //模仿这是一个耗时操作
}).then(data =>{
console.log(data) //使用请求来的数据进行操作
}).catch(err=>{
console.log(err)
})
第二种处理形式:(直接在then中写两个函数,前者处理正确数据,后者报错)
<script>
new Promise((resolve,reject)=>{
setTimeout(()=>{
//操作去请求数据
resolve("data"); //如果请求成功,执行下面的then函数
reject('error data')
},1000) //模仿这是一个耗时操作
}).then(data =>{
console.log(data)
}, err=>{
console.log(err)
})
第三种处理形式:(链式调用)
(主要应用在想要对拿到的数据进行处理后进行加工并在一次进行异步操作)
<script>
new Promise((resolve,reject)=>{
setTimeout(()=>{
//操作去请求数据
resolve("data"); //如果请求成功,执行下面的then函数
reject('error data')
},1000) //模仿这是一个耗时操作
}).then(data =>{
console.log(data,'第一层的处理') //进行操作
return new Promise( //reject是选择性传入的
resolve(data+'111')
)
}).then((data)=>{
console.log(data,"第二层的处理")
})
其中的resolve
和reject
两个参数都是函数
- 在成功的时候调用
resolve
函数,并进入then
后面的代码块进行处理,如果还有嵌套调用则继续以同样方式执行 - 在失败的时候调用
reject
函数来反应错误信息,并在catch
处拿到错误信息进行打印
3.Promise的all方法
如果当一个操作只有在两个或多个请求都完成的时候才进行执行,则就要用到all
方法。
用法:
/
<script>
Promise.all([
new Promise((resolve, reject) =>{
$.ajax({
url:'url1',
success: data=>{
resolve(data)
}
})
}),
new Promise((resolve, reject) => {
$.ajax({
url:'url2',
success: data=>{
resolve(data)
}
})
})
]).then(results=>{//then中的数据时一个数组,
results[0] //数组第一个位置是第一个请求的数据
results[1] //第二个位置是第二个请求的数据
})
Promise
的all
方法会自动检测两个请求是否都完成,只有两个请求都成功完成,才会执行后面then函数中的内容。