MVVM
model(js对象data)、view(dom模板代码)、viewmodel(vue实例),ViewModel负责把Model的数据同步到View,还负责把View的修改同步回Model,实现数据-视图分离,数据不会影响视图。
框架优缺点
优点:上手快;组件化开发,提供方便的指令,可以快速构建复杂的交互式应用;vue是单页面应用加快了访问速度和提升用户体验。
缺点:需要利用大量工具包来开发,实际很重;组件多,调试困难
css写法
vue组件中style没有特殊说明就是全局样式,一般都需要局部样式使用以下两种方法
// 第一种
<style scoped>
/* 本地样式 */
</style>
// 第二种
<template>
<button :class="[$style.button, $style.buttonClose]">X</button>
</template>
<!-- 使用 CSS Modules -->
<style module>
.button {
border: none;
border-radius: 2px;
}
.buttonClose {
background-color: red;
}
</style>
样式穿透
/deep/
双向绑定
(1) 定义: 数据变化视图会自动更新,视图变化数据也会更新
(2) 原理: 数据劫持 + 发布订阅者模式
(3) 实现:采用Object.defineProperty()对数据进行劫持来监听数据变化,并通过getter/setter方法对数据进行读写。其次vue通过发布订阅者模式,维护了一个订阅者数组,当数据发生改变时,vue会通知所有订阅者进行更新,因此当用户在页面上进行修改时。Vue会更新对应的数据,并通知所有订阅者更新视图,同时当数据发生变化时,Vue也会更新对应视图,通过这样的机制,Vue实现了双向绑定
(4) 订阅者是一个概念,它是用于管理更新视图的对象,当数据发生变化时,Vue会通知所有的订阅者进行更新。每一个挂载到视图上的组件或者每一个watcher都可以被看作是一个订阅者,他们订阅了某一个数据的变化,并等待数据发生变化时进行更新,订阅者是Vue实现双向数据绑定的关键组成部分
数据代理
通过一个对象obj2代理对另一个对象obj1中属性x的操作,在vue中,就是把_data中的属性直接放到vm上,是通过vm对象来代理data对象中的属性,好处就是方便操作data
v-model、v-bind
1、v-bind是单向绑定,用来绑定数据和属性以及表达式,数据只能从data流向页面。:
2、v-model是双向绑定,数据能从data流向页面,也能从页面流向data。
3、v-bind可以给任何属性赋值(包括绑定class样式),v-model只能给表单类,也就是具有value属性的元素进行数据双向绑定,注意,v-model不能修饰表达式
compute属性和watch属性
compute:有缓存,不用多次读取,所依赖的数据变化时才重新执行计算属性,method没有缓存要多次读取
watch:监视属性变化时,回调函数handler自动调用,监视属性必须存在,可以开启深度监视
区别:计算属性不能开启异步任务,监视属性可以开启异步任务
绑定class和style样式
用:class :style绑定样式 数组写法,对象写法,字符串写法
v-if v-show
v-if 指令会动态地创建或移除 DOM 元素
v-show display:none 控制元素的显示与隐藏
v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。因此:
如果需要非常频繁地切换,则使用 v-show 较好
如果在运行时条件很少改变,则使用 v-if 较好
v-for key v-for="(p,index) in person" :key="index/p.id"v-for="(val,k) in object" 可以遍历数组对象字符串
会出现的问题:key是vue内部在用的,用index作为key会错乱,用p.id唯一标识不会乱,这是虚拟dom在对比时数组顺序打乱,就出现顺序错乱的问题,没有key会自动用index作为key则顺序可能会乱并开销很大
key的原理:初始数据生成虚拟dom,虚拟dom转为真实dom,用户在真实dom中输入,数据进行更新后,根据新数据生成新虚拟dom,新虚拟dom和之前的真实dom进行对比,一一对比key相同,值不相同则更新,值相同则不更新,对比过后转成新真实dom
更新数组会出现的问题:
this.arr[0]="***"这种修改方式vue监测不到
监测数据的原理:vue在做数据代理之前,加工了data,加了个observer对象,对数据进行getter,setter,深度监视,vue中有set方法,就是方便开发者有新的数据需求的时候也能响应也有gettersetter vm.$set(),Vue.set();vue监测数组时,数组里的数据是没有gettersetter的所以改数组的数据时可能会监测不到,vue中有7个数组方法可以被监视到pop push shift unshift splice sort reverse,vue底层将这些方法包装了一下不是Array原型对象上的方法
自定义指令:
this是window
钩子函数bind inserted update
经典自定义指令:v-debounce(按钮点击防抖) v-lazyload(图片懒加载) v-test(用户名校验) v-resize(和echarts结合实现图表自适应)https://www.cnblogs.com/zbbk/p/16722606.html
<template>
<div class="box">
<div ref="zhex" v-resize="resize" style="width:40%;height:100%;bakcground:pink;">
</div>
</div>
</template>
<script>
import * as echarts from 'echarts'
export default {
name: '',
data() {
return {
opt:null
}
},
mounted() {
this.zhexchartInit()
},
directives:{
resize:{
bind(el,binding){
let width=""
let height=""
function isResezi(){
const style = document.defaultView.getComputedStyle(el);
if(width!==style.width||height!==style.height){
binding.value() // 关键
}
width = style.width
height = style.height
}
el.__vueSetInterval__ = setInterval(isResezi,300)
},
unbind(el){
clearInterval(el.__vueSetInterval__)
}
}
},
methods: {
resize(){
console.log('changed---')
this.myChart.clear()
this.myChart.setOption(this.opt)
},
// 折线图表
zhexchartInit() {
this.myChart = echarts.init(this.$refs.zhex)
this.opt = {
xAxis: {
type: 'category',
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
},
yAxis: {
type: 'value'
},
series: [
{
data: [120, 200, 150, 80, 70, 110, 130],
type: 'bar',
showBackground: true,
backgroundStyle: {
color: 'rgba(180, 180, 180, 0.2)'
}
}
]
}
this.myChart.setOption(this.opt)
}
},
components: {}
}
</script>
<style scoped lang="less">
.box{
width:100%;
height:100vh;
background:peachpuff;
p{font-size:30px;}
}
</style>
生命周期
beforeCreate 在组件实例被创建之初、组件的属性⽣效之前被调用
created 在组件实例已创建完毕。此时属性也已绑定,但真实 DOM 还未⽣成,$el 还不可⽤
beforeMount 在组件挂载开始之前被调⽤。相关的 render 函数⾸次被调⽤
mounted 在 el 被新建的 vm.$el 替换并挂载到实例上之后被调用
beforeUpdate 在组件数据更新之前调⽤。发⽣在虚拟 DOM 打补丁之前
updated 在组件数据更新之后被调用
beforeDestory 在组件销毁前调⽤
destoryed 在组件销毁后调⽤,组件自定义事件不生效了,原生dom事件还是生效但无响应式
activited 在组件被激活时调⽤(使用了 <keep-alive> 的情况下)
deactivated 在组件失活时调⽤(使用了 <keep-alive> 的情况下)
VueComponent.prototype.__proto__===Vue.prototype
残缺版vue不包含模板解析器,所以用render来完成
组件通信
- 父组件给子组件传方法,形参为子值,子组件props接收这个函数把值给父组件
- 父组件给子组件v-on绑定自定义事件,子组件中用$emit触法这个自定义事件并传值给父组件
- 父组件ref获取子组件用this.$refs.son.$on()绑定自定义事件然后做上一步,$off解绑事件
- new Vue的beforcreate中定义全局事件总线Vue.prototype.$bus=this,this.$bus.$on()。。。
- 消息订阅与发布pubsub.js用库实现,类似全局事件总线的方式写
- webstorage,window,vuex
- .sync v-model
- $parent / $children 通过$parent和$children就可以访问组件的实例
$nextTick:在下一次dom更新结束后执行回调,例如可以获取input焦点this.$nextTick(function(){})
slot插槽
默认插槽:在组件中放一个h5标签时例如img,放一个<slot></slot>; 具名插槽:当有多个插槽时,slot属性name="***",img属性slot="***"; 作用域插槽:子传父,父中写<template scope="data">h5标签</template>
vuex
vue插件,实现任意组件间数据共享,以下为工作原理图
actions(处理逻辑判断) mutations(单纯的方法) state(数据) getters(对state加工)为配置项属于store之下的对象{},commit dispatch 为方法
mapstate mapgetters 能映射state和getters中的数据,mapmutations能生成commit方法 mapactions 能生成dipatch方法,,,涉及namespaced:true,需要注意
前端路由原理
前端路由的核心,就在于改变视图的同时不会向后端发出请求;而是加载路由对应的组件。vue-router是vue的插件,专门实现SPA应用,它组件映射到路由, 然后渲染出来的。
登录流程
- 点击登录,账号和密码调用后端的登录接口,后端比对,比对错误,返回错误信息给前端
- 比对成功,给前端返回一个token值,前端拿到token存储在localstorage和vuex中并跳转页面登录成功,放在vux中是因为vuex数据存在内存中读取更快且响应式,放在localstorage时是因为防止vux数据丢失可以从这里获取数据,两者结合
- 前端每次跳转需具备登录状态的页面时,都需要判断token是否存在,如果不存在就跳转到登录页面,存在就正常跳转,利用路由来鉴权
keep-alive两个新钩子
模式:Hash模式、History模式。默认Hash模式
hash模式 : #后面是路由路径,特点是前端访问,不会经过服务器 window.location.hash
history模式:正常的/访问模式,特点是后端访问,任意地址的变化都会访问服务器
vue项目打包生成下面然后去服务器上部署
npm run build