一、MVVM概念
Model(数据模型)、View(ui组件)、ViewModel(view和model进行交互)
在MVVM架构下,View 和 Model 之间并没有直接的联系,而是通过ViewModel进行交互,Model 和 ViewModel 之间的交互是双向的, 因此View 数据的变化会同步到Model中,而Model 数据的变化也会立即反应到View 上。
ViewModel 通过双向数据绑定把 View 层和 Model 层连接了起来,而View 和 Model 之间的同步工作完全是自动的,无需人为干涉,因此开发者只需关注业务逻辑,不需要手动操作DOM,不需要关注数据状态的同步问题。
二、vue生命周期
beforeCreate() { // 这是我们遇到的第一个生命周期函数,表示实例完全被创建出来之前,会执行它
// console.log(this.msg)
// this.show()
// 注意: 在 beforeCreate 生命周期函数执行的时候,data 和 methods 中的 数据都还没有没初始化
},
created() { // 这是遇到的第二个生命周期函数
// console.log(this.msg)
// this.show()
// 在 created 中,data 和 methods 都已经被初始化好了!
// 如果要调用 methods 中的方法,或者操作 data 中的数据,最早,只能在 created 中操作
},
beforeMount() {
// 这是遇到的第3个生命周期函数,表示 模板已经在内存中编辑完成了,但是尚未把 模板渲染到 页面中
// console.log(document.getElementById('h3').innerText)
// 在 beforeMount 执行的时候,页面中的元素,还没有被真正替换过来,只是之前写的一些模板字符串
},
mounted() {
// 这是遇到的第4个生命周期函数,表示,内存中的模板,已经真实的挂载到了页面中,用户已经可以看到渲染好的页面了
// console.log(document.getElementById('h3').innerText)
// 注意: mounted 是 实例创建期间的最后一个生命周期函数,当执行完 mounted 就表示,实例已经被完全创建好了,此时,如果没有其它操作的话,这个实例,就静静的 躺在我们的内存中,一动不动
},
// 接下来的是运行中的两个事件
beforeUpdate() {
// 这时候,表示 我们的界面还没有被更新【数据被更新了吗? 数据肯定被更新了】
/* console.log('界面上元素的内容:' + document.getElementById('h3').innerText)
console.log('data 中的 msg 数据是:' + this.msg) */
// 得出结论: 当执行 beforeUpdate 的时候,页面中的显示的数据,还是旧的,此时 data 数据是最新的,页面尚未和 最新的数据保持同步
},
updated() {
console.log('界面上元素的内容:' + document.getElementById('h3').innerText)
console.log('data 中的 msg 数据是:' + this.msg)
// updated 事件执行的时候,页面和 data 数据已经保持同步了,都是最新的
},
beforeDestory(){
//实例销毁之前调用
//切换路由(当前路由不使用缓存)可以调用这个生命周期
},
destoroyed(){
//离开页面执行可以调用,通常用来离开页面后销毁一些监听事件和定时函数
//当前路由使用 缓存,离开当前路由不会直接调用 beforeDestroy 和 beforeDestroy 销毁,需要使用路由钩子函数主动的调用
},
三、vue数据双向绑定
3.1、数据双向绑定原理:
采用数据劫持结合发布者-订阅者模式的方式,通过 Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应监听回调。当把一个普通 Javascript 对象传给 Vue 实例来作为它的 data 选项时,Vue 将遍历它的属性,用 Object.defineProperty() 将它们转为 getter/setter。用户看不到 getter/setter,但是在内部它们让 Vue 追踪依赖,在属性被访问和修改时通知变化。
vue的数据双向绑定 将MVVM作为数据绑定的入口,整合Observer,Compile和Watcher三者,通过Observer来监听自己的model的数据变化,通过Compile来解析编译模板指令(vue中是用来解析 {{}}),最终利用watcher搭起observer和Compile之间的通信桥梁,达到数据变化 —>视图更新;视图交互变化(input)—>数据model变更双向绑定效果。
input、textarea、option等。
所谓的双向绑定是指Vue实例属性与视图之间的绑定,修改其中一方另一方也会随之跟着变化;所以插值表达式也算是数据的双向绑定;
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
<div id="app">
<input type="text" id="txt">
<p id="show">
</p>
</div>
</body>
<script type="text/javascript">
var obj = {}
Object.defineProperty(obj, 'txt', {
get: function() {
return obj
},
set: function(newValue) {
document.getElementById('txt').value = newValue document.getElementById('show').innerHTML = newValue
}
}) document.addEventListener('keyup', function(e) {
obj.txt = e.target.value
})
</script>
</html>
3.2、数据单向绑定
:class :style 等
四、vue常用指令
4.1、v-for,循环指令
key 一定要具有唯一性,提高渲染性能,简单理解为vue渲染数据,找到指定的数据进行渲染,数据变更了就渲染,没有变更的不渲染。
* v-for尽量不和v-if同时使用
4.2、v-bind,绑定指令
<div :class="{isActive:show}"></div>
<div :style="{width:100px}"></div>
<a :href="url"></a>
<div :text='getText()'>test</div>
<div :text='obj'>test</div>
<div :text='array'>test</div>
稍微对比一下,我们不难发现,计算属性和上面的各种功能是一样的,但是在字符串拼接的情况下,使用计算属性的好处是分离了,不在html中写逻辑。所以计算属性是更推荐的用法。
4.3、v-on,绑定事件指令
DOM事件:
DOM事件 | 功能描述 |
---|---|
onclick | 单击鼠标事件 |
oncontextmenu | 右键菜单 |
ondblclick | 双击事件 |
onmousedown | 鼠标按钮被按下 |
onmouseenter | 鼠标指针移动到元素触发 |
onmouseleave | 鼠标指针离开元素触发 |
onmousemove | 鼠标被移动 |
onmouseover | 鼠标移动到元素上 |
onmouseout | 鼠标从某元素移开 |
onmouseup | 鼠标按键被松开 |
键盘事件:
键盘事件 | 功能描述 |
---|---|
onkeydown | 某个键盘按键被按下 |
onkeypress | 某个键盘按键被按下并松开 |
onkeyup | 某个键盘按键被松开 |
事件修饰符:
<div id="app">
<a href="http://www.qq.com" v-on:click.prevent="btn">腾讯</a>
</div>
4.4、v-if/v-else-if/v-else ,条件判断指令
v-if/v-else :
<div class="test" v-if="true">条件为true</div>
<div class="test" v-else>条件为false</div>
v-if/v-else-if/v-else :
<div class="test" v-if="isShow == 1">条件isShow == 1挂载</div>
<div class="test" v-else-if="isShow == 2">条件isShow == 2挂载</div>
<div class="test" v-else>条件isShow 不等于2 、不等于3时挂载 </div>
4.5、v-model
v-model指令的本质是: 它负责监听用户的输入事件,从而更新数据,并对一些极端场景进行一些特殊处理。同时,v-model会忽略所有表单元素的value、checked、selected特性的初始值,它总是将vue实例中的数据作为数据来源。 然后当输入事件发生时,实时更新vue实例中的数据。
v-model可以用于输入框、select、textarea数据的双向绑定
v-model绑定的数据,输入框输入后,对应的视图没有更新,可使用this.$forceUpdate强制更新视图,因为无法监听到深层的对象或者数组导致的。
4.6、v-once
如果显示的信息后续不需要再修改,使用v-once,这样可以提高性能
<div v-once>{{info}}</div>
7、v-html
绑定html 数据内容,本司使用场景题库富文本编辑数据展示
<div class="test" v-html="content"></div>
修改v-thml内容样式,可以使用.test>>> p{line-height:30px;}
4.8、v-show
判断dom是否显示,注意和v-if的区别
v-show类似于 display:none;和display:block;v-show控制的内容,dom已经挂载页面上;
v-if,dom没有挂载页面中,通过条件判断是否挂载。
五、深入了解组件&自定义组件
5.1、组件注册:全局注册和局部注册
5.2、异步组件&动态组件:
异步组件适用于页面子组件较多或者子组件内容复杂,需要使用按需加载,可以优化页面打开速度。
<confirmDialog :confirmDialogData="confirmDialogData" @dialogEvent="dialogEvent" v-if="confirmShow"></confirmDialog>
components:{
confirmDialog:resolve=>{require(['./confirmDialog'],resolve)},//
},
5.3、父子组件生命周期
渲染过程:父组件挂载完成一定是等子组件都挂载完成后,才算是父组件挂载完,所以父组件的 mounted 在子组件 mouted 之后。
父 beforeCreate -> 父 created -> 父 beforeMount -> 子 beforeCreate -> 子 created -> 子 beforeMount -> 子 mounted -> 父 mounted
子组件更新过程:
影响到父组件:父 beforeUpdate -> 子 beforeUpdate->子 updated -> 父 updated
不影响父组件:子 beforeUpdate -> 子 updated
父组件更新过程:
影响到子组件:父 beforeUpdate -> 子 beforeUpdate->子 updated -> 父 updted
不影响子组件:父 beforeUpdate -> 父 updated
销毁过程:
父 beforeDestroy -> 子 beforeDestroy -> 子 destroyed -> 父 destroyed
5.4、插槽solt
了解应用场景即可,应用场景较窄,不具体列
5.5、组件传值
组件传值方式:父传子(props)、子传父($emit)、子传子(eventBus)
①父传子
<nav :listData="listData"></nav>
props:{
listData:{type:Array},
}
②子传父
子组件通过$emit 可以触发父组件事件传递参数
<nav :listData="listData" @listEvent="listEvent"></nav>
this.$emit('listEvent',data)
③子传子EventBus
就是声明一个全局 Vue 实例变量 EventBus , 把所有的通信数据,事件监听都存储到这个变量上;
类似于 Vuex。但这种方式只适用于极小的项目,原理就是利用 emit 并实例化一个全局 vue 实现数据共享
eventBus,可以实现各个组件之间数据共享,父传子,子传父,子传子都可以使用。小型项目或者局部适用,大型项目使用vuex。
window.eventBus = new Vue();//main.js内定义全局eventBus
eventBus.$emit('eventBusName',data);//A组件传递数据
eventBus.$on('eventBusName',data);//B组件接收数据
eventBus.$off('eventBusName');//移除事件总线
④attrs 和 listeners
attrs 和 listeners应用场景主要是多层组件监听 父组件和子组件以及孙组件之间传值。
<!-- A组件引入B组件 -->
<componentsB :data="data"></componentsB>
<!-- B组件内引入c组件 -->
<componentsC :data="data" v-bind="$attrs" v-on="$listeners"></componentsC>
引入C组件时,绑定$attrs 和 添加$listeners监听C组件的事件;
c组件内部可以通过 this.$emit 传参数给B组件和A组件。
* 建议少使用多层嵌套组件,方便协同开发和维护
⑤provide 和 inject
provide 和 inject 主要为高阶插件/组件库提供用例。并不推荐直接用于应用程序代码中; 并且这对选项需要一起使用;
以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在起上下游关系成立的时间里始终生效;
$refs 父组件调用子组件方法;<br/> 由于vue有$
parent属性可以让子组件访问父组件。但孙组件想要访问祖先组件就比较困难。通过provide/inject可以轻松实现跨级访问祖先组件的数据;
provide 和 inject 绑定并不是可响应的。这是刻意为之的。然而,如果你传入了一个可监听的对象,那么其对象的属性还是可响应的。
//祖先组件
provide(){
return {
'nameObj':{
name:'小布',
},
'age':12,
'city':'郑州'
}
},
//子组件通过inject接收祖先组件传递的值,类似props
inject:['nameObj','age','city'],
六、vue路由
6.1、路由模式
hash模式:在浏览器中符号“#”,#以及#后面的字符称之为hash,用 window.location.hash读取。特点:hash虽然在URL中,但不被包括在HTTP请求中;用来指导浏览器动作,对服务端安全无用,hash不会重加载页面。
history模式:history采用HTML5的新特性;且提供了两个新方法: pushState(), replaceState()可以对浏览器历史记录栈进行修改,以及popState事件的监听到状态变更。
6.2、路由守卫&&路由拦截
导航守卫主要用来通过跳转或取消的方式守卫导航,可用于权限控制,登录判断等;
路由守卫方式:全局路由守卫、单个路由、组件
vue登录权限控制demo
export default new Router({
routes: [{
path: '/',
name: 'home',
component: Home,
meta: {
isLogin: true // 添加该字段,表示进入这个路由是需要登录的
} //路由元
}, {
path: "/login",
name: "login",
component: Login
}]
})
router.beforeEach((to,from,next)=>{
if(to.matched.some(res=>res.meta.isLogin)){//判断是否需要登录
if (sessionStorage['username']) {
next();
}else{
next({
path:"/login",
query:{
redirect:to.fullPath
}
});
}
}else{
next()
}
});
6.3、路由懒加载
路由懒加载是根据按需加载的原则进行加载的,根据不同的场景进行配置:
export default new VueRouter({
routes:
[{
name:
'default',
path: '/',
redirect: '/login',
},
{
name: 'login',
path: '/login',
component: r =>require.ensure([], () =>r(require('@/components/Login/login')), 'login'),
}]
})
router.js不再使用import引入。
6.4、路由缓存(keep-alive)
待补充
6.5、父子路由
// 登录页面
export default new VueRouter({
routes: [{
name: 'default',
path: '/',
redirect: '/examReport',
component: r =>require.ensure([], () =>r(require('@/views/index')), 'index'),
children:[
{
name: 'examReport',
path: '/examReport',
component: r => require.ensure([], () => r(require('@/views/examReport/examReport')),'examReport'),
},
{
name: 'examManage',
path: '/examManage',
component: r => require.ensure([], () => r(require('@/views/examManage/examManage')),'examManage'),
},
]
},
]
})
6.6、动态路由和路由管理
动态路由主要用于复杂的权限控制,后端返回路由数据 点击打开链接
6.7、$router 和 $
route 的区别
$route是“路由信息对象”,包括path,params,hash,query,fullPath,matched,name等路由信息参数。而$
router是“路由实例”对象包括了路由的跳转方法,钩子函数等。
6.8、路由钩子
待补充
6.9、路由传参
<div class="examine" @click="insurance(2)">查看详情</div>
6.9.1、path传参
methods:{
//直接调用$router.push 实现携带参数的跳转,页面刷新参数不丢失
insurance(id) {
this.$router.push({
path: `/particulars/${id}`,
})
}
//对应路由配置
{
path: '/particulars/:id',
name: 'particulars',
component: particulars
}
//目标页面接收参数
this.$route.params.id
6.9.2、params传参
methods:{
//直接调用$router.push 实现携带参数的跳转,页面刷新参数丢失
insurance(id) {
this.$router.push({
name: 'particulars',
params: {
id: id
}
})
})
}
//对应路由配置
{
path: '/particulars',
name: 'particulars',
component: particulars
}
//目标页面接收参数
this.$route.params.id
6.9.3、query传参
methods:{
//直接调用$router.push ,query传参,地址栏后 ?id=1
insurance(id) {
this.$router.push({
name: 'particulars',
query: {
id: id
}
})
})
}
//对应路由配置
{
path: '/particulars',
name: 'particulars',
component: particulars
}
//目标页面接收参数
this.$route.query.id
*不建议使用query和path传递参数,query传参数暴露参数,path传参维护路由文件太麻烦。
七、vuex全局状态
7.1、使用场景
多个视图依赖于同一状态。
来自不同视图的行为需要变更同一状态。
多个组件之间传递参数。
试题篮,购物车等。本司使用场景为试题篮、答题卡,多页面使用同一试题篮,试题篮内容多个页面都可以更新。答题卡制作工具,工具栏切换后,子组件答题卡显示,答题卡下载都需要公用同一状态。
7.2、vuex相关概念
state,驱动应用的数据源;
view,以声明方式将 state 映射到视图;
actions,响应在 view 上的用户输入导致的状态变化。
mutations:通俗的理解mutations,里面装着一些改变数据方法的集合,这是Vuex设计很重要的一点,就是把处理数据逻辑方法全部放在mutations里面,使得数据和视图分离。
const store = new Vuex.Store({
state:{
loading: false,
todoList : [
{id:1,name:'11'},
{id:2,name:'22'},
{id:3,name:'33'},
],
num: 0,
},
mutations:{
setNumIs5(state){
state.num = 5
},
setNumIsWhat(state,payload){
state.num = payload.num
}
},
actions:{ <----- 增加actions属性
setNum(content){ <----- 增加setNum方法,默认第一个参数是content,其值是复制的一份store
return new Promise((resolve)=>{ <----- 返回一个promise,我们模拟一个异步操作,1秒后修改num为5
setTimeout(()=>{
content.commit('setNumIs5')
resolve()
},1000)
})
}
}
})
//以下是调用方法:
async mounted() {
console.log('旧值---'+this.$store.state.num);
await this.$store.dispatch('setNum') <----- actions使用dispatch进行触发,就像mutation使用commit触发一样
console.log('新值---'+this.$store.state.num);
},
actions 和 mutations的区别:
actions类似于mutations,actions提交的是mutation,而不是直接变更state状态。actions可以包含任何异步操作。
action的声明周期就是上面那一块,它在组件里被dispatch到,然后进入action,执行异步操作,异步操作(promise)总有一个结果的,出结果后再决定提不提交mutation。
八、vue数据计算和监听等
8.1、计算属性?
computed用来监控自己定义的变量,该变量不在data里面声明,直接在computed里面定义,然后就可以在页面上进行双向数据绑定展示出结果或者用作其他处理;
computed比较适合对多个变量或者对象进行处理后返回一个结果值,也就是数多个变量中的某一个值发生了变化则我们监控的这个值也就会发生变化,举例:购物车里面的商品列表和总金额之间的关系,只要商品列表里面的商品数量发生变化,或减少或增多或删除商品,总金额都应该发生变化。这里的这个总金额使用computed属性来进行计算是最好的选择
计算属性使用方法:
计算属性内可以完成各种复杂的逻辑,包括运算、函数调用等,最终返回一个结果就可以。计算属性还可以依赖多个vue实例数据,其中任何一个数据变化,计算属性就会重新执行,视图会相应地更新。
<div>{{sum}}</div>
data(){
return{
a:11,
b:12
}
},
computed:{
sum:function(){
return this.a+ this.b;
},
}
计算属性getter和setter
getter是读取,setter是设置。
上述例子,仅使用了computed的getter,setter和getter是相互独立的,并不是触发了setter就一定会触发getter。
export default {
name: 'HelloWorld',
props: {
msg: String
},
data(){
return{
firstName: 'zhang',
lastName: 'san'
}
},
computed: {
fullName: {
// getter
get: function() {
console.log('触发get')
return this.firstName + ' ' + this.lastName
},
// setter
set: function(newValue) {
console.log('触发setter')
// var names = newValue.split(' ')
// this.firstName = names[0]
// this.lastName = names[names.length - 1]
return this.firstName + ' ' + this.lastName
}
}
}
}
8.2、过滤器filter
//过滤器使用方法
{{ 'ok' | globalFilter }}
<div v-bind:data="'ok' | globalFilter" ></div>
{{ message | filterA | filterB }}
filters: {
'multiple': function (value1, value2, value3) {
return value1*value2*value3
}
}
filter:内容格式化,将输入的数据,按照某种规则进行输出,从这一层讲,感觉叫 formatter 可能更合适;
过滤器适合多个同样计算方法的属性的计算;;
过滤器可以定义为全局过滤器,在多个vue实例中使用;;
过滤器可以接收多个参数进行计算;;
过滤器没有缓存机制,每调用一次都会计算一次;;
过滤器相当于定义一个特殊的方法;
8.3、method
method:数据、交互等的逻辑处理,相对 formatter 的功能更纯粹,一般结合“数据驱动”的理念,尽量不直接操作 DOM;
计算属性适合用在单个属性、单个vue实例中使用;
计算属性不能接收参数,只能使用data中定义的变量进行计算;
计算属性有缓存机制,可减少调用次数;
计算属性相当于定义一个变量
//method在插值表达式的使用方法
{{getNum()}}
methods: {
getNum(){
return 1+2;
},
}
8.4、watch监听
8.4.1、监听数据变化
watch:{
//编辑试卷信息
dataName:{
handler(newVal,oldVal) {//handler是监听后,其值是一个回调函数。即监听到变化时应该执行的函数
//newVal 变化后的数据
//oldVal 变化前的数据
},
immediate:true,//是否立即监听,布尔值,立即监听页面初始化即开始监听,注意使用场景
deep:true,//深度监听,布尔值。监听多层对象内部的变化,对象层级过深需要开启。
},
}
8.4.2、监听路由变化
watch:{
'$route.path':function (newVal,oldVal){
if(newVal === '/login'){
console.log('欢迎进入登录页面');
}
if (newVal === '/register') {
console.log('欢迎进入注册页面');
}
}
}
watch:{
$route(to,from){
console.log( to , from )
// to , from 分别表示从哪跳转到哪,都是一个对象
// to.path ( 表示的是要跳转到的路由的地址 eg: /home );
}
}
监听路由变化,不使用立即监听和深度监听
8.4.3、监听vuex数据变化
'$store.state.site': {
handler(newVal,oldVal) {//handler是监听后,其值是一个回调函数。即监听到变化时应该执行的函数
//newVal 变化后的数据
//oldVal 变化前的数据
},
immediate:true,//是否立即监听,布尔值,立即监听页面初始化即开始监听,注意使用场景
deep:true,//深度监听,布尔值。监听多层对象内部的变化,对象层级过深需要开启。
}
8.5、数据计算不同的使用场景
filter常用于对数据进行简单的格式化;
method常用于dom更新频繁的地方,可以进行复杂的数据计算;
computed常用于数据复杂计算,但视图或数据更新不频繁的地方,比如有些数据需要缓存;
8.6、computed 和 watch的区别
8.6.1、computed计算属性
支持缓存,只有依赖数据发生改变,才会重新进行计算
不支持异步,当computed内有异步操作时无效,无法监听数据的变化
computed 属性值会默认走缓存,计算属性是基于它们的响应式依赖进行缓存的,也就是基于data中声明过或者父组件传递的props中的数据通过计算得到的值
如果一个属性是由其他属性计算而来的,这个属性依赖其他属性,是一个多对一或者一对一,一般用computed
如果computed属性属性值是函数,那么默认会走get方法;函数的返回值就是属性的属性值;在computed中的,属性都有一个get和一个set方法,当数据变化时,调用set方法。
8.6.2、侦听属性watch
不支持缓存,数据变,直接会触发相应的操作;
watch支持异步;
监听的函数接收两个参数,第一个参数是最新的值;第二个参数是输入之前的值;
当一个属性发生变化时,需要执行对应的操作;一对多;
监听数据必须是data中声明过或者父组件传递过来的props中的数据,当数据变化时,触发其他操作,函数有两个参数:immediate:组件加载立即触发回调函数执行
deep: 深度监听,为了发现对象内部值的变化,复杂类型的数据时使用,例如数组中的对象内容的改变,注意监听数组的变动不需要这么做。
注意:deep无法监听到数组的变动和对象的新增,参考vue数组变异,只有以响应式的方式触发才会被监听到。
九、axios相关
9.1、POST传参序列化、配置、返回状态监听
//创建请求拦截器
axios.interceptors.request.use((config) => {
if(config.method === 'post') {
config.data = qs.stringify(config.data);
}
return config;
}, (error) => {
return Promise.reject(error);
});
9.2、axios配置超时,header头,baseUrl等
// axios 配置
axios.defaults.timeout = 5000;
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8';
axios.defaults.baseURL = 'http://localhost:8008'
// 返回状态判断 可用于统一返回状态监听,可以封装api请求
axios.interceptors.response.use((res) =>{
if(!res.data.success){
return Promise.reject(res);
} return res;
}, (error) => {
//404等问题可以在这里处理 return Promise.reject(error);
})
9.3、开发环境和生产环境配置接口调用地址
//接口地址配置
if(process.env.NODE_ENV == 'development'){//开发环境
var apiUrl = 'http://59.110.67.15:8085';
}else{
//生产环境
//var apiUrl = 'http://192.168.1.160:8085';
var apiUrl = window.location.protocol+'//' + window.location.host;
}
9.4、请求超时和错误捕捉
可用于捕捉404 403 500 等接口无响应的状态
axios.defaults.timeout = 5000;//配置请求超时时间
//创建 response 拦截器,最好是放在main.js做全局拦截
axios.interceptors.response.use(
response=>{
//to do
return response;
},
error=>{
if(error.message.includes('timeout')){
console.log('请求超时,请重试!');
}
if(error.response){
console.log('请求服务器错误,请重试!');
}
return Promise.reject(error);
}
)
//也可以使用catch捕捉错误
.catch(err=>{
alert(err.message)
})
十、vue性能优化
参照性能优化文档:网站性能优化(点击可打开链接)
十一、其它
11.1、vue修饰符
.lazy
使用了这个修饰符将会从“input事件”变成change事件进行同步
<input type="text" v-model.lazy="message">
.number
number并不是限制用户的输入,而是将用户输入的数据尝试绑定为 js 中的 number 类型
<input type="text" v-model.lazy="message">
.trim
trim可以用来过滤前后的空格
11.2、过渡和动画
单元素/组件的过渡
通过name和enter、leave样式控制动画
<div id="demo">
<button v-on:click="show = !show">
Toggle
</button>
<transition name="fade">
<p v-if="show">hello</p>
</transition>
</div>
<style>
.fade-enter-active, .fade-leave-active {
transition: opacity .5s;
}
</style>
过渡的类名:
在进入/离开的过渡中,会有 6 个 class 切换;
v-enter:定义进入过渡的开始状态。在元素被插入之前生效,在元素被插入之后的下一帧移除。
v-enter-active:定义进入过渡生效时的状态。在整个进入过渡的阶段中应用,在元素被插入之前生效,在过渡/动画完成之后移除。这个类可以被用来定义进入过渡的过程时间,延迟和曲线函数。
v-enter-to:2.1.8 版及以上定义进入过渡的结束状态。在元素被插入之后下一帧生效 (与此同时 v-enter 被移除),在过渡/动画完成之后移除。
v-leave:定义离开过渡的开始状态。在离开过渡被触发时立刻生效,下一帧被移除。
v-leave-active:定义离开过渡生效时的状态。在整个离开过渡的阶段中应用,在离开过渡被触发时立刻生效,在过渡/动画完成之后移除。这个类可以被用来定义离开过渡的过程时间,延迟和曲线函数。
v-leave-to:2.1.8 版及以上定义离开过渡的结束状态。在离开过渡被触发之后下一帧生效 (与此同时 v-leave 被删除),在过渡/动画完成之后移除。
CSS 过渡:
和单元素、组件过渡类似
JavaScript 钩子
<transition
v-on:before-enter="beforeEnter"
v-on:enter="enter"
v-on:after-enter="afterEnter"
v-on:enter-cancelled="enterCancelled"
v-on:before-leave="beforeLeave"
v-on:leave="leave"
v-on:after-leave="afterLeave"
v-on:leave-cancelled="leaveCancelled"
>
<!-- ... -->
</transition>
11.3、vue里data使用return
在大型项目中使用return ,只在当前组件内生效,不会影响其他组件。不适用return包裹的数据会在项目中全局课件,会造成变量污染
export default{
data(){
return {
showLogin:true,
msg: 'hello vue',
user:'',
homeContent: false,
}
},
methods:{
}
}