1.插值表达式 {{}}
2.指令
2.1 v-if 、v-else、 v-show、v-else-if
v-if: 在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建,开销较高,在运行时条件很少改变时使用。
v-show:调整css dispaly属性,开销较小,在常频繁地切换时使用
2.2 v-for
数组 v-for="item in items"
加key diff算法高效的更新虚拟DOM
对象 v-for="(value, key, index) in object"
2.3 v-text 、v-html
v-text {{xxx}}取值有个弊端,当网速很慢或javascript出错时,会在页面显示{{xxx}},Vue提供的v-text可以解决这个问题
v-html 用于输出html代码
2.4 v-on
<button v-on:click="add">加分</button>
缩写 <button @click="add">加分</button>
2.5 v-moudle
需要在data中声明初始值
单选 radio 多选 checkbox 下拉 select/option
2.6 v-bind
<img v-bind:src="imgSrc" width="200px">
缩写 <img :src="imgSrc" width="200px">
2.7 v-pre、v-cloak、v-once
v-pre 在模板中跳过vue的编译,直接输出原始值,如果在标签中加入v-pre就不会输出vue中的data值了
v-cloak 在vue渲染完指定的整个DOM后才进行显示。它必须和CSS样式一起使用
[v-cloak] {
display: none;
}
v-once 只显示DOM第一次渲染的值,以后不改变了
生命周期
new vue() 实例化对象 > 初始化生命周期和事件 >
beforeCreate 实例刚被创建还没实例化,做一些初始化操作 > 初始化依赖注入和校验
created 实例已创建,属性已绑定,dom未生成,$el属性不存在,此时可发起网络请求,结束加载动画 >
has 'el' option 存在则继续,不存在则等到vm.$mount(el)继续编译 >
has 'template' option 有则继续编译 render函数首次执行 否则用html
beforeMount 完成虚拟dom,模板已编译,data里的数据和模板生成html,未挂载到页面上 >
給vue实例添加$el成员,并替换掉挂载的dom元素
mounted dom结构完成,可做网络请求 >
beforeUpdate data数据发生变化,触发组件重新渲染,组件发生变化之前,虚拟dom已发生更改 >
重新渲染虚拟dom,并通过diff算法对比vnode节点差异更新真实dom
updated 组件更新之后
beforeDestory 组件销毁之前 > 拆卸观察者、子组件、事件监听者
destoryed 解绑,事件监听器移除,子实例销毁
常用选项
methods
用于html中绑定的方法
methods:{
add(){
}
}
计算属性
对于任何复杂逻辑,都应当使用计算属性
提供的函数将用作 vm.data. 的 getter 函数
计算属性是基于它们的响应式依赖进行缓存的。只在相关响应式依赖发生改变时它们才会重新求值,否则不会重新执行函数
不是响应式依赖不缓存
computed:{
fullName (){
return this.firstName + this.lastName
}
}
计算属性的getter/setter
computed:{
fullName:{
get:function(){
return this.firstName + this.lastName
},
set: function(nameValue){
var names = newValue.split(' ')
this.firstName = names[0]
this.lastName = names[names.length - 1]
}
}
}
侦听器
watch
当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的
watch:{
question:function(newQuestion,oldQuestion){
this.answer = 'Waiting for you to stop typing...'
this.debouncedGetAnswer()
}
}
对引用数据类型监听
watch:{
obj:{
handler(new,old){
执行回调
}
deep:true, 是否进行深度监听
immediate:true 是否初始执行handle函数
},
}
filters过滤器
filters:{
filterA (value){
return value.toUpperCase()
}
}
vue-cli
安装 npm vue-cli -g npm install -g @vue/cli
升级 npm update -g @vue/cli
检查版本 vue -V
初始化项目 vue init <template-name> <project-name>
<template-name>:表示模板名称,vue-cli官方提供的5种模板,一般使用webpack
自动打开浏览器 config>index>autoOpenBrowser属性改为true
vue组件传值 传值取数据
父向子
父 :params=''
子 props:{params:{required:true,type:string}}
子向父
子 @click='$emit('zxf',params)'
父 @zxf='zxfSend' zxfSend(e){}
事件总线
vue事件总线就像所有组件的事件中心,在组件中,我们可以使用 $emit,$on,$off 分别来分发、监听、取消监听事件
全局事件总线创建
// 创建写法1:
let EventBus = new Vue() //vue实例可以作为事件总线
Object.defineProperties(Vue.prototype,{
$bus:{
get(){
return EventBus
}
}
})
// 创建写法2:
Vue.prototype .$bus = new Vue()
全局事件总线操作
this.$bus.$emit('nameOfEvent', { ... pass some event data ...});
this.$bus.$on('nameOfEvent',($event) => {
// ...
})
事件总线
创建一个单独的event-bus.js文件
import Vue from 'vue'
let EventBus = new Vue()
export default EventBus
//事件总线操作
import EventBus from event-bus.js
//发送事件,第二个参数可选
EventBus.$emit("aMsg", params}
import EventBus from event-bus.js
EventBus.$on("aMsg",(msg)=>{
// do something
})
在vue页面销毁时,同时移除EventBus 事件监听
beforeDestroy: function () {
eventBus.$off('add-todo', this.addTodo)
eventBus.$off('delete-todo', this.deleteTodo) //两个参数
},
methods: {
addTodo: function (newTodo) {
this.todos.push(newTodo)
},
deleteTodo: function (todoId) {
this.todos = this.todos.filter(function (todo) {
return todo.id !== todoId
})
}
EventBus.$off() -----------移除当前组件的所有事件监听者
EventBus.$off(param:string)------------移除当前组件对某个事件的所有监听
EventBus.$off(param:string,param)-------移除某个方法对某个事件的监听如:this.addTodo
$parent / $children与 ref
ref:如果在普通的dom元素上使用,引用指向的就是dom元素,如果用在子组件上,引用就是指向组件实例
this.$refs['string']
this.$parent.
this.$children[].
这两种方法的弊端是,无法在跨级或兄弟间通信
$attrs/$listeners
$attrs包含了父作用域中不被prop所识别(且获取)的特性绑定,当一个组件没有声明任何prop时,会包含所有父作用域的绑定,
并通过v-bind='$attrs'传入组件内部,通常配合inheritAttrs选项一起使用
inheritAttrs: false, // 可以关闭自动挂载到组件根元素上的没有在props声明的属性
$listeners包含了父作用域中(不含.native修饰器的)v-on事件监听器,它可以通过v-on='$listeners'传入组件内部
是$emit的偷懒写法
provide与inject 用于父组件向子孙组件传递数据
使用方法
provide在父组件中返回要传给下级的数据,inject在需要使用这个数据的子辈组件或者孙辈等下级组件中注入数据
provide:是一个对象,或者是一个返回对象的函数。里面呢就包含要给子孙后代的东西,也就是属性和属性值。
inject:一个字符串数组,或者是一个对象。属性值可以是一个对象,包含from和default默认值
provide() {
return {
theme: this//方法一:提供祖先组件的实例
};
},
inject: {
theme: {
//函数式组件取值不一样
default: () => ({})
}
}
父组件调用子组件方法
通过 ref
通过 $emit发射事件传事件
通过 $emit/$on
通过 $children[0]
通过总线、vuex、
子组件调用父组件方法
通过 props传函数
通过 $parent
通过 $emit发生事件传信号
通过总线、vuex
vuex
vuex是vue.js应用程序开发的状态管理模式
安装 npm install vuex --save
使用
import Vue from 'vue'
import Vuex from 'vuex' Vue.use(Vuex)
new Vuex.store({
state:{
},
getter:{
}
})
访问数据 this.$store.state.
用计算属性优雅
使用mapState
import {mapState} from 'vuex'
computed:{
...mapState(['name']) //...mapState({aliasName:'name'})
}
vuex的getters,相当于vuex的计算属性,state参数必传
new Vuex.store({
getters:{
getName(state){
}
}
})
this.$store.getters.getName
使用mapGetters
import{mapState,mapGetters} from 'vuex'
computed:{
...mapGetters(['getName'])
}
修改状态 Mutations
new Vuex.store({
Mutations:{
setName(state){
state.name = ''
}
}
})
使用方法 this.$store.commit('setName')
使用mapMutations
import{mapMutations} from 'vuex'
在methods中解构
methods:{
...mapMutations(['setName'])
}
异步修改状态Actions
actions:{
asyncNewName(content){ 可把commit解构出来
return new promise(resolve=>{
setTimeout(()=>{
content.commit('setName')
resolve()
},1000)
})
}
}
使用方法 this.$store.dispatch('asyncNewName',{})
使用mapActions
import {mapActions} from 'vuex'
在methods中解构
moudle 把vuex模块化封装
vue-router
#后hash值得变化,不会导致刷新页面,会触发hashchange
widow.addEventLister('hashChange',update)
引:history 模式,H5提供pushState,replaceState两个API,通过API修改url地址不会发送请求刷新页面。
因为没有#号更加美观,但当用户刷新页面时还是会发送请求,为了避免这种个情况,需要服务端支持,把所有路由重定向到根页面
安装 npm install vue-router --save
import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)
export default new Router({
routers:[
path: '/', //链接路径
name: 'HelloWorld', //路由名称,
component: HelloWorld //对应的组件模板
]
})
路由跳转
通过router-link标签跳转
<router-link :to="{path:'/first',params:{id:1}}">first</router-link>,获取不到参数,路由不能加/:id,否则不能跳转
<router-link :to="{path:'/first',query:{id:1}}">first</router-link>
<router-link :to="{name:'first',params:{id:1}}">first</router-link>
获取参数 this.$route.params.id 路由配置/first/:id 刷新不会消失
<router-link :to="{name:'first',query:{id:1}}">first</router-link>
获取参数 this.$route.query.id 相当于get传参
编程式跳转
this.$router.push()
this.$router.push('/home')
this.$router.push({name:'home'})
this.$router.push({path:'/home'})
this.$router.push({name:'home',query: {id:'1'}})
this.$router.push({path:'/home',query: {id:'1'}})
this.$router.push({name:'home',params: {id:'1'}})
this.$router.replace() (用法同push)
this.$router.go(n)
路由守卫
Vue 路由 导航守卫(全局守卫、路由独享守卫、组件内守卫)
to:即将要进入的目标路由对象
from:当前导航即将要离开的路由对象
next :调用该方法后,才能进入下一个钩子函数(afterEach)
next() 进入管道的下一个钩子
next(false) 中断当前导航,回到from路由对应的地址
next('/') 或者next({path:'/'})跳转到其他路由
next(error) 导航终止,且该错误会传递给router.onError()注册过的回调
全局守卫
router.beforeEach((to,from,next)=>{})
router.beforeResolve((to,from,next)=>{}) 全局解析守卫,路由跳转前,所有组件内守卫和异步路由组件被解析之后触发
router.afterEach((to,from)=>{})
路由守卫
{
path:'first',
name:'first',
component:'first',
beforeEnter:(to,from,next)=>{}
}
组件守卫
beforeRouteEnter(to,from,next){}
beforeRouteUpdate(to,from){} 组件内子路由更新
beforeRouteLeave(to,from){}
面试题汇总
vue修饰符
.lazy 输入框光标离开时才改变 .trim过滤空格
.number 将值转换为数字 先输入数字,只保留数字,先输入字母,number修饰符无效
.stop 阻止冒泡 .capture 由外往内捕获
.prevent 阻止默认事件 .native加在自定义时间上,保证事件能执行
对象新属性无法更新视图,删除属性无法更新视图
原因:Object.definePropertym没有对对象的新属性进行劫持
使用Vue.$set(obj,key,value)
删除用 Vue.$delete(obj,key)
直接arr[index] = xxx无法更新视图
原因:Vue没有对数组进行数据劫持
使用数组的splice方法
使用Vue.$set(arr,index,value)
nextTick的用处
Vue是异步更新 此方法是在更新之后
SSR服务端渲染
Vue响应式原理怎么实现的
对象内部使用defineReactive方法,使用Object.defineProperty将属性进行劫持,数组则是重写,每个属性都有自己的dep属性
存放他所依赖的watcher,属性变化时通知自己对应的watcher去更新
为什么不对数组进行数据劫持?
数据量
实际面试总结
Vue页面加载优化
路由懒加载
路由懒加载的几种方法
component:()=>import('@/views/login.vue') 解构
component:resolve=>require(['@/views/login'],resolve) 引入并赋值
const login = ()=>import('./views/login.vue')
component:login
webpack提供的require.ensure()实现懒加载
const HelloWorld=resolve=>{
require.ensure(['@/components/HelloWorld'],()=>{
resolve(require('@/components/HelloWorld'))
})
}
路由懒加载做了什么事
主要作用是将路由对应的组件打包成一个个的js代码块,只有在这个路由被访问到的时候,才加载对应的组件,否则不加载!
组件懒加载
const one = ()=>import('./one')
components:{one}
components:{
one:resolve=>require(['./one'],resolve)
}
按需加载 elementui
较大图片进行压缩/换成网络地址
CDN引入
不生成.map文件
build出来的dist文件夹里面有很多的.map文件,这些文件主要是帮助线上调试代码,查看样式.
由于基本都是本地调试好,线上不需要怎么修改,所以就禁止生成这些文件
config>index.js中 productionSourceMap改为false
使用gzip压缩
安装compression-webpack-plugin
Vue改变数组的方法 七种
push pop shift unshift reverse sort spilice
vue侦听器
方法格式的侦听器
watch:{
name(newName,oldName){
}
}
缺点:首次进入浏览器,无法立即触发第一次。侦听对象,对象数据发生变化,不会触发。
对象格式的侦听器
优点:可以通过immediate属性,控制侦听器自动触发一次(默认是false)。可以 通过deep属性,控制侦听器深度监听到对象中每一个属性的变化
watch:{
obj:{
handler(newval){
},
immediate:true,
deep:true
}
}
如果想要侦听对象里某一个子属性的变化,可以通过''单引号进行包裹
watch:{
'obj.name'(newval,oldval){
}
}
侦听器的特点
它的命名不能随意,必须和你想侦听的属性名称完全一致
它不能手动调用,它是自动触发
不需要有任何返回值
它可以侦听异步操作中数据的变化
computed/watch/filter的区别
computed当页面中需要使用大量的表达式处理数据时
watch数据变化时执行异步或开销较大的操作时
filter与computed的主要区别在于它可以当做函数使用
computed 对于其中变量的依赖是多个的 watch 的依赖则是单个的
vue前端权限控制
接口权限
接口权限目前一般采用jwt的形式来验证,没有通过的话一般返回401,跳转到登录页面重新进行登录
登录完拿到token,将token存起来,通过axios请求拦截器进行拦截,每次请求的时候头部携带token
axios.interceptors.request.use(config => {
config.headers['token'] = cookie.get('token')
return config
})
axios.interceptors.response.use(res=>{},{response}=>{
if (response.data.code === 40099 || response.data.code === 40098) { //token过期或者错误
router.push('/login')
}
})
标签:总结,vue,入门,Vue,组件,router,路由,属性 From: https://blog.51cto.com/u_15449946/5840226