Vue2全家桶精简备忘录

97 阅读9分钟

指令

内容渲染

  1. v-text

    • 覆盖内部原有内容
  2. {{}}

    • 内容占位
  3. v-html

    • 渲染成HTML

属性绑定

  1. v-bind(:)

    • 动态绑定值(单向)

事件绑定

  1. v-on:可简写为@

  2. v-on

    • 事件对象

      • @click=“clk(666,$event)”

        • 自动给形参$event传入事件对象
    • 事件修饰符

      • @click.prevent

        • 阻止单击默认行为
      • @click.stop

        • 阻止单击冒泡
    • 按键修饰符

      • @keyup.enter

        • enter键抬起
      • @keyup.esc

        • esc键抬起

双向绑定

  1. v-model

    • 动态绑定值(双向)

    • 绑定修饰符

      • 转为数值

        • v-model.number
      • 去掉首尾空白

        • v-model.trim
      • 懒更新

        • v-model.lazy
        • 输入完成后更新数据

条件渲染

  1. v-if、v-else-if、v-else、

    • 对dom修改
  2. v-show

    • 对css修改

列表渲染

绑定key

  1. v-for

插槽绑定

v-slot: 简写 #

v-slot:槽名 简写为 #槽名

自定义指令

this = undefined

vue指令规定必须以v-开头,v-后才是真正的指令名

注意是指令不是属性,指令上下文默认在vue实例上,不需要进行绑定

私有

定义在vue实例的directives节点下

不接收指令值

注意!!!! bind先于mounted this指undefined

<template>
  <div>
    <p v-color></p>
  </div>
</template>
<script>
export default {
  directives:{
    color:{ // color:指令名
      bind(el){ // bind:绑定时执行 el:原生dom对象 
        console.log(el)
      },
       update(el){ //update:dom更新时执行,绑定时不执行 数据改变dom改变
       console.log(el)
      }
    }
  }
}
</script>

接收指令值

<template>
  <div>
    <p v-color="red"></p>
  </div>
</template>
<script>
export default {
  data() {
    return {
      age:13
    }
  },
  directives:{
    color:{ // color:指令名
      bind(el,binding){ // bind:绑定时执行 el:原生dom对象
        console.log(el,binding.value) // binding.value:指令值
      },
      update(el,binding){ //update:dom更新时执行,绑定时不执行
      console.log(el,binding.value)
      }
    }
  }
}
</script>

bind在绑定时,update在dom更新时执行。每次都执行相同的操作可以将指令名写成函数的形式

<template>
  <div>
    <p v-color="red"></p>
  </div>
</template>
<script>
export default {
  data() {
    return {
      age:13
    }
  },
  directives:{
    color(el,binding){ // color:指令名
        
    }
  }
}
</script>

全局

通过Vue构造函数的directive()声明

过滤器(filters)

Vue.directive("color",(el,binding){ // Vue.directive(参数1,参数2) 参数2效果同私有指令相同。函数形式每次执行相同的代码 对象形式需指定bind、update
​
})

vue3(不支持)

一般用于对数据格式化,以 (表达式 | 过滤器)形式调用 。

私有过滤器

定义在Vue实例filters节点

filters:{
    filter(value){
​
    }
}

全局过滤器

调用Vue构造函数filter函数,传入过滤器名回调函数

侦听器(watch)

定义在Vue实例watch节点

方法形式

页面加载时不触发

watch:{
    // attribute:要监听的属性 变化后newVal 变化前oloVal
    attribute(newVal,oloVal){
        
    }
​
}

对象形式

页面加载时触发、深度监听

watch:{
    // attribute:要监听的属性 变化后newVal 变化前oloVal
    attribute:{
        handler(newVal,oloVal){
​
        },
        // true:页面加载时触发 false:页面加载时不触发(默认)
        immediate:true,
        // true:开启深度监听 对象属性变化时 会触发(获取到对象非对象属性) false(默认)
        deep:true
    }
​
}

监听子属性

