Vue工程化开发
Vue工程化开发
一、工程化开发和脚手架
1.开发Vue的两种方式
- 核心包传统开发模式:基于html / css / js 文件,直接引入核心包,开发 Vue。
- 工程化开发模式:基于构建工具(例如:webpack)的环境中开发Vue。
工程化开发模式优点:
提高编码效率,比如使用JS新语法、Less/Sass、Typescript等通过webpack都可以编译成浏览器识别的ES3/ES5/CSS等
工程化开发模式问题:
- webpack配置不简单
- 雷同的基础配置
- 缺乏统一的标准
为了解决以上问题,所以我们需要一个工具,生成标准化的配置
2.脚手架Vue CLI
Vue CLI 是Vue官方提供的一个全局命令工具
可以帮助我们快速创建一个开发Vue项目的标准化基础架子。【集成了webpack配置】
使用步骤:
- 全局安装(只需安装一次即可) yarn global add @vue/cli 或者 npm i @vue/cli -g
- 查看vue/cli版本: vue --version
- 创建项目架子:vue create project-name(项目名不能使用中文)
- 启动项目:yarn serve 或者 npm run serve(命令不固定,找package.json)
3.项目目录介绍和运行流程

二、组件化开发
组件化:一个页面可以拆分成一个个组件,每个组件有着自己独立的结构、样式、行为。
好处:便于维护,利于复用 → 提升开发效率。
组件分类:普通组件、根组件。
1.根组件 App.vue
整个应用最上层的组件,包裹所有普通小组件

2.组件是由三部分构成
- 语法高亮插件

-
三部分构成
- template:结构 (有且只能一个根元素)
- script: js逻辑
- style: 样式 (可支持less,需要装包)
-
让组件支持less
(1) style标签,lang=“less” 开启less功能
(2) 装包: yarn add less less-loader -D 或者npm i less less-loader -D
3.局部注册
局部注册只能在注册的组件内使用,放在components包下,以大驼峰命名法, 如 HmHeader
// 导入需要注册的组件
import 组件对象 from '.vue文件路径'
import HmHeader from './componets/HmHeader'export default { // 局部注册components: {'组件名': 组件对象,HmHeader:HmHeaer,HmHeader}
}
3.全局注册
全局注册的组件,在项目的任何组件中都能使用,在mian.js中进行注册
Vue.component(‘组件名’, 组件对象)
例:
// 导入需要全局注册的组件
import HmButton from './components/HmButton'
Vue.component('HmButton', HmButton)
scoped样式冲突
默认情况下,写在组件中的样式会 全局生效 → 因此很容易造成多个组件之间的样式冲突问题。
-
全局样式: 默认组件中的样式会作用到全局,任何一个组件中都会受到此样式的影响
-
局部样式: 可以给组件加上scoped 属性,可以让样式只作用于当前组件
<style scoped>
</style>
组件data函数写法
一个组件的 data 选项必须是一个函数(以前是对象)。保证每个组件维护一份数据,函数执行一次得到一个新函数保证每个组件实例,维护独立的一份数据对象。
代码演示:
<template><div class="base-count"><button @click="count--">-</button><span>{{ count }}</span><button @click="count++">+</button></div>
</template><script>
export default {data: function () {return {count: 100,}},
}
</script>
三、父子组件通信
组件通信,就是指组件与组件之间的数据传递,组件的数据是独立的,无法直接访问其他组件的数据。想使用其他组件的数据,就需要组件通信
父子通信流程
- 父组件通过 props 将数据传递给子组件
- 子组件利用 $emit 通知父组件修改更新
1.定义父子组件
父组件App.vue
<template><div class="app" style="border: 3px solid #000; margin: 10px">我是APP组件 <Son></Son></div>
</template><script>
import Son from './components/Son.vue'
export default {name: 'App',data() {return {myTitle: 'Vue',}},components: {Son,},
}
</script>
子组件Son.vue
<template><div class="son" style="border:3px solid #000;margin:10px">我是Son组件</div>
</template><script>
export default {name: 'Son-Child',
}
</script><style></style>
2.父向子传递数据
子组件利用 props 向子组件传递数据,可以传递 任意数量 任意类型 的prop

父向子传值步骤
- 给子组件以添加属性的方式传值
- 子组件内部通过props接收
- 模板中直接使用 props接收的值
3.子向父通信
子组件利用 $emit 通知父组件,进行修改更新

