前提
安装Js
方法1:下载vue.js文件,保存在js目录下
方法2:采用npm方式 $ npm install vue 后期采用
Vue基本结构
{{message}}
执行流程:使用vue中的el指明要管理的元素是app,然后去检测app 发现有一个message参数
会去数据data中去查看是否有这个参数 有会填坑一样将数据填在参数中
生命周期
当我们写下简单的new Vue() 这是开始在Vue.js中开始出生,走路,吃饭等
在vue实例里面或者组件里面定义一些函数,会在某个时候回调这些函数。
[图片上传失败...(image-4c951c-1639615996147)]
created : 在绑定元素的属性或事件监听器被应用之前调用。
beforeMount : 指令第一次绑定到元素并且在挂载父组件之前调用。。
mounted : 在绑定元素的父组件被挂载后调用。。
beforeUpdate: 在更新包含组件的 VNode 之前调用。。
updated: 在包含组件的 VNode 及其子组件的 VNode 更新后调用。
beforeUnmount: 当指令与在绑定元素父组件卸载之前时,只调用一次。
unmounted: 当指令与元素解除绑定且父组件已卸载时,只调用一次。
插值语法
1.{{}}:叫Mustache语法 也叫胡须语法 双大括号语法
指令(自定义属性)
v-once:
当我们响应的时候不希望这个跟着响应一起变 所以使用该指令
元素和组件(组件后面才会学习)只渲染一次,不会随着数据的改变而改变。
{{message}}
v-html:
我们从服务器请求到的数据本身就是一个HTML代码
如果我们直接通过{{}}来输出,会将HTML代码也一起输出。
但是我们可能希望的是按照HTML格式进行解析,并且显示对应的内容。
deta中的url为url:'点我搜索'
v-text:
用法还不如Mustache 不看也罢。就是直接将这个文本输出 v-text="message"
v-pre:
如果要将{{message}}原封不动的输出,不渲染不传值 就使用 直接在元素中添加 v-pre
直接输出mag而不会调用data中的参数msg{{msg}}
指令事件绑定
- v-on事件监听
- v-on 指令可以缩写为 @ 符号。
- 事件处理程序中可以有多个方法,这些方法由逗号运算符分隔
- Vue 允许为 v-on 在监听键盘事件时添加按键修饰符
只有在 keyCode 是 13 时调用 .submit())
.enter
.tab
.delete (捕获 "删除" 和 "退格" 键)
.esc
.space
.up
.down
.left
.right
系统修饰键:
.ctrl
.alt
.shift
.meta
鼠标按钮修饰符:
.left
.right
.middle
{{conter}}
v-on的修饰符
我是文本
- v-bind
在实际开发中元素的某些属性值都不是固定的,所以我们要动态的生成 所以我们使用v-bind- 让v-bind来指示那个属性需要动态绑定 v-bind:src="imgurl"
- 语法糖的写法 直接:src="imgurl"
- v-bind 在处理 class 和 style 时, 表达式除了可以使用字符串之外,还可以是对象或数组。
1.对象
结果为:
2.数组
--使用template标签
我是组件
这两种方法都使用id来连接 例如在全局组件中 是这样的
Vue.component('my-cpn',{
template:'#cpn'
})
分离出模板后 觉得模板中的数据因该是动态可修改的
使用的是组件数据中的data 例如在全局组件中 是这样的
Vue.component('my-cpn',{
template:'#cpn',
data(){
return{
message:'我是动态可变的'
}
}
})
形态1
//3.将组件写到合适位置上
形态2
我使用的是template标签的方式分离模板
我使用的是template标签的方式分离模板
父子组件
app里面有cpn2 ,cpn2里面有cpn1
父子之间传值(重要)
1.父传子
- {{items}}
{{cmassage}}
2.子传父
插槽
组件的插槽是为了让我们封装的组件更加具有扩展性
让使用者可以决定组件内部的一些内容到底展示什么
插槽的使用
我是p标签
我是span标签 我通过插槽来改变我的
我是子组件
我想显示我每个(模板)下面那个都不一样
结果显示
我是子组件
我想显示我每个(模板)下面那个都不一样
我是p标签
我是子组件
我想显示我每个(模板)下面那个都不一样
我是默认
我是子组件
我想显示我每个(模板)下面那个都不一样
我是span标签 我通过插槽来改变我的
具名插槽
中间标题
左边
中间
右边
const app = new Vue({
el: '#app',
data: {
meassage: '我是数据'
},
components: {
cpn: {
template: '#cpn'
}
}
})
模块化
在实际开发中 一般都是多人开发 如果像以前使用js开发 每个人都有自己的js 在最终导入项目的时候
可能会产生命名冲突 例如小红的flag和小明的flag冲突了 几千代码,几十个js,找起来不好找。这时候使用匿名函数不能在同一个人创建的多个js中引用,所以使用模块化思想,
这里使用的模块化就是nodejs的自定义模块(我的理解)
但是随着js的数量增多 需要导来导去的 将js之间的关系网变得复杂 我们需要webpack来帮助我们打包(就是给我们梳理管理网 将一些css/less/png...等解析为浏览器能识别的代码) 会生成一个文件夹,在项目中直接引用,就会为你部署,然后浏览器就能正常运行
使用Webpack
Webpack是前端资源构建工具,是一个静态打包工具。
就是我们在使用less/jqury/xxx等当渲染到页面的时候,浏览器是不能识别的,我们需要借助各种工具,将less转化为css,将jqury转换为js等,比如将less转化为css我们可以使用less-css插件,但是这么多,我们引入了构建(大的,里面包括了各种转化工具)。
*规范使用vue
el和template模板的关系是什么呢?
在我们之前的学习中,我们知道el用于指定Vue要管理的DOM,可以帮助解析其中的指令、事件监听等等。
而如果Vue实例中同时指定了template,那么template模板的内容会替换掉挂载的对应el的模板。
--首先我们要知道在实际开发中不是在index.html中直接将{{template}}写在里面
--->在vue中写template:{模板}因为最后这个template会替换在index.html中App的代码,data:{数据}
--->使用组件 将template:{模板}定义为组件App,还要将数据拿过来,在Vue中写components:{App},并且将template该为{ }
--->还能在src中创建一个vue文件 创建App.js import default={将组件App中的template拿过来},然后在main.js中导入const App = import App form '什么什么app.js'
--->在src中创建一个vue创建一个app.vue将app.js中的template放到template标签中,将data放到name:'App'后面,还能再下面写样式
--->到了这一步你要知道浏览器之前处理css 图片 less ES6->ES5等都要使用loader才能解析,所以.vue也要vue-loader,这部分查看ppt或者去官网vue.js查看vue-loader
我们发现在webpack.config.js中的代码多起来了,有开发依赖(devServer ),生产依赖(plugin),分为三个个js文件(开发生产环境相关的配置,开发时相关的配置,还有公共的配置),把他们分开放在src下的build中
--下载npm i webpack merge --save-dev
--在webpack.config.js中引入 const webpackMerge = require('webpack-merge')
--在下面进行合并module.exports = webpackMerge('公共内容的webpack.config',{plugin})
当然在上面还要将有公共内容的webpack.config的js文件引入
--对于其他的也这样
vue-cli
使用脚手架
1.首先安装
当然你要首先安装淘宝镜像
npm install -g @vue/cli-service-global
2.使用vue create 项目名 安装一个项目
这里我创建的时hello-world 这个创建的是脚手架3,看不见build and config
- 创建后进入我的项目然后 npm run serve能运行
- 使用命名启动本地服务器 vue ui 提供一个用户界面来,用图形化界面来管理配置
runtime-complier和runtime-only
**runtime-compiler和runtime-only的区别
二者中只有main.js文件不同
runtime-compiler
new Vue({
el: '#app',
components: { App },
template: ' '
})
过程:template解析成ast(抽象语法树);ast再编译成render函数;然后转为虚拟dom;最后转化为真实Dom。
template->ast->vdom->DOM
runtime-only:1.性能更多高 2.代码量更少(创建项目时就可看出比上面的小6KB,建议使用)
new Vue({
el: '#app',
render: h => h(App)
//箭头函数相当于下面代码
// render: function (h) {
// return h(App)
// }
})
过程:render函数转为虚拟dom;最后转化为真实Dom。
runtime-only比对runtime-compiler,减少了解析成render函数的过程。vue-template-compiler这个插件帮助了我们做了这个过程。
new Vue({
el: '#app',
// components: { App },
// template: ' '
render: function (createElement) {
//1.普通用法:createElement('标签', {标签的属性}, [显示内容]) 自定义内容
return createElement('h2',
{class: 'box'},
['Hello World'], createElement('button'), ['按钮'])
//2.核心用法:传入组件对象 函数还可以传入组件对象,那么我们就可以吧app组件直接传入
return createElement(App)
}
})
这里的参数好是createElement,在runtime-only中使用的是h
还有的是配置之间的跳转等,建议观看vue clii详解.ppt!!!
路由
路由阶段
1.早期采用后端渲染
当用户输入一个网址,回到服务器中使用一种jsp的技术,来获取html+css+java,通过java来让页面渲染到浏览器上。每当用户输入一个网址就会的取到一个相应的html+css+java.是通过服务器来映射url和页面之间的关系的。这个后端渲染不利于后期维护,因为有java混合在里面代码混乱
后端路由:使用后端来映射url和页面的关系
前后端分离阶段:
当用户输入一个网址,会在静态资源服务器中拿到相应的html+css+js到浏览器,得到一个初步的网页,利用里面的js代码中的ajax到服务器请求数据,每当用户输入一个网址就会在静态资源服务器中得到一个相应的html+css+js
后端只负责拿数据,不负责其他
前端路由:浏览器中的页面大部分都是前端写的js代码在浏览器中执行熏染出来的
单页面富应用阶段:
一个页面只有一个html,当输入一个网址,会在静态资源服务器中拿到一个的html+css+js到浏览器(在静态页面中只有一个html+css+js),通过前端路由来对url和页面进行映射,例如实现页面跳转。这里的服务器也是只连接数据库拿数据
如何实现呢?
- URL的hash也就是锚点(#), 本质上是改变window.location的href属性.
- 我们可以通过直接赋值location.hash来改变href, 但是页面不发生刷新
①. history.pushState() --> 入栈
②. history.replaceState()
③. history.go()
④. history.back() 等价于 history.go(-1) --> 后退
⑤. history.forward() 等价于 history.go(1) --> 前进
综合总结提问
1. 什么是前端渲染, 什么是后端渲染?
前端渲染:
指的是后端返回JSON数据,前端利用预先写的html模板,循环读取JSON数据,拼接字符串(es6的模板字符串特性大大减少了拼接字符串的的成本),并插入页面。
好处:网络传输数据量小。不占用服务端运算资源(解析模板),模板在前端(很有可能仅部分在前端),改结构变交互都前端自己来了,改完自己调就行。
坏处:前端耗时较多,对前端工作人员水平要求相对较高。前端代码较多,因为部分以前在后台处理的交互逻辑交给了前端处理。占用少部分客户端运算资源用于解析模板。
后端渲染:
前端请求,后端用后台模板引擎直接生成html,前端接受到数据之后,直接插入页面。
好处:前端耗时少,即减少了首屏时间,模板统一在后端。前端(相对)省事,不占用客户端运算资源(解析模板)
坏处:占用服务器资源。
前端渲染与后端渲染对比:
后端渲染:
页面呈现速度:快,受限于用户的带宽
流量消耗:少一点点(可以省去前端框架部分的代码)
可维护性:差(前后端东西放一起,掐架多年,早就在闹分手啦)
seo友好度:好
编码效率:低(这个跟不同的团队不同,可能不对)
前端渲染:
页面呈现速度:主要受限于带宽和客户端机器的好坏,优化的好,可以逐步动态展开内容,感觉上会更快一点
流量消耗:多一点点(一个前端框架大概50KB)当然,有的用后端渲染的项目前端部分也有在用框架
可维护性:好,前后端分离,各施其职,代码一目明了。
SEO友好度:差,大量使用ajax,多数浏览器不能抓取ajax数据。
编码效率:高,前后端各自只做自己擅长的东西,后端最后只输出接口,不用管页面呈现,只要前后端人员能力不错,效率不会低
2. 什么是前后端分离?
现在 Web 服务器不再处理任何业务,它接收到请求后,经过转换,发送给各个相关后端服务器,将各个后端服务器返回的,处理过的业务数据填入 HTML 模板,最后发送给浏览器。Web 服务器和后端服务器间,可以选用任何你觉得合适的通信手段,可以是 REST,可以是 RPC,选用什么样的通信手段,这是另一个议题了。
这样,前端人员和后端人员约定好接口后,前端人员彻底不用再关心业务处理是怎么回事,他只需要把界面做好就可以了,后端人员也不用再关系前端界面是什么样的,他只需要做好业务逻辑处理即可。服务的切离,代码管理,服务部署也都独立出来分别管理,系统的灵活性也获得了极大的提升。
注意,这不是个微服务架构,那是另外一个议题了
总结,任何系统架构设计,实际上是对组织结构在系统上进行映射,前后端分离,就是在对前端开发人员和后端开发人员的工作进行解耦,尽量减少他她们之间的交流成本,帮助他她们更能专注于自己擅长的工作。
最后是几个常见误解的说明:
前后端分离是说浏览器和后端服务分离吗?
不是,前后端分离里的前端不是浏览器,指的是生成 HTML 的那个服务,它可以是一个仅仅生成 HTML 的 Web 服务器,也可以是在浏览器中通过 JS 动态生成 HTML 的 单页应用。实践中,有实力的团队往往在实现前后端分离里时,前端选用 node 服务器,后端选用 C#、Java 等(排名不分先后)
前后端分离是种技术吗?
不是,前后端分离是种架构模式,或者说是最佳实践。所谓模式就是大家这么用了觉得不错,你可以直接抄来用的固定套路。
前后端分离是最佳实践吗?
看你团队和项目的情况,如果是短平快的小项目,真的没必要。如果是面向简历开发,那绝对在任何时候都应该使用前后端分离这种架构。
- 什么是前端路由, 什么是后端路由?
A. 什么是前端路由?
很重要的一点是页面不刷新,前端路由就是把不同路由对应不同的内容或页面的任务交给前端来做,每跳转到不同的URL都是使用前端的锚点路由. 随着(SPA)单页应用的不断普及,前后端开发分离,目前项目基本都使用前端路由,在项目使用期间页面不会重新加载
B. 什么是后端路由?
浏览器在地址栏中切换不同的url时,每次都向后台服务器发出请求,服务器响应请求,在后台拼接html文件传给前端显示, 返回不同的页面, 意味着浏览器会刷新页面,网速慢的话说不定屏幕全白再有新内容。后端路由的另外一个极大的问题就是 前后端不分离。
优点:分担了前端的压力,html和数据的拼接都是由服务器完成。
缺点:当项目十分庞大时,加大了服务器端的压力,同时在浏览器端不能输入制定的url路径进行指定模块的访问。另外一个就是如果当前网速过慢,那将会延迟页面的加载,对用户体验不是很友好。
C. 什么时候使用前端路由?
在单页面应用,大部分页面结构不变,只改变部分内容的使用
D. 前端路由有什么优点和缺点?
优点:
用户体验好,和后台网速没有关系,不需要每次都从服务器全部获取,快速展现给用户
可以再浏览器中输入指定想要访问的url路径地址。
实现了前后端的分离,方便开发。有很多框架都带有路由功能模块
缺点:
使用浏览器的前进,后退键的时候会重新发送请求,没有合理地利用缓存
单页面无法记住之前滚动的位置,无法在前进,后退的时候记住滚动的位置
vue-router
vue-router是基于路由和组件的
- 路由用于设定访问路径, 将路径和组件映射起来.
- 在vue-router的单页面应用中, 页面的路径的改变就是组件的切换.
使用vue-router
1.安装npm install vue-router --save
2.在模块工程中使用
3.挂载路由
**在router文件中**
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'
// 1.使用vue.use安装路由
Vue.use(VueRouter)
// 配置组件和路径的映射关系
const routes = [
{
path: '/',
redirect: Home
},
//redirect是重定向, 也就是我们将根路径重定向到/home的路径下, 这样就可以得到我们想要的结果了.
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/about',
name: 'About',
// 懒加载,当要使用这个组件的时候才加载出来
component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
}
]
// 2.创建路由对象
const router = new VueRouter({
// 使用history的方式来不刷新来修改地址
mode: 'history',
base: process.env.BASE_URL,
routes
})
// 3.导入路由,在实例中使用
export default router
**在合适组件中使用路由**
注意
: 该标签是一个vue-router中已经内置的组件, 它会被渲染成一个标签.
: 该标签会根据当前的路径, 动态渲染出不同的组件.
在路由切换时, 切换的是挂载的组件, 其他内容不会发生改变.
-
还有一些其他属性:
在使用路由的组件中通过this.$router获取路由(?)
动态路由
就是有些时候我们在使用路由的时候希望能将一些信息(在使用路由那个组件中的信息)显示在路径上
路由中
{ path: "/user/:userId", component: User }
在使用路由那个组件中
用户
data() {
return {
userId: "lisi",
};
},
路由组件中
我是用户界面
我是用户相关信息
{{userId}}
数据在使用路由的那个组件中,在router中路径后面要加参数,点击进入User页面后, 想要拿到User的后缀(userId)
this.route: 谁处于活跃状态, 拿到谁
上面的代码照写
嵌套路由
嵌套路由是一个很常见的功能
比如在home页面中, 我们希望通过/home/news和/home/message访问一些内容.
一个路径映射一个组件, 访问这两个路径也会分别渲染两个组件.
mport Vue from ‘vue’
import VueRouter from ‘vue-router’
const Home = () => import('../components/Home.vue')
const HomeNews = () => import('../components/HomeNews.vue')
const About = () => import('../components/About.vue')
Vue.use(VueRouter)
const routes = [
{
path: '/',
redirect: './home'
},
{
path: '/home',
component: Home,
children: {
{
path: 'news',
component: HomeNews
}
}
},
{
path: '/about',
component: About
}
]
const app = new VueRouter({
router,
mode: 'history'
})
export default router
在嵌套组件内部使用< router-view>标签.
-- Home.vue文件
我是首页
// 要写完整的路径
使用
- 在路由映射中将嵌套的路由写在使用嵌套路由的路径下的children中配置
- 在使用嵌套路由的路由组件中使用嵌套路由(要写完整的路径)
传递参数
- 1.params的类型
配置路由格式: /router/:id
传递的方式: 在path后面跟上对应的值
传递后形成的路径: /router/123, /router/ab
就是动态路由的传递方式
- 2.query的类型
配置路由格式: /router, 也就是普通配置
import Vue from ‘vue’
import VueRouter from ‘vue-router’
const Home = () => import('../components/Home.vue')
const User = () => import('../components/User.vue')
Vue.use(VueRouter)
const routes = [
{
path: '/',
redirect: './home'
},
{
path: '/user',
component: User
}
]
const app = new VueRouter({
router,
mode: 'history'
})
export default router
传递的方式: 对象中使用query的key作为传递方式
-- User.vue文件
传递后形成的路径: /router?id=球球, /router?id=abc
{{$route.params}}
{{$route.query.name}}
导航守卫
使用路由的时候只有一个Index,如何实现跳转的时候标题跟着变呢?
当每个组件被创建的时候都会进入到created()这生命周期中,所以我们可以在这个里面修改标题
但是这样的话每次都要到每个.vue文件中添加这个,麻烦。我们可以监听,使用全局导航守卫。
--在index.js中添加router.berforeEach((to,form,next)=>{...next()})其中在里面必须执行next()。我们可以将当前的标题更改为to的标题,因为to是route类型,会拿到当前点击的那个路由。这时我们需要在每个.vue的路由中添加元数据meta:{title:'关于'}
vue-router提供的导航守卫主要用来监听监听路由的进入和离开的.
vue-router提供了beforeEach和afterEach的钩子函数, 它们会在路由即将改变前和改变后触发.
Vue.use(VueRouter)
// 定义路由
const routes = [
{
path:'',
redirect:'/about',
meta:{
title:'关于'
},
},
{
path: '/home',
component: Home,
meta:{
title:'首页'
},
children:[
{
path:'news',
component:news,
meta:{
title:'新闻'
}
},
{
path:'message',
component:message,
meta:{
title:'信息'
}
}
]
},
{
path: '/about/:isab',
component: About,
// component: () => import( '/about/:isab')
meta:{
title:'关于大'
}
}
]
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
})
router.beforeEach((to,from,next)=>{
document.title = to.meta.title;
// 有时候娶不到是undinfined 要在to下面的那个matched中的meta中才行
// 从from跳转到to
document.title = to.matched[0].meta.title;
next();
})
export default router
导航钩子的三个参数解析:
- to: 即将要进入的目标的路由对象
- from: 当前导航即将要离开的路由对象
- next: 调用该方法后, 才能进入下一个钩子
导航守卫补充
- berforeEach():跳转前回调
如果是后置钩子, 也就是afterEach, 不需要主动调用next()函数.
上面我们使用的导航守卫, 被称之为全局守卫
路由独享的守卫
组件内的守卫
// 后置守卫(guard)
router.afterEach((to, from) => {
})
keep-alive
keep-alive 是 Vue 内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染.
就是当点击首页里面的消息后,点击about,再点击Home消息界面的内容会保留.保持活跃状态,不要每次都要重新创建
这就要触及生命周期的理解,当点击了消息的时候,会触发created(),但是当点击了about后,就会触发destroyed()会消亡这个消息界面.
它们有两个非常重要的属性:
include - 字符串或正则表达,只有匹配的组件会被缓存
exclude - 字符串或正则表达式,任何匹配的组件都不会被缓存
router-view 也是一个组件,如果直接被包在 keep-alive 里面,所有路径匹配到的视图组件都会被缓存
// 所有路径匹配到的视图组件都会被缓存
vuex
就是当多个组件想要共享变量(状态管理比如登录状态),vuex就像一个大管家,来管理这些组件。
创建的对象来管理,是响应式的。但是也不是全部都放里面,父子组件之间就不用了.
就是如果有一个变量,按照组件树的方式一个一个传下来,很麻烦。使用vuex就直接将这个变量放在state(状态)中,就能通过$store.state
.变量名来响应式获取或者更改。
但是在组件中最好不要直接通过$store.state.变量名来更改变量的值,因为组件多了,不知道谁改的。我们要通过发布一个行为,在行为action里面提交到mutations,通过mutation来改,因为mutation有一个浏览器插件devtools,能每次记录修改状态的日志。但是只能接收同步的,如果要接收异步的话,在action中操作修改后,提交到mutation。
在浏览器插件中下载,就能在控制台看到vuex
使用Vuex
1.下载 npm install vuex --save
2.创建state文件夹写vuex
import Vue from "vue"
import Vuex from "vuex"
Vue.use(Vuex);
export default new Vuex.Store({
state:{
1.使用了单一状态树来管理应用层级的全部状态。
2.单一状态树能够让我们最直接的方式找到某个状态的片段,而且在之后的维护和调试过程中,也可以非常方便的管理和维护。
count:5
},
getters:{
1.getters 是store的计算属性,类似于computed,对state里的数据进行一些过滤,改造等等
powerCount:count => state.count * 10
}
mutations:{
1.里面写回调函数(同步函数),默认参数为state
2.可理解为更改state的函数集
3.多个参数,用对象形式传过来用payload接收
addition(state,payload){
state.count++
}
},
actions: {
1.类似于mutations,必须通过mutations来操作,只是异步操作,如网络请求等
2.context是和store对象具有相同方法和属性的对象.
3.也就是说, 我们可以通过context去进行commit相关的操作, 也可以获取context.state等.
styaddition(context,payload){
setTimeout(()=>{
//交给mutations
context.commit('addition',payload)
},3000)
}
},
modules: {
1.里面还可以有state,mutations,actions,modelue
2.前面还有引入moduleA,moduleB
moduleA,
moduleB
}
})
moduleA moduleB
const moduleA = {
state: {
name: "zhangsan"
},
mutations: {
// 不能和store的mutations的函数名重复 优先在下面找
updateName(state, payload) {
state.name = payload;
}
},
actions: {
// 这里的context指的是 模块中的 mutations
console.log(context); //这里的context可以拿到很多东西的
aUpdateName(context) {
setTimeout(() => {
context.commit("updateName", "wangwu");
}, 1000);
}
},
getters: {
fullname(state) {
return state.name + 111;
},
// 嵌套调用getters
fullname2(state, getters) {
return getters.fullname + "222";
},
// 引用根state中的counter 添加一个参数rootState
fullname3(state, getters, rootState) {
return getters.fullname2 + rootState.counter;
}
}
};
const moduleB = {
state: {},
mutations: {},
actions: {},
getters: {}
};
// 可以进行抽离
modules: {
a: moduleA,
b: moduleB
}
3.加载到项目中
在main.js中
import { createApp } from "vue";
import App from "./App.vue";
import store from "./store";
createApp(App).use(store).mount("#app");
4.使用vuex
在某个组件中
{{$store.state.counter}}
count*10的count{{$store.getters.powerCount}}