要监听对象的子属性,需要给侦听器名加一层单引号

watch:{
    // attribute:要监听的属性 变化后newVal 变化前oloVal
    'attribute.attribute'(newVal,oloVal){
        
    }
​
}

计算属性(computed)

定义在Vue实例computed节点

计算属性也是Vue实例属性,但该属性由计算而来

computed:{
	// attribute:计算属性名
	attribute(){
		// calculate:计算后的值
		return calculate
	}
}

组件

组件三部分:组件结构(template)、组件行为(script)、组件样式(style)

每个template只能必须包含一个标签

启用less

<style lang="less">

</style>

导入使用

导入

import Left from "@/components/Left.vue"

注册

定义在Vue实例components节点

components:{
	Left
}

导入(全局)

main.js入口文件导入

import Left from "@/components/Left.vue"

注册(全局)

main.js入口文件通过Vue.component()注册

Vue.component(“Left”,Left)

使用

<Left></Left>

props(只读)

自定义属性也是实例属性,定义在Vue实例props节点下

用于组件接收外部传入的值

定义(数组)

只能接收值

export default {
  props:["attribute"]
}

定义(对象)

指定默认值、类型、必填

export default {
  props:{
		attribute:{
			default:0, //设置默认值
			type:Number, //指定类型
			required:true //属性必填
		}
	}
}

使用

<Left attribute1="666"></Left>

样式冲突

scoped

给style加上scoped,实现样式隔离(给所有的元素和样式添加属性data-v-xxx)

<style scoped>

</style>

/deep/

设置scoped情况下,表示当前组件的属性(data-v-xxx),实现修改子组件样式

<style scoped>
    // 可以选择到子组件下的div
    /deep/ div{
        
    }
</style>

生命周期

创建

beforeCreate

  • 创建前
  • 初始化事件和生命周期函数
  • 组件的props、data、methods未创建,不可用

created

  • 创建后
  • 组件的props、data、methods以创建,可用
  • 模板结构未生成,dom未创建,不可用
  • 用于发送请求

beforeMount

  • 挂载前
  • 将要渲染,dom未渲染,不可用

mounted

  • 挂载后
  • dom渲染完成,dom可用

运行

数据更新会引发dom更新,执行0次多次

beforeUpdate

  • dom更新前
  • 数据以更新,dom未更新

updated

  • dom更新后
  • 数据、dom更新完成

激活

activated

  • 组件在被keep-alive 激活后触发

暂停

deactivated

  • 组件被keep-alive 停用缓存后触发

出错

errorCaptured

  • 子组件出错(同步错误)会调用这个生命周期函数

销毁

beforeDestroy

  • 销毁前
  • 将要销毁组件,组件能正常工作

destroyed

  • 销毁后
  • vue实例销毁完成

父向子传值

props

子向父传值

自定义事件

子组件向外抛出一个自定义事件并传入参数,父组件捕获事件获取参数

子组件

this.$emit("event"data) // 向外抛出一个event自定义事件,传入data

父组件

<son @event="getData"></sonson> // 监听子组件的event自定义事件,调用getData回调

兄弟组件传值

EventBus

通过导入vue实例(单例),触发和监听自定义到达传值和取值的目的

eventBus .js

import Vue from 'vue'
const eventBus = new Vue()
export default eventBus

A .vue

<template>
  <div>
      <button @click="send">点击发送</button>
  </div>
</template>

<script>
import eventBusVue from "./eventBus.js"
export default {
    methods:{
        send(){
            eventBusVue.$emit("send",0)
        }
    }
}
</script>

B .vue

<template>
  <div>

  </div>
</template>

<script>
import eventBusVue from "./eventBus.js"
export default {
    created(){
        eventBusVue.$on("send",(v)=>{
            console.log(v)
        })
    }
}
</script>

App .vue

<template>
  <div>
      <button @click="send">点击发送</button>
  </div>
</template>
<script>
import eventBusVue from "./eventBus.js"
export default {
    methods:{
        send(){
            eventBusVue.$emit("send",0)
        }
    }
}
</script>