子向父传值步骤
- $emit触发事件,给父组件发送消息通知
- 父组件监听$emit触发的事件
- 提供处理函数,在函数的性参中获取传过来的参数
4.props校验
为组件的 prop 指定验证要求,不符合要求,控制台就会有错误提示 → 帮助开发者,快速发现错误,可以进行类型校验、非空校验、默认值、自定义校验
props:{校验的属性名:类型(Number String Boolean ...)//传递值必须为对应类型
}
props校验完整写法
语法:
props: {校验的属性名: {type: 类型, // Number String Boolean ...required: true, // 是否必填default: 默认值, // 默认值validator (value) {// 自定义校验逻辑return 是否通过校验}}
},
注意:
default和required一般不同时写(因为当时必填项时,肯定是有值的)
default后面如果是简单类型的值,可以直接写默认。如果是复杂类型的值,则需要以函数的形式return一个默认值
四、-event bus事件总线
-event bus事件总线可在非父子组件之间,进行简易消息传递。(复杂场景→ Vuex)
步骤
-
创建一个都能访问的事件总线 (空Vue实例)
import Vue from 'vue' const Bus = new Vue() export default Bus -
A组件(接受方),监听Bus的 $on事件
created () {Bus.$on('sendMsg', (msg) => {this.msg = msg}) } -
B组件(发送方),触发Bus的$emit事件
Bus.$emit('sendMsg', '这是一个消息')
代码示例

五、provide&inject
provide&inject可用于跨层级共享数据,顶层组件提供数据,子孙后代获取数据
语法
- 父组件 provide提供数据
export default {provide () {return {// 普通类型【非响应式】color: this.color, // 复杂类型【响应式】userInfo: this.userInfo, }}
}
2.子/孙组件 inject获取数据
export default {inject: ['color','userInfo'],created () {console.log(this.color, this.userInfo)}
}
注意
- provide提供的简单类型的数据不是响应式的,上层修改子孙后代的值不会实时修改,复杂类型数据是响应式。(推荐提供复杂类型数据)
- 子/孙组件通过inject获取的数据,不能在自身组件内修改
六、.sync修饰符
作用:实现 子组件 与 父组件数据 的 双向绑定,简化代码
简单理解:子组件可以修改父组件传过来的props值
语法
父组件在原本父传子的基础上加上 .sync和@update:属性名的简写
//.sync写法,本质是 :属性名和
<BaseDialog :visible.sync="isShow" />
--------------------------------------
//完整写法
<BaseDialog :visible="isShow" @update:visible="isShow = $event"
/>
子组件事件类型固定位update:属性名
props: {visible: Boolean
},
//update对应上面的@update
this.$emit('update:visible', false)
代码示例

七、ref和$refs
ref 和 $refs 可以用于在 **当前组件内 **(更精确稳定)获取 dom 元素 或 组件实例
语法
1.给要获取的盒子添加ref自定义属性名
<div ref="chartRef">我是渲染图表的容器</div>
2.获取时通过 $refs获取 this.$refs.chartRef 获取(当前实例须渲染完成)
mounted () {console.log(this.$refs.chartRef)
}
之前只用document.querySelect(‘.box’) 获取的是整个页面中的盒子
代码示例

八、异步更新 & $nextTick
$refs获取dom时,可能dom未更新导致获取失败,$nextTick:等 DOM更新后,才会触发执行此方法里的函数体
语法: this.$nextTick(函数体)
this.$nextTick(() => {this.$refs.inp.focus()
})
注意:$nextTick 内的函数体 一定是箭头函数,这样才能让函数内部的this指向Vue实例
九、插槽
1.默认插槽
如果组件结构相同,但现实内容不同,例如提示框。就可以使用插槽自定义组件显示内容
插槽的基本语法
- 组件内需要定制的结构部分,改用****占位
- 使用组件时, ****标签内部, 传入结构替换slot
- 给插槽传入内容时,可以传入纯文本、html标签、组件
实例:

插槽默认值
通过插槽完成了内容的定制,传什么显示什么, 但是如果不传,则是空白
封装组件时,可以为预留的 <slot> 插槽提供后备内容(默认内容)。
在 标签内,放置内容, 作为默认显示内容
<!-- 往slot标签内部,编写内容,可以作为后备内容(默认值) --><slot>我是默认的文本内容</slot>
2.插槽-具名插槽
默认插槽只能定制一个内容,如果需要为多个地方定制内容,需要使用具名插槽(给插槽起名字)
语法

v-slot写起来太长,vue给我们提供一个简单写法 v-slot —> #
3.作用域插槽
作用域插槽值定义slot 插槽的同时, 。给 插槽 上可以 绑定数据,来 给使用组件时可以用,它是插槽的传参语法,并不是插槽的类别
使用步骤
-
给 slot 标签, 以 添加属性的方式传值
<slot :id="item.id" msg="测试文本"></slot> -
所有添加的属性, 都会被收集到一个对象中
{ id: 3, msg: '测试文本' } -
在template中, 通过
#插槽名= "obj"接收,默认插槽名为 default<MyTable :list="list"><template #default="obj"><button @click="del(obj.id)">删除</button></template> </MyTable>
插槽只有两种,默认插槽和具名插槽,作用域插槽不属于插槽的一种分类
十、路由
1.路由基本使用
Vue工程一般都为单页面程序,单页应用程序:SPA【Single Page Application】是指所有的功能都在一个html页面上实现,如网易云官网。单页面应用程序页面是按需更新,所以开发效率高,性能好,用户体验也更好。要按需更新,就需要明确:访问路径和 组件的对应关系,而路由就是设置组件和访问路径的
VueRouter安装配置步骤
//1.下载 VueRouter 模块到当前工程,版本3.6.5
yarn add vue-router@3.6.5
//2.main.js中引入VueRouter
import VueRouter from 'vue-router'
//3.安装注册
Vue.use(VueRouter)
//4.创建路由对象
const router = new VueRouter()
//5.注入,将路由对象注入到new Vue实例中,建立关联
new Vue({render: h => h(App),router:router
}).$mount('#app')
注:当我们配置完以上5步之后 就可以看到浏览器地址栏中的路由 变成了 /#/的形式。表示项目的路由已经被Vue-Router管理了
VueRouter路径设置
-
在
main.js创建需要的组件 (views目录),配置路由规则import Find from './views/Find' import My from './views/My' import Friend from './views/Friend' import VueRouter from 'vue-router' Vue.use(VueRouter) // VueRouter插件初始化const router = new VueRouter({// routes 路由规则们// route 一条路由规则 { path: 路径, component: 组件 }routes: [{ path: '/find', component: Find },{ path: '/my', component: My },{ path: '/friend', component: Friend },] }) -
配置导航,配置路由出口(路径匹配的组件显示的位置)
App.vue
<div class="footer_wrap"><a href="#/find">发现音乐</a><a href="#/my">我的音乐</a><a href="#/friend">朋友</a> </div> <div class="top"><router-view></router-view> </div>
路由的封装抽离
可以将路由模块单独抽离出来。 好处:拆分模块,利于维护

路径简写:
脚手架环境下 @指代src目录,可以用于快速引入组件
2.声明式导航-导航链接
vue-router 提供了一个全局组件 router-link (取代 a 标签)
- 能跳转,配置 to 属性指定路径(必须) 。本质还是 a 标签 ,to 无需 #
- 能高亮,默认就会提供高亮类名,可以直接设置高亮样式
语法: 发现音乐
<div><div class="footer_wrap"><router-link to="/find">发现音乐</router-link><router-link to="/my">我的音乐</router-link><router-link to="/friend">朋友</router-link></div><div class="top"><!-- 路由出口 → 匹配的组件所展示的位置 --><router-view></router-view></div></div>
声明式导航-两个类名
使用router-link跳转后,我们发现。当前点击的链接默认加了两个class的值 router-link-exact-active和router-link-active我们可以给任意一个class属性添加高亮样式即可实现功能
-
router-link-active:模糊匹配(用的多,to=“/my” 可以匹配 /my /my/a /my/b …
-
router-link-exact-active:精确匹配,to=“/my” 仅可以匹配 /my
-在跳转路由时,进行传参。可以通过查询参数传参和动态路由传参两种方式,在跳转的时候把所需要的参数传到其他页面中
01-查询参数传参
-
传参:
-
接受参数:
固定用法:$router.query.参数名
示例

02-动态路由传参
-
配置动态路由
动态路由后面的参数可以随便起名,但要有语义
const router = new VueRouter({routes: [...,{ path: '/search/:words', component: Search }] }) -
配置导航链接
to=“/path/参数值”
-
对应页面组件接受参数
$route.params.参数名
示例

注:
- 查询参数传参 (比较适合传多个参数)
- 动态路由传参 (优雅简洁,传单个参数比较方便)
- 动态路由也可以传多个参数,但一般只传一个
动态路由参数的可选符(了解)
配了路由 path:“/search/:words” 如果没有传入参数,会未匹配到组件显示空白。如果不传参数,也希望匹配,可以在words后面加一个?
3.编程式导航
编程式导航是用JS代码来实现点击按钮时跳转路由,主要有两种方式:path 路径跳转 (简易方便)和name 命名路由跳转 (适合 path 路径长的场景)
01-path路径跳转语法
特点:简易方便
- query查询参数跳转
//简单写法
this.$router.push('/路径?参数名1=参数值1&参数2=参数值2')
//完整写法
this.$router.push({path: '/路径',query: {参数名1: '参数值1',参数名2: '参数值2'}
})
接受参数的方式依然是:$route.query.参数名
- 动态路由传参
//简单写法
this.$router.push('/路径/参数值')
//完整写法
this.$router.push({path: '/路径/参数值'
})
示例

**注意:**path不能配合params使用
02-name命名路由跳转
特点:适合 path 路径长的场景
- query查询参数跳转
this.$router.push({name: '路由名字',query: {参数名1: '参数值1',参数名2: '参数值2'}
})
接受参数的方式依然是:$route.query.参数名
- 动态路由传参
this.$router.push({name: '路由名字',params: {参数名: '参数值',}
})
示例

4.路由重定向
网页打开时, url 默认是 / 路径,未匹配到组件时,会出现空白,可以加上redirect配置重定向路径
示例
const router = new VueRouter({routes: [{ path: '/', redirect: '/home'},...]
})
5.404页面路由
当路径找不到匹配时,给个404提示页面
配置方式
path: “*” (任意路径) – 前面不匹配就命中最后这个
import NotFind from '@/views/NotFind'const router = new VueRouter({routes: [...{ path: '*', component: NotFind } //最后一个]
})
6.Vue路由-模式设置
路由的路径看起来不自然, 有#,能否切成真正路径形式?
- hash路由(默认) 例如: http://localhost:8080/#/home
- history路由(常用) 例如: http://localhost:8080/home (以后上线需要服务器端支持,开发环境webpack给规避掉了history模式的问题)
设置方式
const router = new VueRouter({mode:'histroy', //默认是hashroutes:[]
})
7. 二级路由配置
当在页面中点击链接跳转,只是部分内容切换时,我们可以使用嵌套路由,二级路由也叫嵌套路由,当然也可以嵌套三级、四级…
配置方式:
- 在一级路由下,配置children属性即可
- 配置二级路由的出口
1.在一级路由下,配置children属性
注意:一级的路由path 需要加 / 二级路由的path不需要加 /
const router = new VueRouter({routes: [{path: '/',component: Layout,children:[//children中的配置项 跟一级路由中的配置项一模一样 {path:'xxxx',component:xxxx.vue},{path:'xxxx',component:xxxx.vue},]}]
})
2.配置二级路由的出口
这些二级路由对应的组件渲染到哪个一级路由下,children就配置到哪个路由下边
注意: 配置了嵌套路由,一定配置对应的路由出口,否则不会渲染出对应的组件
Layout.vue
<template><div class="h5-wrapper"><div class="content"><router-view></router-view></div>....</div>
</template>
二级导航高亮
- 将a标签替换成 组件,配置to属性,不用加 #
- 结合高亮类名实现高亮效果 (推荐模糊匹配:router-link-active)
代码实现
Layout.vue
....<nav class="tabbar"><router-link to="/article">面经</router-link><router-link to="/collect">收藏</router-link><router-link to="/like">喜欢</router-link><router-link to="/user">我的</router-link></nav><style>a.router-link-active {color: orange;}
</style>
十一、缓存组件
当路由被跳转后,原来所看到的组件就被销毁了(会执行组件内的beforeDestroy和destroyed生命周期钩子),重新返回后组件又被重新创建了(会执行组件内的beforeCreate,created,beforeMount,Mounted生命周期钩子),所以数据被加载了。这样就会导致详情页返回列表页,页面重新加载回到列表顶部。
keep-alive
keep-alive 是 Vue 的内置组件,当它包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。在组件切换过程中把切换出去的组件保留在内存中,防止重复渲染DOM,可以减少加载时间及性能消耗,提高用户体验性。
keep-alive 是一个抽象组件:它自身不会渲染成一个 DOM 元素,也不会出现在父组件中。
App.vue
<template><div class="h5-wrapper"><keep-alive><router-view></router-view></keep-alive></div>
</template>
这样会缓存了所有被切换的组件
keep-alive的三个属性:
-
include : 组件名数组,只有匹配的组件会被缓存
-
exclude : 组件名数组,任何匹配的组件都不会被缓存
-
max : 最多可以缓存多少组件实例
示例:
<template><div class="h5-wrapper"><keep-alive :include="['LayoutPage']"><router-view></router-view></keep-alive></div>
</template>
keep-alive的使用会触发两个生命周期函数
- activated 当组件被激活(使用)的时候触发 → 进入这个页面的时候触发
- deactivated 当组件不被使用的时候触发 → 离开这个页面的时候触发
组件缓存后就不会执行组件的created, mounted, destroyed 等钩子了
所以其提供了actived 和deactived钩子,帮我们实现业务需求。
十二、Vuex
Vuex 是一个 Vue 的 状态管理工具,状态就是数据。可以帮我们管理 Vue 通用的数据 (多组件共享的数据)。
优势:
- 共同维护一份数据,数据集中化管理
- 响应式变化
- 操作简洁 (vuex提供了一些辅助函数)
但不是所有的场景都适用于vuex,只有在必要的时候才使用vuex,使用了vuex之后,会附加更多的框架中的概念进来,增加了项目的复杂度 (数据的操作更便捷,数据的流动更清晰)
vuex安装使用
1. 安装 vuex
//安装vuex与vue-router类似,vuex是一个独立存在的插件,如果脚手架初始化没有选 vuex,就需要额外安装。
yarn add vuex@3 或者 npm i vuex@3
2.新建 store/index.js 专门存放 vuex
为了维护项目目录的整洁,在src目录下新建一个store目录其下放置一个index.js文件。 (和 router/index.js 类似)
3.创建仓库 store/index.js
// 导入 vue
import Vue from 'vue'
// 导入 vuex
import Vuex from 'vuex'
// vuex也是vue的插件, 需要use一下, 进行插件的安装初始化
Vue.use(Vuex)// 创建仓库 store
const store = new Vuex.Store()// 导出仓库
export default store
4 在 main.js 中导入挂载到 Vue 实例上
import Vue from 'vue'
import App from './App.vue'
import store from './store'Vue.config.productionTip = falsenew Vue({render: h => h(App),store
}).$mount('#app')
此刻起, 就成功创建了一个 空仓库!!
5.测试打印Vuex
App.vue
created(){console.log(this.$store)
}
1.state 状态
State提供唯一的公共数据源,所有共享的数据都要统一放到Store中的State中存储。
打开项目中的store.js文件,在state对象中可以添加我们要共享的数据。
// 创建仓库 store
const store = new Vuex.Store({// state 状态, 即数据, 类似于vue组件中的data,// 区别:// 1.data 是组件自己的数据, // 2.state 中的数据整个vue项目的组件都能访问到state: {count: 101}
})
访问Vuex中的数据的方式:
- 通过$store直接访问 —> {{ $store.state.count }}
- 通过辅助函数mapState 映射计算属性 —> {{ count }}
通过$store访问的语法
获取 store:1.Vue模板中获取 this.$store2.js文件中获取 import 导入 store模板中: {{ $store.state.xxx }}
组件逻辑中: this.$store.state.xxx
JS模块中: store.state.xxx
组件逻辑中使用
将state属性定义在计算属性中,可以直接使用变量名访问
<h1>state的数据 - {{ count }}</h1>// 把state中数据,定义在组件内的计算属性中computed: {count () {return this.$store.state.count}}
每次都像这样一个个的提供计算属性, 太麻烦了,我们有没有简单的语法帮我们获取state中的值呢?
2.mapState
访问state内属性每次都需要一个个的提供计算属性, 太麻烦了。Vue为我们提供了mapState辅助函数,帮助我们把store中的数据映射到 组件的计算属性中
使用步骤
//1.引入 mapState函数import { mapState } from 'vuex'
//2.采用数组形式引入state属性mapState(['count'])
//3.利用展开运算符将导出的状态映射给计算属性computed: {...mapState(['count'])}
3.mutations
明确 vuex 同样遵循单向数据流,组件中不能直接修改仓库的数据。如果需要修改,需要提交mutations方式提交给仓库让仓库进行修改
mutations是一个对象,对象中存放修改state的方法
const store = new Vuex.Store({state: {count: 0},mutations: {// 方法里参数 第一个参数是当前store的state属性// payload 载荷 运输参数 调用mutaiions的时候 可以传递参数 传递载荷addCount (state) {state.count += 1}}
})
组件中提交 mutations
this.$store.commit('addCount')
带参数的 mutations
1.提供mutation函数(带参数)
mutations: {...addCount (state, count) {state.count = count}
},
2.提交mutation
handle ( ) {this.$store.commit('addCount', 10)
}
小tips: 提交的参数只能是一个, 如果有多个参数要传, 可以传递一个对象
4.mapMutations
mapMutations和mapState很像,它把位于mutations中的方法提取了出来,我们可以将它导入
import { mapMutations } from 'vuex'
methods: {...mapMutations(['addCount'])
}
//上面代码的含义是将mutations的方法导入了methods中,等价于
//methods: {
// addCount () {
// this.$store.commit('addCount')
// }
// }
methods: {// commit(方法名, 载荷参数)addCount () {this.$store.commit('addCount')}}
此时,就可以直接通过this.addCount调用了
<button @click="addCount">值+1</button>
注意: Vuex中mutations须是同步的,不能写异步代码,如果有异步的ajax请求,应该放置在actions中
5.actions
state是存放数据的,mutations是同步更新数据 (便于监测数据的变化, 更新视图等, 方便于调试工具查看变化),
actions则负责进行异步操作
1.定义actions
mutations: {changeCount (state, newCount) {state.count = newCount}
}actions: {setAsyncCount (context, num) {// 一秒后, 给一个数, 去修改 numsetTimeout(() => {context.commit('changeCount', num)}, 1000)}
},
2.组件中通过dispatch调用
setAsyncCount () {this.$store.dispatch('setAsyncCount', 666)
}
6.mapActions
mapActions 是把位于 actions中的方法提取了出来,映射到组件methods中
import { mapActions } from 'vuex'
methods: {...mapActions(['changeCountAction'])
}//mapActions映射的代码 本质上是以下代码的写法
//methods: {
// changeCountAction (n) {
// this.$store.dispatch('changeCountAction', n)
// },
//}
直接通过 this.方法 就可以调用
<button @click="changeCountAction(200)">+异步</button>
7.getters/mapGetters
除了state之外,有时我们还需要从state中筛选出符合条件的一些数据,这些数据是依赖state的,此时会用到getters。getters的数据依赖state
1.定义getters
getters: {// getters函数的第一个参数是 state// 必须要有返回值filterList: state => state.list.filter(item => item > 5)}
2.使用getters
- 2.1原始方式-$store
<div>{{ $store.getters.filterList }}</div>
- 2.2辅助函数 - mapGetters
computed: {...mapGetters(['filterList'])
}
<div>{{ filterList }}</div>
十三、Vuex分模块:module
由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。这句话的意思是,如果把所有的状态都放在state中,当项目变得越来越大的时候,Vuex会变得越来越难以维护。由此,又有了Vuex的模块化
分模块步骤:
01.模块定义 - 准备 state
定义两个模块 user 和 setting放在 store/modules/user.js,并导出
const state = {userInfo: {name: 'zs',age: 18}
}const mutations = {}
const actions = {}
const getters = {}
export default {namespace:true //开启命名空间state,mutations,actions,getters
}
02.模块注册
在store/index.js文件中的modules配置项中,注册这两个模块
import user from './modules/user'
import setting from './modules/setting'const store = new Vuex.Store({modules:{user,setting}
})
使用模块中的数据, 可以直接通过模块名访问 $store.state.模块名.xxx => $store.state.setting.desc
也可以通过 mapState 映射
尽管已经分模块了,但其实子模块的状态,还是会挂到根级别的 state 中,属性名就是模块名
使用模块中的State
- 直接通过模块名访问 $store.state.模块名.xxx
- 通过 mapState 映射:
- 默认根级别的映射 mapState([ ‘xxx’ ]) (如mapState([ ‘user’ ]是获取整个子模块的对象)
- 子模块的映射 :mapState(‘模块名’, [‘xxx’]) - 需要开启命名空间 namespaced:true
获取模块的getters
- 直接通过模块名访问
$store.getters['模块名/xxx '] - 通过 mapGetters 映射
- 默认根级别的映射
mapGetters([ 'xxx' ]) - 子模块的映射
mapGetters('模块名', ['xxx'])- 需要开启命名空间
- 默认根级别的映射
获取模块内的mutations
- 直接通过 store 调用 $store.commit('模块名/xxx ', 额外参数)
- 通过 mapMutations 映射
- 默认根级别的映射 mapMutations([ ‘xxx’ ])
- 子模块的映射 mapMutations(‘模块名’, [‘xxx’]) - 需要开启命名空间
获取模块内的actions
- 直接通过 store 调用 $store.dispatch('模块名/xxx ', 额外参数)
- 通过 mapActions 映射
- 默认根级别的映射 mapActions([ ‘xxx’ ])
- 子模块的映射 mapActions(‘模块名’, [‘xxx’]) - 需要开启命名空间
onst mutations = {}
const actions = {}
const getters = {}
export default {
namespace:true //开启命名空间
state,
mutations,
actions,
getters
}
02.模块注册在`store/index.js`文件中的modules配置项中,注册这两个模块```js
import user from './modules/user'
import setting from './modules/setting'const store = new Vuex.Store({modules:{user,setting}
})
使用模块中的数据, 可以直接通过模块名访问 $store.state.模块名.xxx => $store.state.setting.desc
也可以通过 mapState 映射
尽管已经分模块了,但其实子模块的状态,还是会挂到根级别的 state 中,属性名就是模块名
使用模块中的State
- 直接通过模块名访问 $store.state.模块名.xxx
- 通过 mapState 映射:
- 默认根级别的映射 mapState([ ‘xxx’ ]) (如mapState([ ‘user’ ]是获取整个子模块的对象)
- 子模块的映射 :mapState(‘模块名’, [‘xxx’]) - 需要开启命名空间 namespaced:true
获取模块的getters
- 直接通过模块名访问
$store.getters['模块名/xxx '] - 通过 mapGetters 映射
- 默认根级别的映射
mapGetters([ 'xxx' ]) - 子模块的映射
mapGetters('模块名', ['xxx'])- 需要开启命名空间
- 默认根级别的映射
获取模块内的mutations
- 直接通过 store 调用 $store.commit('模块名/xxx ', 额外参数)
- 通过 mapMutations 映射
- 默认根级别的映射 mapMutations([ ‘xxx’ ])
- 子模块的映射 mapMutations(‘模块名’, [‘xxx’]) - 需要开启命名空间
获取模块内的actions
- 直接通过 store 调用 $store.dispatch('模块名/xxx ', 额外参数)
- 通过 mapActions 映射
- 默认根级别的映射 mapActions([ ‘xxx’ ])
- 子模块的映射 mapActions(‘模块名’, [‘xxx’]) - 需要开启命名空间
相关文章:
Vue工程化开发
Vue工程化开发 一、工程化开发和脚手架 1.开发Vue的两种方式 核心包传统开发模式:基于html / css / js 文件,直接引入核心包,开发 Vue。工程化开发模式:基于构建工具(例如:webpack)的环境中开…...
Ray_Tracing_The_Next_Week下
5image Texture Mapping 图像纹理映射 我们之前虽然在交点信息新增了uv属性,但其实并没有使用,而是通过p交点笛卡尔坐标确定瓷砖纹理或者大理石噪声纹理的值 现在通过uv坐标读取图片,通过std_image库stbi_load(path)…...
ES索引生命周期管理
基于如何 定时删除ES索引过期数据 而引发的一系列关于ES索引生命周期管理ILM(Index Lifecycle Management)的学习 快速上手 :定时删除ES索引中的过期数据 1. ILM解决什么问题? ES从6.7版本引入ILM,通过ILM可以解决哪些问题呢? 自动新建…...
Oracle数据库体系结构基础
关于Oracle体系结构 基于Oracle11g体系结构 目标: 了解Oracle体系结构掌握逻辑存储结构掌握物理存储结构熟悉Oracle服务器结构熟悉常用的数据字典 Oracle数据库管理中的重要的三个概念 实例(instance):实例是指一组Oracle后台进程以及在服务器中分配…...
QT学习笔记4.5(文件、参数文件)
QT学习笔记4.5(文件、参数文件) 1.保存配置参数 1.使用QSettings保存到注册表,ini文件 2.文件存储:使用 QFile 和其他类将参数保存到文本文件、二进制文件、XMLWENJIAN、JSON 文件等。 文本文件:以简单的键值对格式…...
服务器虚拟化的详细学习要点
服务器虚拟化的详细学习要点可以归纳为以下几个方面: 1. 基本概念与原理 定义与原理:了解服务器虚拟化是一种将物理服务器资源转化为虚拟服务器资源的技术,允许在一台物理服务器上运行多个虚拟服务器。 虚拟化层次:理解虚拟化的不同层次,如裸机虚拟化(Type 1)和托管虚…...
创建一个Java Web API项目
创建一个Java Web API涉及多个步骤和技术栈,包括项目设置、依赖管理、数据访问层实现、业务逻辑实现、控制层开发以及测试和部署。在这篇详解中,我将带领你通过一个完整的Java Web API实现流程,采用Spring Boot和MyBatis-Plus作为主要技术工具…...
对称加密算法的使用Java和C#
1. JAVA中的使用 1.1.原生使用 Main函数代码 import symmetric_encryption.AESExample; import symmetric_encryption.BlowfishExample; import symmetric_encryption.DESExample; import symmetric_encryption.TripleDESExample; public class App { public static…...
10款好用的开源 HarmonyOS 工具库
大家好,我是 V 哥,今天给大家分享10款好用的 HarmonyOS的工具库,在开发鸿蒙应用时可以用下,好用的工具可以简化代码,让你写出优雅的应用来。废话不多说,马上开整。 1. efTool efTool是一个功能丰富且易用…...
ubuntu22.04中备份Iptables的设置
在 Ubuntu 22.04 中备份 iptables 的设置,您可以采用以下几种方法: 使用 iptables-save 命令: 您可以使用 iptables-save 命令将当前的 iptables 规则保存到文件中。例如,要将规则保存到 /etc/iptables/rules.v4 文件中࿰…...
(PyTorch) 深度学习框架-介绍篇
前言 在当今科技飞速发展的时代,人工智能尤其是深度学习领域正以惊人的速度改变着我们的世界。从图像识别、语音处理到自然语言处理,深度学习技术在各个领域都取得了显著的成就,为解决复杂的现实问题提供了强大的工具和方法。 PyTorch 是一个…...
若依从redis中获取用户列表
因为若依放入用户的时候,会在减值中添加随机串,所以用户的key会在redis中变成: login_tokens:6af07052-b76d-44dd-a296-1335af03b2a6 这样的样子。 如果用 Set<Object> items redisService.redisTemplate.keys("login_tokens&…...
文件上传之%00截断(00截断)以及pikachu靶场
pikachu的文件上传和upload-lab的文件上传 目录 mime type类型 getimagesize 第12关%00截断, 第13关0x00截断 差不多了,今天先学文件上传白名单,在网上看了资料,差不多看懂了,但是还有几个地方需要实验一下&#…...
Chainlit集成LlamaIndex并使用通义千问实现和数据库交互的网页对话应用(text2sql)
前言 我在之前的几篇文章中写了如何使用Chainlit集成Langchain并使用通义千问实现和数据库交互的网页对话应用,但是发现Langchain的几种和数据库交互的组件都不够让我满意,虽然已经满足了大部分场景的需求,但是问题还是很多,比如…...
计组复习笔记
计组笔记 汇编部分 通用寄存器(General Registers): AX (Accumulator): 用于累加运算,也是乘法和除法的默认寄存器。BX (Base Register): 可以用作一个基址寄存器,通常用于存放数据的基地址。CX (Counter Register): 通常用于循环…...
62. 环境贴图2
环境贴图作用测试 实际生活中光源照射到一个物体上,这个物体反射出去的光线也会影响其他的物体,环境贴图就是用一种简单方式,近似模拟一个物体周边环境对物体表面的影响。 测试:对于PBR材质,如果threejs三维场景不添…...
MATLAB中数据导入与导出的全面指南
在MATLAB中,数据的导入与导出是数据处理工作流中的两个基本步骤。导入是将外部数据加载到MATLAB工作区的过程,而导出则是将工作区中的数据保存到外部文件中。这两个步骤对于数据分析、可视化和结果共享至关重要。本文将详细介绍如何在MATLAB中进行数据的…...
Jenkins从入门到精通,构建高效自动化流程
目录 一、Jenkins简介1、Jenkins的历史与发展(1)Jenkins的起源(2)Jenkins的发展(3)Jenkins的社区与生态系统(4)Jenkins在我国的发展 2、Jenkins的核心功能3、Jenkins的应用场景 二、…...
【Android 13源码分析】Activity生命周期之onCreate,onStart,onResume-2
忽然有一天,我想要做一件事:去代码中去验证那些曾经被“灌输”的理论。 – 服装…...
如何在电脑上浏览手机界面
联想浏览器中,点击右键-》检查,进入开发者工具: 点击如上,红色框框选中的手机浏览模式即可。...
ES6从入门到精通:前言
ES6简介 ES6(ECMAScript 2015)是JavaScript语言的重大更新,引入了许多新特性,包括语法糖、新数据类型、模块化支持等,显著提升了开发效率和代码可维护性。 核心知识点概览 变量声明 let 和 const 取代 var…...
.Net框架,除了EF还有很多很多......
文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...
376. Wiggle Subsequence
376. Wiggle Subsequence 代码 class Solution { public:int wiggleMaxLength(vector<int>& nums) {int n nums.size();int res 1;int prediff 0;int curdiff 0;for(int i 0;i < n-1;i){curdiff nums[i1] - nums[i];if( (prediff > 0 && curdif…...
智能在线客服平台:数字化时代企业连接用户的 AI 中枢
随着互联网技术的飞速发展,消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁,不仅优化了客户体验,还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用,并…...
select、poll、epoll 与 Reactor 模式
在高并发网络编程领域,高效处理大量连接和 I/O 事件是系统性能的关键。select、poll、epoll 作为 I/O 多路复用技术的代表,以及基于它们实现的 Reactor 模式,为开发者提供了强大的工具。本文将深入探讨这些技术的底层原理、优缺点。 一、I…...
Reasoning over Uncertain Text by Generative Large Language Models
https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829 1. 概述 文本中的不确定性在许多语境中传达,从日常对话到特定领域的文档(例如医学文档)(Heritage 2013;Landmark、Gulbrandsen 和 Svenevei…...
Redis的发布订阅模式与专业的 MQ(如 Kafka, RabbitMQ)相比,优缺点是什么?适用于哪些场景?
Redis 的发布订阅(Pub/Sub)模式与专业的 MQ(Message Queue)如 Kafka、RabbitMQ 进行比较,核心的权衡点在于:简单与速度 vs. 可靠与功能。 下面我们详细展开对比。 Redis Pub/Sub 的核心特点 它是一个发后…...
HashMap中的put方法执行流程(流程图)
1 put操作整体流程 HashMap 的 put 操作是其最核心的功能之一。在 JDK 1.8 及以后版本中,其主要逻辑封装在 putVal 这个内部方法中。整个过程大致如下: 初始判断与哈希计算: 首先,putVal 方法会检查当前的 table(也就…...
图解JavaScript原型:原型链及其分析 | JavaScript图解
忽略该图的细节(如内存地址值没有用二进制) 以下是对该图进一步的理解和总结 1. JS 对象概念的辨析 对象是什么:保存在堆中一块区域,同时在栈中有一块区域保存其在堆中的地址(也就是我们通常说的该变量指向谁&…...
基于江科大stm32屏幕驱动,实现OLED多级菜单(动画效果),结构体链表实现(独创源码)
引言 在嵌入式系统中,用户界面的设计往往直接影响到用户体验。本文将以STM32微控制器和OLED显示屏为例,介绍如何实现一个多级菜单系统。该系统支持用户通过按键导航菜单,执行相应操作,并提供平滑的滚动动画效果。 本文设计了一个…...
