vue知识点
第一章、vue的指令
指令(Directives)是 vue 为开发者提供的
模板语法
,用于辅助开发者渲染页面
的基本结构
① 内容渲染指令
② 属性绑定指令
③ 事件绑定指令
④ 双向绑定指令
⑤ 条件渲染指令
⑥ 列表渲染指令
1. 内容渲染指令
内容渲染指令用来辅助开发者
渲染 DOM 元素的文本内容
1.1. v-text
:缺点会覆盖元素内部原有的内容
1.2.{{ }}
:插值表达式,只是内容的占位符不会覆盖原来的内容
1.3.v-html
:可以带有标签的内容,渲染成真正的html内容
2. 属性渲染指令(又称单向数据绑定指令)
为元素的
属性动态绑定属性值
,则需要用到v-bind
属性绑定指令
注意 : 插值表达式只能用在元素内容节点中,不能用在元素属性节点中
v-bind
:为元素的属性动态的绑定值- 简写是英文
:
- 在使用v-bind属性绑定期间,如果绑定内容需要进行动态的拼接,则字符串的外面应该包裹单引号,例如:
<div v-bind:title="'box'+index">这是一个div</div>
3. 事件绑定指令
vue 提供了
v-on
事件绑定指令,用来辅助程序员为 DOM 元素绑定事件监听
原生 DOM 对象有 onclick、oninput、onkeyup 等原生事件,替换为 vue 的事件绑定形式后,
分别为:v-on:click、v-on:input、v-on:keyup
v-on 绑定的事件处理函数,需要在 methods 节点中进行声明
3.1.v-on
指令绑定点击事件 后面是跟处理函数
3.2.可以简写为:@
3.3.语法格式为:
<button v-on:click="add"></button>
mmethods:{
add(){
//如果在方法中要修改数据,可以通过this访问到
this.count+=1;
}
}
3.4. $event
的应用场景:如果默认的事件对象e被覆盖了,则可以手动的传递一个 $event。例如:
<button v-on:click="add(n,$event)"></button>
mmethods:{
add(e){
//如果在方法中要修改数据,可以通过this访问到
this.count+=n;
}
}
3.5. 事件修饰符
prevent
<a @click.prevent="XXX">链接</a>
stop
<button @click.stop="XXX">按钮</button>
4. v-model
:双向绑定指令(又称数据双向绑定指令)
vue 提供了 v-model 双向数据绑定指令,用来辅助开发者在不操作 DOM 的前提下,快速获取表单的数据
注意:只能用于一些表单的数据操作才有意义,其他没有意义
4.1. v-model的修饰符:
5. 条件渲染指令(根据条件显示与隐藏相应的dom元素)
条件渲染指令用来辅助开发者按需控制 DOM 的显示与隐藏
5.1.v-show
的原理是:动态的为元素添加或移除display:none
样式,来实现元素的显示和隐藏
如果要频繁的切换元素的显示状态,用v-show性能会更好
5.2.v-if
的原理:每次动态的创建或移除元素
,实现元素的显示与隐藏
如果刚进入页面的时候,某些元素默认不需要显示,而且后期这个元素很可能不需要被展示出来,此时用v-if性能会更好
5.3.v-else-if
:多条件判断指令,要和v-if
来搭配只用 结束是:v-else
,里面可以放Boolean值也可以放条件表达式的到Boolean值
<div v-if="type==='A'">优秀</div>
<div v-else-if="type==='B'">良好</div>
<div v-else-if="type==='C'">一般</div>
<div v-else="type==='D'">差</div>
6. v-for
:列表渲染指令
6.1.作用:用来辅助开发基于一个数组来循环渲染一个列表结构。v-for
指令需要使用item in items
形式的的特殊语法,
item
:表示被循环的每一项- 在自身上也可以访问到item里面的值
items
:表示被循环的数组,例如- ① key 的值只能是字符串或数字类型
② key 的值必须具有唯一性(即:key 的值不能重复)
③ 建议把数据项 id 属性的值作为 key 的值(因为 id 属性的值具有唯一性)
④ 使用 index 的值当作 key 的值没有任何意义(因为 index 的值不具有唯一性)
⑤ 建议使用 v-for 指令时一定要指定 :key 的值(既提升性能、又防止列表状态紊乱)
data:{
//list 表示数据
list:[
{id:1,name:'zs'}
{id:2,name:'ls'}
]
}
<ul>
<li v-for="item in list" :key="item.id">姓名:{{item.name}}</li>
</ul>
7. 总结:
① 能够知道vue的基本使用步骤
● 导入vue.js文件
● new Vue()构造函数,得到vm实例对象
● 声明el和data数据节点
● MVVM的对应关系
② 掌握vue中常见指令的基本用法
● 插值表达式、v-bind、v-on、v-if 和v-else
● v-for 和:key. v-model
③ 掌握vue中过滤器的基本用法
第二章、vue的过滤器
过滤器(Filters)是 vue 为开发者提供的功能,常用于文本的格式化。过滤器可以用在两个地方:插值表达式
和 v-bind 属性绑定
1. 过滤器的注意点:
1.1.要定义到filters
节点下,本质是一个函数
1.2.在过滤器函数中一定要有return
值
1.3.在过滤器的形参中,就可以获取到 管道符 |
前面待处理的那个值
1.4.私有过滤器与全局过滤器
- 私有过滤器:定义在
vue 实列对象里面 filters
的就是私有过滤器 - 全局过滤器:
Vue.filter
参数1 ,表示全局过滤器的名字
参数2,表示全局过滤器处理函数
Vue.filter('toMiniDate', function (val) {
const y = val.getFullYear()
const m = val.getMinutes() + 1
const d = val.getDate()
return [y, m, d].join('-')
})
//使用
<p>金额:{{ money | toRmb }}</p>
<p>生日:{{ bornDate | toMiniDate }}</p>
第三章、侦听器watch
watch 侦听器允许开发者监视数据的变化,从而针对数据的变化做特定的操作
1.方法格式的侦听器
- 缺点1:无法在
进入页面
的时候,自动触发! - 缺点2:如果侦听的
是一个对象
,如果对象里面的属性发生了变化,不会触发侦听器!
const vm = new Vue({
el: "#app",
data: {
username: "张三",
},
// 所有的监听器都应该定义在watch 节点下
watch: {
// 侦听器本质上就是一个函数,要监听那个数据的变化,就把数据名作为方法名即可
// 新增的数值在前,旧值在后
username(newVal, oldValue) {
// console.log('监听到了username值的变换', newVal, oldValue);
$.get("https://www.escook.cn/api/finduser/" + newVal, function (req,res) {
console.log(req,res);
})
}
}
})
2.对象格式的侦听器
- 好处1:可以通过
handler
函数,immediate:true
,让侦听器自动触发! - 好处2:可以通过
deep:true
选项,让侦听器深度监听对象中每个属性的变化!
const vm = new Vue({
el: "#app",
data: {
username: "张三",
},
// 所有的监听器都应该定义在watch 节点下
watch: {
// 定义对象格式的侦听器
username: {
// 侦听器处理函数
handler(newVal, oldValue) {
console.log(newVal, oldValue);
},
// 默认是false 不会触发
// immediate作用:控制侦听器是否自动触发一次
immediate: true
}
},
})
//使用
<p>金额:{{ money | toRmb }}</p>
<p>生日:{{ bornDate | toMiniDate }}</p>
第四章、计算属性 (computed)
计算属性是通过一些列运算之后,最终得到的一个值,这个动态计算出来的属性可以被
模板结构
或者methods
方法使用
注意点:
- 所有的计算属性都要定义到
computed
中 - 在定义计算属性的时候要定义成
方法
- 在使用计算属性的时候,当
普通的属性
使用即可
优点 - 实现了代码的复用
- 只要计算属性中依赖的数据源变化了,则计算属性会自动重新求值
var vm = new Vue({
el: '#app',
data: {
// 红色
r: 0,
// 绿色
g: 0,
// 蓝色
b: 0
},
methods: {
// 点击按钮,在终端显示最新的颜色
show() {
console.log(this.rgb)
}
},
// 所有的计算属性都要被定义到computed中
// rgb作为一个计算属性,被定义成 方法格式
// 最终这个方法中,要返回一个生成到的rgb(x,x,x)的字符串
computed: {
rgb() {
return `rgb(${this.r}, ${this.g}, ${this.b})`
}
}
});
第五章、axios
axios是一个专注于网络请求的一个库
1. 私有axios
axios的基本使用
1.1 发起post请求:
axios({
// 请求方式
method: "GET",
// 请求地址
url: "http://www.liulongbin.top:3006/api/getbooks",
// get传参 url中的查询参数
params: {
id: 1
}
}).then((res) => {
console.log(res.data);
})
1.2. 发起post请求:
<button id="btn1">发起post请求</button>
<script>
document.querySelector("#btn1").addEventListener('click', async function () {
// 如果调用某个方法的返回值是promise实列 ,则前面可以调价 await
// await 只能用在被 async '修饰'的方法中
const { data } = await axios({
// 请求方式
method: "POST",
// 请求地址
url: "http://www.liulongbin.top:3006/api/post",
// post 传参
data: {
name: "zs",
age: 20
}
})
console.log(data);
})
2. 全局axios
2.1.在main.js中 配置
// 导入axios模块
import axios from 'axios'
//全局配置axios的请求地址
axios.defaults.baseURL='http://www.liulongbin.top:3006'
// 今后,在每个.vue每个组件中发起请求,直接调用 this.$http
Vue.prototype.$http=axios
2.2. 使用
methods: {
async getAss() {
const {data:res } = await this.$http.get('/api/get')
console.log(res);
}
第六章、vue-cli(称脚手架)
vue-cli 是 Vue.js 开发的标准工具。它简化了程序员基于 webpack 创建工程化的 Vue 项目的过程
1.安装
1.1.安装vue-cli 指令
// -g 表示全局安装
npm install -g @vue/cli
1.2. 检测是否安装成功
vue -V
2. 创建vue项目
- 步骤指令 点击
enter
vue create 项目名称
2.步骤 点击enter
3.步骤 点击enter
4.步骤 点击enter
5.步骤 点击enter
6.步骤 点击enter
7.步骤 点击enter
8.步骤
3. vue项目中src目录的构成
3.1.
assets
文件名:存放项目中用到的静态资源,例如:css样式表,图片资源
3.2.components
文件名:存放程序员封装的,可复用的组件,到要放到此目录
3.3.main.js
是项目的入口文件,整个项目的运行,要先执行main.js
3.4.App.vue
是项目的跟组件
第七章、组件(components)
1. vue在项目中运行的过程
- 在工程化的项目中,vue 要做的事情很单纯:通过
main.js
把App.vue
渲染到index.html
的指定区域中。
其中:
①App.vue
用来编写待渲染的模板结构
②index.html
中需要预留一个 el 区域
③ main.js 把 App.vue 渲染到了 index.html 所预留的区域中
2.组件的格式语法
组件化开发指的是:根据封装的思想,把页面上可重用的 UI 结构封装为组件
- 每个 .
vue
组件都由 3 部分构成,分别是: template
-> 组件的模板结构script
-> 组件的 JavaScript 行为style
-> 组件的样
- 组件中
template
定义ui结构的:
注意点1:template 中只能包含唯一的根节点
<template>
<h1 class="box">这是测试text.vue的结构---{{ username }}</h1>
</template>
- 组件中
script
处理交互行为
注意:组件中的data数据,不能指向对象
注意:组件中的data数据必须是一个函数{},在return出去的{}中,可以定义数据
style
是样式:
<template>
<h1 class="box">这是测试text.vue的结构---{{ username }}</h1>
</template>
<script>
// 默认到处的语法
export default {
// data数据源
//注意:.vue组件中的data 不能像之前一样,不能指向对象
//注意:组件中的data必须是一个函数
data() {
//这个return出去的{}中,可以定义数据
return {
username: 'zs'
}
}
}
</script>
<style>
.box {
background-color: red;
}
</style>
3.组件之间的父子关系
4. 使用组件三个步骤
4.4.1. 注册私有组件
通过 components 注册的是私有子组件
例如:
在组件 A 的 components 节点下,注册了组件 F。
则组件 F 只能用在组件 A 中;不能被用在组件 C 中
4.4.2. 注册全局组件
在 vue 项目的 main.js 入口文件中,通过 Vue.component() 方法,可以注册全局组件
// 导入 Count组件
import Count from '@/components/Count.vue'
// 把Count注册为全局组件
Vue.component('MyCount', Count)
4.4.3.组件中的props属性
props 是自定义属性,允许使用者通过自定义属性,为当前的组件指定初始值
export default{
//组件的自定义属性
props:['自定义属性A','自定义属性B'....]
//组件的私有数据
data(){
return{}
}
}
第八章、组件的生命周期函数
表示组件从创建到运行到销毁的时间阶段:叫生命周期
1.总结
第九章、动态组件
动态组件:表示动态的按需展示或者隐藏所需要的组件
- vue内置得到组件
component
占位符
<component is='组件得到名字'></component>
- 缓存(
keep-alive
),include
:表示要缓存的组件
<keep-alive include='要缓存的组件'>
<component is='组件的名字'><component>
</keep-alive>
- keep-alive对应的生命周期
1.当组件被缓存了,自动触发deactivated
生命周期函数
2.当组件被激活了,自动触发activated
生命周期函数
deactivated (){
console.log('组件被缓存了')
},
activated(){
console.log('组件被激活了')
}
第十章、插槽(slot)
把不确定,希望用户自定的部分定义为插槽
1. 默认插槽
1.1. 插槽的name
属性,表示给每一个插槽指定一个插槽名称
// 子组件
<slot name='插槽的名称'></slot>
1.2. 在使用组件中,把内容填充到指定的插槽中(v-slot
简写:#)
// 父组件
<templat v-solt:default>
// v-solt 只能用在组件或者template身上
<p>把这个内容渲染到指定的插槽中</p>
</templat>
2. 具名插槽
为每一个插槽指定一个名字
//父组件
<template>
<div>
<TestChild>
<template v-slot:title>
<div>哈哈</div>
</template>
<template #contain>
<div>你好</div>
</template>
<template #author>
<div>李白</div>
</template>
</TestChild>
</div>
</template>
<script>
import TestChild from '@/components/TestChild'
export default {
components: {
TestChild
},
// 子组件
<template>
<div class="article-contain">
<!-- 文章的标题 -->
<div class="header-box">
<slot name="title"></slot>
</div>
<!-- 文章的内容 -->
<div class="contain-box">
<!-- 在封装组件时,为预留的<slot>提供属性对应的值,这种用法,叫做 "作用域插槽" -->
<slot name="contain" msg="hello world" :user="userInfo"></slot>
</div>
<!-- 文章的作者 -->
<div class="footer-box">
<slot name="author"></slot>
</div>
</div>
</template>
3. 作用域插槽
为预留插槽提供属性的对应值,叫做作用域插槽
<template>
// 父组件
<div>
<TestChild v-slot="{ item }">
<div>{{ item }}</div>
</TestChild>
</div>
</template>
<script>
import TestChild from '@/components/TestChild'
export default {
components: {
TestChild
}
}
</script>
//子组件
<template>
<div>
<slot v-for="item in list" :item="item"></slot>
</div>
</template>
<script>
export default {
data() {
return {
list: [1, 2, 3]
}
}
}
</script>
第十一章、自定义指令
2.私有自定义指令
1.两个函数:bind
当指令绑定到元素上才触发,只触发一次
2.update
:实时更新DOM元素内容
在每个vue组件中,可以在directives节点下声明私有自定义指令
// 第一种 对象形式的写法
// 定义私有自定义指令
directives: {
// 定义一个color指令 指向一个配置对象
color: {
// 当指令绑定到元素上的时候,会立即触发bind函数
// 形参中的el表示当前所绑定到的那个DOM对象
bind(el,bind) {
el.style.color = bind.value
},
// 数据发生改变是就是触发这个update函数
update(el,bind){
el.style.color=bind.value
}
}
}
//第二种 函数形式的写法,当对象形式的写法的bind和update函数的逻辑一样的时候可以改成函数形式的写法
color(el,bind){
el.style.color=bind.value
}
2.全局自定义指令
在main.js中定义全局自定义属性
// 全局自定义指令
Vue.directive('color', function (el, binding) {
el.style.color = binding.value
})
第十二章、路由(router)
表示
hash
地址和组件
之间的对应关系
1.安装路由
npm install vue-router@4
2.配置路由在src
下新建一个router
->index.js
文件
import Vue from 'vue'
import VueRouter from 'vue-router'
import HomeView from '../views/HomeView.vue'
Vue.use(VueRouter)
const routes = [
{
path: '/',
name: 'home',
component: HomeView
},
{
path: '/about',
name: 'about',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import(/* webpackChunkName: "about" */ '../views/AboutView.vue')
}
]
const router = new VueRouter({
routes
})
export default router
2.1.<router-view>
表示存放定义的hash地址的组件
<router-view></touter-view>
2.2.routes
:定义路由链接
routes: [
// 表示路由规则
{path: '/home',component: HomeView},
]
2.3.router-link
:可以替换a链接
<router-link to='路由的hash地址'>首页<router-link>
2.4. 路由的重定向redirect
routes: [
// 路由重定向
{path:'/', redirect:'/home'}
// 表示路由规则
{path: '/home',component: HomeView},
]
第十三章、路由的嵌套(router children)
- 默认子路由相当于是路由重定向
默认子路由:如果children数组中,某个路由规则的path值为空字符,则这条路由规则,叫做‘默认子路由’
路由参数对象:route 路由导航对象:router
<div id="app">
<router-link to="/home">首页</router-link>
<!-- 注意1:再hash地址中,/后面的参数项,叫做路径参数 -->
<!-- 再路由参数对象中,需要使用this.$route.params 来访问路径参数 -->
<router-link to="/mui/i">篮球火</router-link>
<!-- 注意2:在hash地址中, ?好后面的参数项,叫做 查询参数 -->
<!-- 在路由参数对象中,需要使用 this.$route.query来访问 查询参数 -->
<!-- 注意3:在this.$route中,path只是路径部分,fullpath是完整的路径地址 -->
<router-link to="/mui/w?name=zs age=20">熊出没</router-link>
<router-link to="/mui/f">大鱼</router-link>
<router-link to="/music">歌曲</router-link>
<hr>
<!-- 只要再项目中安装了vue-router 就提供了一个组件router-view这个组件起到占位符 -->
<router-view></router-view>
</div>
第十四章、vue-router中的编程式导航API
vue-router提供了许多编程式导航的API,其中最常用的导航API分别是
thi.$router.push('hash地址')
,跳转到指定的地址,并增加
一条历史记录this.$router.replace('hash地址')
,跳转到指定的地址,并替换
掉原来的历史记录this.$router.go('数字')
,表示前进或者后退
3.1. $router.go的简写
$router.back()
:在历史记录中,后退
到上一个页面$router-forward()
:在历史记录中,前进
到下一个页面
第十五章、vue-$router导航守卫
导航守卫可以控制路由的访问权限
- 全局前置守卫
// 创建路由实例对象
const router =new VueRouter({})
// 全局前置守卫
router.beforeEach((to,from,next)=>{
// to表示要访问的 路由信息对象
// from 表示将要离开路由信息对象
//next是一个函数 调用next()表示放行,允许这次路由导航
next()
})
- next函数的三种调用方式
3.全局前置导航守卫
// from表示当前所在的hash地址,to表示的是路由连接跳转到组件的hash地址
router.beforeEach((to, from, next) => {
// 1.要拿到用户将要访问的hash地址
// 2.判断hash 地址是否等于/main。
// 2.1 如果等于/main, 证明需要登录之后,才能访问成功
// 2.2如果不等于/main, 则不需要登录,直接放行next()
// 3.如果访问的地址是/main。 则需要读取localStorage 中的token值
// 3.1 如果有token, 则放行
// 3.2如果没有token, 则强制跳转到/login 登录页
if (to.path === '/main') {
const token = localStorage.getItem('keyToken')
if (token) {
next()
} else {
next('/login')
}
} else {
next()
}
})
第十六章、 组件之间的通信方法
第一种 自定义属性,父向子传递数据
//父组件中的数据传递给Left 组件 yongv-bind绑定自定义属性
<div class="box">
<Left :msg="message" :userInfo="userInfo"></Left>
<Right @changVal="countValue"></Right>
</div>
data() {
return {
message: 'hello word',
userInfo: { name: '你好', age: 12 },
countAdd: 0
}
// 子组件中用props来声明接收,可以直接在模板中使用
props: ['msg', 'userInfo'],
第二种 自定义事件,子向父传递数据
//父组件
<template>
<div id="app">
// 父组件中定义自定义事件处理函数
<Right @changVal="countValue"></Right>
</div>
</template>
<script>
import Left from "@/components/Left.vue"
import Right from "@/components/Right.vue"
export default {
name: 'App',
components: {
Right
},
data() {
return {
userInfo: { name: '你好', age: 12 },
}
},
methods: {
countValue(e) {
this.countAdd = e
}
}
}
</script>
// 子组件
<template>
<button @click="addCount">count++</button>
</template>
<script>
import bus from '@/components/eventBus'
export default {
name: 'Left_Info',
data() {
return {
// 子组件,将来将count子组件里面的值传递给父组件
count: 10,
songMessage:''
}
},
methods: {
addCount() {
this.count++
// $emit 触发自定义事件,将值传递给父组件
this.$emit('changVal',this.count)
}
}
}
第三种 eventBus 兄弟组件通信
第四种 全局事件总线
- 在main.js中vue实列上挂载一个属性
import Vue from 'vue'
import App from './App.vue'
Vue.config.productionTip = false
new Vue({
render: h => h(App),
beforeCreate() {
// 安装全局事件总线,借助的是同一个vue实列
Vue.prototype.$bus = this
}
}).$mount('#app')
- 在任意组件中绑定一个点击事件 调用
$emit
将数据发送过去
methods: {
nameDaas() {
// 发送数据
this.$bus.$emit('hell', 9999)
}
}
3.在任意组件中的生命钩子接收数据 调用 $on
mounted() {
//接收数据
this.$bus.$on('hell', (data) => {
console.log('我是Left组件', +data);
})
},
第五种方式、消息订阅与发布
1.安装包来完成消息订阅与发布
npm i pubsub-js
2.在任意组件种导入包,发送数据方调用pubsub.publish
methods: {
nameDaas() {
// 发送数据
pupsub.publish('hello', 666)
}
}
3.在任意组件中导入包并在组件中调用一个生命周期钩子函数,接收数据方调用pupsub.unsubscribe
mounted() {
// 接收数据,两个参数,第一个是订阅的名称,第二个参数是发送方发过来的数据
this.pubId = pupsub.subscribe('hello', (item, msg)=> {
console.log('有人发布消息了', item, msg);
})
},
// 在组件销毁之前把所有的订阅数据个他解绑
beforeDestroy() {
pupsub.unsubscribe(this.pubId)
}
第六种方式、provide与inject
1.父组件种定义数据
<template>
<div class="home">
<h2>父组件</h2>
<p>姓名:{{ name }}</p>
<p>年龄:{{ age }}</p>
<p>汽车名称:{{ carName }}</p>
<p>汽车颜色:{{ carColor }}</p>
<!-- 父组件通过props向子组件传递数据 -->
<One :name="name" :age="age" @setname="name = $event" @setage="updateAge"></One>
<Two></Two>
</div>
</template>
<script>
import One from '@/components/One.vue'
import Two from '@/components/Two.vue'
export default {
name: 'My_Home',
// 数据
data() {
return {
name: '张三',
age: 20,
carName: '特斯拉',
carColor: '白色'
}
},
// 依赖数据,这里定义数据,所有的后代组件都可以获取
provide() {
return {
carName: this.carName,
carColor: this.carColor,
setCarName: this.setCarName,
setCarColor: this.setCarColor
}
},
methods: {
updateAge(e) {
this.age = e
},
// 修改汽车名称的方法
setCarName(val) {
this.carName = val
},
// 修改汽车颜色的方法
setCarColor(val) {
this.carColor = val
}
},
components: {
One,
Two
}
}
</script>
- 在子组件种接收数据
<template>
<div class="three">
<h3>子组件</h3>
<p>汽车名称:{{ MyCarName }}</p>
<p>汽车颜色:{{ MyCarColor }}</p>
<p>
<button @click="setName">修改汽车名称</button>
<button @click="setCarColor1">修改汽车颜色</button>
</p>
</div>
</template>
<script>
export default {
name: 'My_three',
// 后代组件,通过inject选项注入父组件中依赖鹅数据
inject: ['carName', 'carColor', 'setCarName', 'setCarColor'],
data() {
return {
// 中转接收过来的父组件数据
MyCarName: this.carName,
MyCarColor: this.carColor,
}
},
methods: {
setName() {
// 修改自己的值
this.MyCarName = '宝马'
// 修改父组件中的值
this.setCarName('宝马')
},
setCarColor1() {
this.MyCarColor = '红色'
this.setCarColor('红色')
},
},
}
</script>
第十七章、vuex
vuex是专门在vue中实现集中式数据管理的一个vue插件,读vue应用中的多个组件的共享状态进行集中式的管理(读/写)也是组件间通信的方式
- 安装vuex
//安装版本三
npm i vuex@3
-
搭建vuex环境
-
创建文件:
src/store/index.js
//引入Vue核心库
import Vue from 'vue'
//引入Vuex
import Vuex from 'vuex'
//应用Vuex插件
Vue.use(Vuex)
//准备actions对象——响应组件中用户的动作
const actions = {}
//准备mutations对象——修改state中的数据
const mutations = {}
//准备state对象——保存具体的数据
const state = {}
//创建并暴露store
export default new Vuex.Store({
actions,
mutations,
state
})
- 在
main.js
中创建vm时传入store
配置项
......
//引入store
import store from './store'
......
//创建vm
new Vue({
el:'#app',
render: h => h(App),
store
})
基本使用
- 初始化数据、配置
actions
、配置mutations
,操作文件store.js
//引入Vue核心库
import Vue from 'vue'
//引入Vuex
import Vuex from 'vuex'
//引用Vuex
Vue.use(Vuex)
const actions = {
//响应组件中加的动作
jia(context,value){
// console.log('actions中的jia被调用了',miniStore,value)
context.commit('JIA',value)
},
}
const mutations = {
//执行加
JIA(state,value){
// console.log('mutations中的JIA被调用了',state,value)
state.sum += value
}
}
//初始化数据
const state = {
sum:0
}
//创建并暴露store
export default new Vuex.Store({
actions,
mutations,
state,
})
-
组件中读取vuex中的数据:
$store.state.sum
-
组件中修改vuex中的数据:
$store.dispatch('action中的方法名',数据)
或$store.commit('mutations中的方法名',数据)
备注:若没有网络请求或其他业务逻辑,组件中也可以越过actions,即不写
dispatch
,直接编写commit
getters的使用
-
概念:当state中的数据需要经过加工后再使用时,可以使用getters加工。
-
在
store.js
中追加getters
配置
......
const getters = {
bigSum(state){
return state.sum * 10
}
}
//创建并暴露store
export default new Vuex.Store({
......
getters
})
- 组件中读取数据:
$store.getters.bigSum
四个map方法的使用
- mapState方法:用于帮助我们映射
state
中的数据为计算属性
computed: {
//借助mapState生成计算属性:sum、school、subject(对象写法)
...mapState({sum:'sum',school:'school',subject:'subject'}),
//借助mapState生成计算属性:sum、school、subject(数组写法)
...mapState(['sum','school','subject']),
},
- mapGetters方法:用于帮助我们映射
getters
中的数据为计算属性
computed: {
//借助mapGetters生成计算属性:bigSum(对象写法)
...mapGetters({bigSum:'bigSum'}),
//借助mapGetters生成计算属性:bigSum(数组写法)
...mapGetters(['bigSum'])
},
- mapActions方法:用于帮助我们生成与
actions
对话的方法,即:包含$store.dispatch(xxx)
的函数
methods:{
//靠mapActions生成:incrementOdd、incrementWait(对象形式)
...mapActions({incrementOdd:'jiaOdd',incrementWait:'jiaWait'})
//靠mapActions生成:incrementOdd、incrementWait(数组形式)
...mapActions(['jiaOdd','jiaWait'])
}
- mapMutations方法:用于帮助我们生成与
mutations
对话的方法,即:包含$store.commit(xxx)
的函数
methods:{
//靠mapActions生成:increment、decrement(对象形式)
...mapMutations({increment:'JIA',decrement:'JIAN'}),
//靠mapMutations生成:JIA、JIAN(对象形式)
...mapMutations(['JIA','JIAN']),
}
备注:mapActions与mapMutations使用时,若需要传递参数需要:在模板中绑定事件时传递好参数,否则参数是事件对象。
模块化+命名空间
-
目的:让代码更好维护,让多种数据分类更加明确。
-
修改
store.js
const countAbout = {
namespaced:true,//开启命名空间
state:{x:1},
mutations: { ... },
actions: { ... },
getters: {
bigSum(state){
return state.sum * 10
}
}
}
const personAbout = {
namespaced:true,//开启命名空间
state:{ ... },
mutations: { ... },
actions: { ... }
}
const store = new Vuex.Store({
modules: {
countAbout,
personAbout
}
})
- 开启命名空间后,组件中读取state数据:
//方式一:自己直接读取
this.$store.state.personAbout.list
//方式二:借助mapState读取:
...mapState('countAbout',['sum','school','subject']),
- 开启命名空间后,组件中读取getters数据:
//方式一:自己直接读取
this.$store.getters['personAbout/firstPersonName']
//方式二:借助mapGetters读取:
...mapGetters('countAbout',['bigSum'])
- 开启命名空间后,组件中调用dispatch
//方式一:自己直接dispatch
this.$store.dispatch('personAbout/addPersonWang',person)
//方式二:借助mapActions:
...mapActions('countAbout',{incrementOdd:'jiaOdd',incrementWait:'jiaWait'})
- 开启命名空间后,组件中调用commit
//方式一:自己直接commit
this.$store.commit('personAbout/ADD_PERSON',person)
//方式二:借助mapMutations:
...mapMutations('countAbout',{increment:'JIA',decrement:'JIAN'}),
- 总结
第十七章、 自定义插件
import axios from 'axios'
// 自定义插件就是一个对象
export default {
// 对象中的必须是一个install方法
install(Vue, options) {
// install方法第第一个参数必须是Vue, 第二个参数是可选的配置对象
// 在options方法中,对Vue进行扩展
// 在vue原型上添加一个属性
Vue.prototype.$bus = new Vue()
// 扩张过滤器
Vue.filter('toRmb', function (val) {
return '¥' + val.toFixed(2)
})
Vue.filter('toMiniDate', function (val) {
const y = val.getFullYear()
const m = val.getMinutes() + 1
const d = val.getDate()
return [y, m, d].join('-')
})
// 全局混入
// 混入代码,这里面定义的选项或跟所有的vue实列及组件进行合并
Vue.mixin({
data() {
return {
message: '欢迎使用vue开发'
}
},
methods: {
setMessage(e) {
this.message = e
},
async $get(url, params) {
const { data } = await axios.get(url, { params })
return data
},
// 定义post请求方法
async $post(url, params) {
const { data } = await axios.post(url, params)
return data
}
}
})
// 全局自定义指令
// 自定义指令,就是对dom结构的封装
Vue.directive('red', function (el, bind) {
// el: 当前所在的元素
// bind:是绑定的一份数据
el.style.color = 'red'
})
Vue.directive('green', function (el, bind) {
el.style.color = 'green'
})
Vue.directive('myShow', function (el, bind) {
if (bind.value) {
el.style.display = 'block'
} else {
el.style.display = 'none'
}
})
Vue.directive('role', function (el, bind) {
// 判断当前登录的用户权限
const roeId = sessionStorage.getItem('roeId')
if (['1', '3', '5'].includes(roeId)) {
el.style.display = 'block'
} else {
el.style.display = 'none'
}
})
// 全局组件
Vue.component('my_box', (h) => {
return h('div', {}, '哈哈')
})
}
}