ref引用

每个vue组件实例上,都包含一个$refs对象,存储这对dom元素或组件的引用。默认属性为空

<son ref="s"></son>
export default {
  mounted() {
    console.log(this.$refs)
  }
}

$nextTick延迟

延迟到dom渲染后执行

this.$nextTick(()=>{

})

name

在声明时给组件指定name,有以下作用

  1. 在调试工具以name给组件命名
  2. keep-alive的include以name为准。

插槽

把组件不确定的部分定义为插槽

不具名槽

<slot></slot>

vue官方规定每个slot槽都要有name名称,默认为“default”。

所有的插默认放在name=“default”槽中

具名槽

槽自定义name(不为default)

<slot name="zs"></slot>

插指定槽时必须用template包裹,并且在template上用 v-solt:槽名 指定槽

槽默认内容

当没有插与槽匹配时,可以给槽指定默认内容

<slot name="zs">默认内容</slot>

作用域插槽

可以给槽像一般组件一样传递参数

<slot name="zs" :m="s">默认内容</slot>

插接收参数,必须在template上通过 ="对象名" 来接收槽的参数,默认为空对象,可解构接收,但该对象的作用域只在该template有效

<template v-slot:zs ="ob" > //v-slot: 简写 #,#zs也是可以的
	<div>
        66
    </div>
</template>

不具名插

// 不具名插不用template包裹,默认将内容放到 不具名槽(name="default")中
<Left>
	<p>
        123
    </p>
</Left>

具名插

// 具名插要用template包裹,template是个虚拟元素
<template v-slot:zs ="ob" > //v-slot: 简写 #,#zs也是可以的
	<div> // 将template包裹的元素渲染到 name="zs" 的槽处
        66
    </div>
</template>

动态组件

动态组件可以动态的切换组件的显示和隐藏

vue提供了内置组件,用于实现动态组件

<component is="组件名"></component> //渲染指定组件 切换组件名会导致组件创建销毁

缓存

切换组件时,不会销毁组件,只是将组件隐蔽

<keep-alive>
	<component is="组件名"></component> //渲染指定组件 切换组件名不会导致组件创建销毁
</keep-alive>

激活后自动调用组件activated生命周期函数

隐蔽后自动调用组件deactivated生命周期函数

指定缓存

给的include属性添加规则,可以指定被缓存的组件

<keep-alive include=“a”>
	<component is="组件名"></component> //渲染指定组件 切换组件时只有a组件不会被销毁
</keep-alive>

mixin(混入)

将相同的部分抽离成一个文件,需要时直接引入使用

组件定义的方法和data等会覆盖混入的

组件的生命周期不会覆盖混入的,混入生命周期先于组件定义的生命周期执行

src/mixin.js

export default { // 向外暴露带有vue格式的对象
    data(){
        return {
            name:'zs'
        }
    },
    mounted(){
        console.log("mounted");
    }
}

全局混入

root根组件也会被混入,所有vue实例(包括root)都会被混入

main.js

import Mymixin from "./mixin";
Vue.mixin(Mymixin)

局部混入

import Mymixin from "../mixin"
export default {
  data() {
    return {
      h:"123"
    }
  },
  mounted(){
        console.log("object");
    },
  mixins:[Mymixin], // mixins混入只能是数组形式
​
}

路由

两种模式hash和history(切换url目录,如果用户刷新将向服务器发起请求,存在服务器没有响应的可能)

用户点击路由链接,导致url的hash变化,前端路由监听hash变化匹配不同的组件

安装vue-router

npm i vue-router -S

创建路由模块

  • 在src源代码目录下,新建router/index.js
// 导包
import Vue from 'vue'
import VueRouter from 'vue-router'
// 导入组件
import Home from '@/components/Home.vue'

// 在Vue上安装VueRouter插件
Vue.use(VueRouter)

// 创建实例配置路由规则并默认导出
const router = new VueRouter({
    mode: "hash", // 默认hash模式  mode: "history"开启请求路径模式
    routes:[
        {path:'/home',name:'home',component:Home} // 规则里面的name和<router-view name='home'>的name是两个不同的概念,不要混淆
    ]
})

export default router

导入并挂载路由模块

  • main.js(打包入口文件)中挂载VueRouter实例

    // 导入VueRouter实例
    import router from 'router/index.js'
    new Vue({
      router, // 挂载路由实例到Vue实例
      store,
      render: h => h(App)
    }).$mount('#app')
    

声明链接和占位符

  • 在要跳转路由和要展示的区域使用router-link和router-view

    <router-link to="/home">home</router-link> // 可用<a href='#/home'></a>标签修改hash实现
    <router-view ></router-view>
    

路由规则

重定向

redirect

const router = new VueRouter({
routes:[
        {path:'/',name:'home',redirect:'/home'} // 将/重定向到/home
    ]
})

嵌套路由

const router = new VueRouter({
    routes:[
        {
			path:'/home',
			name:'home',component:Home,
			children:[
      			{
        			path:'tab1',
        			component:Tab1
      			}

    		]
		}
    ]
})

默认子路由

const router = new VueRouter({
    routes:[
        {
			path:'/home',
			name:'home',component:Home,
			children:[
      			{
        			path:'', // 子路由path为空,当hash为#/home 时子路由也会匹配
        			component:Tab1
      			}
    		]
		}
    ]
})

路由参数获取

把hash地址可变的部分定义为参数项,提高路由规则的复用性。

在路由匹配规则里面,使用 :变量名 接收参数

const router = new VueRouter({
    routes:[
        {path:'/home/:id',name:'home',component:Home} // #/home/xxx的内容都被匹配,#/home/xxx/xxx不会被匹配,并且只匹配第一个满足项(书写顺序)
// 在组件里面可以通过 this.$route.params.id获取路由规则里面的值
    ]
})

route获取

Vue挂载Vue-router后在Vue实例上

this.$route.fullPath:#后的全部字符串

this.$route:路径相关信息

this.$route.params:动态参数对象

this.$route.path:路径参数

this.$route.query:请求参数

在组件里面可以通过 this.$route.params.id获取路由规则里面的值

props获取

const router = new VueRouter({
    routes:[
        {
			path:'/home/:name/:age',
			name:'home', // 路由命名
            component:Home,
            props:true, // 开启props传参,动态params参数会传递给组件对应的porps
            props:($route)=>({params:$route.params,query:$route.query}), // 开启props传参,params和query都可以传递porps
		}
    ]
})

参数传递

query

params

注意

通过

path:'/home/:name/:age' // 必须传递对应的参数
path:'/home/:name/:age?' // 可不传

params传递空串路径出问题,传undefined不会

mate

传递格式

字符串

对象

对象的name何必和组件的name保持一致

path不能和params参数一起使用

this.$router.push({name:"demo",params:{},query:{}})

声明式导航

点击链接实现导航的方式,叫做声明式导航

编程式导航

调用aip实现导航的方式,叫做编程式导航

push

this.$router.push(‘hash地址):增加历史记录

replace

this.$router.replace('hash地址'):不增加历史记录

go

this.$router.go(数值n):在历史记录上移动

this.$router.back();后退一个历史记录

this.$router.forward():前进一个历史记录

导航守卫

全局前置守卫

每次发生路由导航跳转时都会触发全局前置守卫,因此可以在全局前置守卫中进行访问权限控制。

在src源代码目录下,router/index.js

// 导包
import Vue from 'vue'
import VueRouter from 'vue-router'
// 导入组件
import Home from '@/components/Home.vue'

// 在Vue上安装VueRouter插件
Vue.use(VueRouter)

// 创建实例配置路由规则并默认导出
const router = new VueRouter({
    routes:[
        {path:'/home',name:'home',component:Home} 
    ]
})

// to:将要访问的 路由信息对象  from:将要离开的路由信息对象 next:放行函数
在当前页面 
router.beforeEach((to,from,next)=>{
    //to.path:将要访问的路由字符串(请求路径) this.$router.path
    // next():直接放行 
    // next('/login'):跳转到登录页面 
    // next(false):不允许跳转,停留在当前页面
}) // 路由导航跳转回调

export default router

this.$route:路由信息对象

this.$route.fullPath:#后的全部字符串

this.$route:路径相关信息

this.$route.params:动态参数对象

this.$route.path:路径参数

this.$route.query:请求参数

在组件里面可以通过 this.$route.params.id获取路由规则里面的值

Vuex

安装

npm i vuex -S

导入挂载创建

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
    // state全局共享数据
  state: { 
  	count:0
  },
    
  getters: {
  },
    // 定义(同步)函数参数1接收state对象
  mutations: {
  },
    // 
  actions: {
  },
  modules: {
  }
})

属性

state

state全局共享数据

定义

state: { 
  	count:0
  },

访问state(不允许直接修改)

  1. 通过this.$store.state.count访问

  2. 映射成计算属性

    import {mapState} from 'vuex'
    
    export default {
        computed:{
    	...mapState(['count']) // 也可以写函数式:...mapState({count:(state)=>state.count}) 
    	}
    }
    

getters

在getters定义函数,函数参数1接收state对象

用于对state里的数据进行加工不修改,类似与Vue计算属性

定义

getters: { 
  	getCount(state){
		return 'the count is' + state.count
	}
},

调用getters里函数

  1. 通过this.$store.getters.getCount调用

  2. 映射成计算属性

    import {mapGetters} from 'vuex'
    
    export default {
        computed:{
    	...mapGetters(['getCount'])
    	}
    }
    

mutations

在mutations定义同步函数,函数参数1接收state对象

最好只执行同步代码,devtools调试工具需要捕捉到前一状态和后一状态的快照,如果执行了异步操作devtools调试工具对于异步的操作无法记录(虽然异步也不会报错)

定义

mutations: { 
	add(state,n){ // 定义函数 参数1:state
		state.count += n
	}
},

调用mutations里函数(不要有异步代码)

  1. 通过this.$router.commit('add',3)

  2. 映射成方法

    import {mapMutations} from 'vuex'
    
    export default {
        methods:{
    	...mapMutations(['add'])
    	}
    }
    

actions

在mutations可以定义异步函数,函数参数1接收一个与 store 实例具有相同方法和属性的 context 对象,因此你可以调用 context.commit 提交一个 mutation

定义

actions: { 
	asyncAdd(context,n){ // 定义函数 参数1:state
		setTimeout(()=>{
		context.commit('add',n)
	},1000)
	}
},

调用actions里函数

  1. 通过this.$router.dispatch('asyncAdd',3)

  2. 映射成方法

    import {mapActions} from 'vuex'
    
    export default {
        methods:{
    	...mapActions(['asyncAdd'])
    	}
    }
    

modules

Vuex 允许我们将 store 分割成模块(module) 。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块

挂载实例

import Vue from 'vue'
import App from './App.vue'
import store from './store'

new Vue({
  store,
  render: h => h(App)
}).$mount('#app')

axios

安装

npm i axios -S

get

import axios from "axios"
axios.get(url,{请求参数})

post

import axios from "axios"
axios.get(url,{请求参数})

配置挂载到Vue原型

main.js

import axios from "axios"
axios.defaults.baseURL = "http://localhost:9090" 
// axios.defaults.baseURL = location.origin 配置到服务器域名
Vue.prototype.$http = axios

脚手架

全局安装

npm install -g @vue/cli

升级

npm install -g @vue/cli

创建

vue create hello-world

启动

npm run serve

编译

npm run build

踩坑日记

img动态src

<img :src="require(`../assets/${titles.cover}`)" alt="" srcset="" />
<!-- 动态拼接rsc时,需要通过require导入模块的形式导入,不能直接修改rsc字符串,因为图片也会被webpack打包修改文件名 -->