Vue基础
1. Vue的基本原理当一个Vue实例创建时,Vue会遍历data中的属性,用 Object.defineProperty(vue3.0使用proxy )将它们转为 getter/setter,并且在内部追踪相关依赖,在属性被访问和修改时通知变化。 每个组件实例都有相应的 watcher 程序实例,它会在组件渲染的过程中把属性记录为依赖,之后当依赖项的setter被调用时,会通知watcher重新
MVVM
MVVM 分为 Model、View、ViewModel:
- Model代表数据模型,数据和业务逻辑都在Model层中定义;
- View代表UI视图,负责数据的展示;
- ViewModel负责监听Model中数据的改变并且控制视图的更新,处理用户交互操作;
Model和View并无直接关联,而是通过ViewModel来进行联系的,Model和ViewModel之间有着双向数据绑定的联系。因此当Model中的数据改变时会触发View层的刷新,View中由于用户交互操作而改变的数据也会在Model中同步。
vue
1.数据与视图分离 (数据驱动视图)
2.性能更高,减少dom操作(耗费性能) diff (虚拟dom对比)
3.组件化
虚拟DOM的优缺点:
- 缺点
- 首次渲染大量DOM时,由于多了一层虚拟DOM的计算,会比innerHTML插入慢
- 优点
- 减少了dom操作,减少了回流与重绘
- 保证性能的下限,虽说性能不是最佳,但是它具备局部更新的能力,所以大部分时候还是比正常的DOM性能高很多的
双大括号插值,值一定是data中的变量 (数据)
双大括号其实提供了一个js执行环境,可以写任意js表达式,不识别html结构
指令:都是以v-开头的,去实现特定功能,写在元素开始标签中的
注意:所有指令后面的引号是提供一个js执行环境的,不是字符串的引号,写字符串必须加单引号;
1.v-html="数据" 把一段html结构渲染到它所绑定的元素中 (识别标签)
2.v-text = {{}}
3.v-bind:属性="数据" 简写为 :属性="数据" (动态绑定变量)
特殊情况:class
1.可以绑定一个字符串,字符串名就是class名
2.可以绑定一个对象
对象的属性名就是class名,对象的属性值是布尔,代表是否有这个class
3.可以绑定一个数组
数组里是变量名,变量值就是class名字
特殊情况:style
1.绑定到一个对象,对象就是样式对象
2.绑定到一个数组,就是绑定到多个样式对象
3.v-on:事件名="函数名" 缩写为@事件名="函数名"
样式穿透:
父元素 ::v-deep 内部元素(通过f12查看元素类名)
//如果使用的是css,可以用下面这种
外层容器 >>> 组件 {}
//但在css预处理器中用上面这种是无法生效的,类似在scss和less中,我们可以用下面这种。
外层容器 /deep/ 组件 {}
method函数中,要想改数据的话,不要用箭头函数
this.变量名=新数据
this代表的是当前vue实例
模板中拿不到window对象/vue实例
只有传参函数名才可以加()
引号中的变量必须是data中或methods中定义过的;
事件对象:
5.v-if v-else-if v-else条件渲染 真正的条件渲染
6.v-show 条件渲染 只是基于样式的切换
区别:v-show有更高的初始渲染消耗 v-if有更高的切换消耗
7.v-for=“item in array” 列表渲染
可以循环一个数组,item代表每一项 (item,index)
如果需要修改,选择数组自带的方法,或者使用Vue.set(要修改的数组,角标,新值)
直接重新赋值
可以循环一个对象,item代表每一项的值 (value,key,index)
如果需要添加对象属性 Vue.set(要修改的对象,属性名,属性值)
可以循环一个整数
嵌套循环(嵌套循环避免变量重复)
v-for优先级高于v-if
避免v-if和v-for一起用:
可以v-if嵌套v-for
如果非要一起用,可以把v-if放到外层元素,或者不用v-if,先在计算属性中筛选出数据,然后在v-for
<template>
<div id="app">
<ul>
<li v-for="item in info" :key={item}>{{item}}->偶数</li>
</ul>
</div>
</template>
<script>
export default {
data () {
return {
Nums: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
}
},
computed: {
info () {
return this.Nums.filter(i => i % 2 === 0)
}
}
}
</script>
v-for必须定义key:
不能用index和random
diff算法通过tag和key判断是否是sameNode
减少渲染次数,提高渲染性能
8.v-model:表单的双向绑定
v-model默认绑定到表单的value属性
多选框: 单个复选框,绑定到布尔值,多个复选框,绑定的是数组
单选框:值直接绑定到值
下拉选择框:直接绑定到值
实现:oninput/onchange事件 事件对象
v-model的原理
vue 双向数据绑定是通过 数据劫持 结合 发布订阅模式的方式来实现的, 也就是说数据和视图同步,数据发生变化,视图跟着变化,视图变化,数据也随之发生改变;
核心:关于VUE双向数据绑定,其核心是 Object.defineProperty()方法。
// var obj = {
// a: 1,
// c: [1, 2, 3],
// set f(value) {
// console.log("set")
// this.a = value
// },
// get f() {
// console.log("get")
// return this.a
// }
// }
// Object.defineProperty(obj, "h", {
// value: 10
// })
// var obj1 = JSON.parse(JSON.stringify(obj))
// console.log(obj)
// console.log(obj1)
var obj={a:1,b:2};
var hander={
set:(target,key,value)=>{
console.log("set",target,key,value)
target[key]=value
},
get:(target,key)=>{
console.log("get")
return target[key]
},
has:(target,key)=>{
console.log("has")
return key in target
}
}
var p=new Proxy(obj,hander);
p.c=20;
console.log(p.c)
console.log("c" in p)
methods:里面写所有的函数 (事件)
computed:计算属性:将逻辑运算写在这里,避免在模板里面写过多js逻辑
计算属性是个函数,一定需要return一个值的
计算属性里面的函数一定是她所依赖的值发生变化的才会去执行 (提高性能)
避免计算属性与data中数据重复
过滤器:filter
watch:监听器 用来监测一个数据,只要数据发生变化,就会执行一个函数
函数名为数据名
watch都可以监听哪些值:
1.data中的数据
2.props
3.$route
4.$emit
5.computed
computed与methods,watch区别:
- method 调用总会执行该函数。数据驱动视图(视图重新渲染) 主动调用 做事
- computed 计算属性 :有缓存,只有在它的相关依赖发生改变时会自动重新求值,适用于大量计算的场景 当一个属性受多个属性影响的时候使用
- watch 侦听器 : 无缓存,每当监听的数据变化时都会执行回调进行后续操作。 做事 一次只能监听一个,页面重新渲染时值不变化也会执行;当一条数据影响多条数据的时候使用
<template>
<div>
<p>{{msg}}</p>
<p @click="change">改变</p>
<p>{{info}}</p>
</div>
</template>
<script>
export default {
data(){
return {
msg:111,
}
},
methods:{
change(){
this.msg+=1
}
},
watch:{
msg: {
handler(oldValue,newVal) {
console.log("msg",oldValue,newVal)
},
deep: true // 深度监听
}
},
computed:{
info(old,new){
return this.msg
}
},
}
</script>
事件修饰符
- .stop:等同于 JavaScript 中的
event.stopPropagation()
,防止事件冒泡; .prevent
:等同于 JavaScript 中的event.preventDefault()
,防止执行预设的行为- .enter
- .trim
组件
只能使用自己的配置项(data,methods,watch,computend,components)
组件的注册
1.全局注册:
Vue.component("组件名",{
template:"html代码",
data(){
return{}
}
})
其他的完全跟vue实例一样的
注意:
data必须是函数,保证组件之间的数据必须独立性,根实例只有一个(数据为对象)
对象为引用类型,当重用组件时,由于数据对象都指向同一个data对象,当在一个组件中修改data时,其他重用的组件中的data会同时被修改,而是用返回对象的函数,每次返回的嗾使一个新对象,引用地址不同,不会出现这个问题;
template必须只有一个根节点
2.局部注册:
1.先定义组件配置选项,
2.在要使用的组件中去注册
<div id="app">
<my-foot></my-foot>
</div>
<script>
let foot = {
template: `<div><h1 >{{msg}}</h1></div>`,
data() { return { msg: "局部组件" } },
}
new Vue({
el:"#app",
components:{
"my-foot":foot //局部注册
}
})
Vue.component("foot",foot) //全局注册
</script>
3.组件之间的数据传递(父子组件的单向数据流)
(1)父--子 props
- 父组件动态绑定:src=src
- 子组件定义props
- 子组件规定该属性用在哪
- 组件调用在开始标签里面传递来自父组件的数据
props:可以是数组,可以是对象{属性名:类型}(对象可以对数据进行检测)
(2)子--父:自定义事件$emit
- 在父组件调用的子组件开始标签绑定一个自定义事件@src=“src(msg)”
- 在该子组件内部定义方法,该方法要通过$emit去触发自定义事件,并且把自己的数据作为$emit的第二个参数传递进去 $emit(@src,"222")
- 自定义事件触发时要做的事定义在父组件的methods中,在此方法里只需要将自己的数据更新为传进来的参数即可
(3)ref / $refs(dom操作)
ref
: 这个属性用在子组件上,它的引用就指向了子组件的实例。可以通过实例来访问组件的数据和方法。
<child ref="child"></component-a>
console.log(this.$refs['child']);
通过 ref 属性给子组件设置一个名字。父组件通过 $refs 组件名来获得子组件,子组件通过 $parent 获得父组件,这样也可以实现通信。
$nextTick()方法:
异步渲染,待dom渲染完毕后再回调
this.$nextTick(() => { console.log(222); console.log(this.$refs['hello']); });
(4)事件总线
import Vue from 'vue'
var bus=new Vue()
发布
<p @click="get">发布</p>
get(){
bus.$emit("get",this.msgg)
}
订阅
bus.$on("get",(data)=>{
this.ms=data
})
及时销毁 否则可能内存泄漏
beforeDestroy(){
bus.$off("get",this.msgg)
}
获取自定义属性的属性值
第一种:
<div data-msg="222" ref="ww"></div>
this.$refs.ww.dataset.msg
第二种:
<span data-num="21" @click="getData($event)">55</span>
e.target.getAttribute('data-num')
4.slot
slot又名插槽,是Vue的内容分发机制,组件标签中的所有内容会渲染到插槽位置上,让组件更灵活
具名插槽:没有名字的插槽默认名字是default
v-slot可以缩写为#
作用域插槽:
如果插槽模板中想使用该组件内部的数据,首先需要在模板的插槽中定义v-bind:属性=“数据”
<slot name="before" :ss="'2222'"></slot>
组件调用的地方插槽通过 v-slot:属性=“prop” prop代表所有属性的集合
<template v-slot:before="prop">
<h1>{{prop.ss}}</h1>
</template>
template 包裹标签,运行时不会被渲染
//调用:
<jyn-button>插槽</jyn-button>
//jyn-button.vue
<div>
<slot></slot>
</div>
具名插槽:
//调用:
<jyn-button>
<template v-slot="a">
插槽
</template>
</jyn-button>
//jyn-button.vue
<div>
<slot name="a"></slot>
</div>
5.组件的生命周期:其实就是在某个时间段会自动触发的事件
Vue 实例有⼀个完整的⽣命周期,也就是从开始创建、初始化数据、编译模版、挂载Dom -> 渲染、更新 -> 渲染、卸载 等⼀系列过程,称这是Vue的⽣命周期。
- beforeCreate(创建前):创建实例前
- created(创建后) :实例创建完成, data、computed、watch、methods 等都配置完成,但是此时渲染得节点还未挂载到 DOM
- beforeMount(挂载前):编译模板,把data里面的数据和模板生成html
- mounted(挂载后):挂载DOM对象
- beforeUpdate(更新前):响应式数据更新时调用,此时虽然响应式数据更新了,但是对应的真实 DOM 还没有被渲染。
- updated(更新后) :此时 DOM 已经根据响应式数据的变化更新了
- beforeDestroy(销毁前):实例销毁之前调用。
this
仍能获取到实例。 - destroyed(销毁后):实例销毁后调用,调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。(解绑自定义事件,清除定时器,解绑自定义的dom事件)
keepalive:
keep-alive是vue内置的一个组件,而这个组件的作用就是能够缓存不活动的组件
要使用activated与deactivated生命周期来获取当前组件是否处于活动状态
vue父子组件生命周期的执行顺序(面试中问道)
加载渲染过程
父beforeCreate->父created->父beforeMount->子beforeCreate->子created->子beforeMount->子mounted->父mounted
子组件更新过程
父beforeUpdate->子beforeUpdate->子updated->父updated
父组件更新过程
父beforeUpdate->父updated
销毁过程
父beforeDestroy->子beforeDestroy->子destroyed->父destroyed
动态组件
<component :is = "temp"></component>
vue/cli搭建vue脚手架的步骤:
npm install -g @vue/cli 全局安装vue脚手架
vue create 项目名字
脚手架生成文件说明
- 单文件组件:
以.vue结尾的包含html css js 的一个页面的组件 ,默认自动导出
(插件 vue vscode snippets) vbase-css 自动生成.vue结构
组件名大写 Test
组件的样式是全局的
- html 写在template标签里面,必须保证有一个根节点
- js写在script标签里面
- css写在style标签里,style里面可以添加一个scoped,代表该样式仅在当前组件内生效
- render: h => h(App)的原理(接收一个组件,创造出来,挂载到div里面)
- 组件嵌套
views文件夹写入组件
app.vue
导入组件(import xxx from "./views/xxx.vue")
注册组件(components:{xxx}
调用组件<xxx></xxx>
没有内容的标签可以自闭和标签<test/>
@代表src目录
路由:npm install vue-router
高内聚(相同的东西),低耦合(不同的东西)
1.vue引入插件
vue引入的所有插件都需要注册 Vue.use(插件名)
2.VueRouter实例化
new VueRouter({接受路由配置项当参数})
3.路由配置项:
就是规定路径和组件的对应关系子路由如果不加斜线,那么默认在上级路由上叠加,如果加了斜线,那么前面必须带上上级路由
注意:页面与路由一定是一一对应的,一个页面一定要对应路由,否则找不到 (地址-->视图)
4.路由懒加载:
提高性能 component: () => import('../views/xxx.vue')
6.使用路由的步骤
(1)定义路由组件 (单文件组件)
(2) 定义路由配置项(path,name,meta,component)
(3) 创建路由实例,传入配置项
(4) 挂载
7.路由的视图显示:
路由必须要有router-view 来规定路由的显示位置 <router-view/>
8.嵌套路由:
哪个组件还有子路由,需要在该组件内部定义router-view,代表该组件的子路由显示在该位置上。
9.路由的跳转
$router 是“路由实例”对象包括了路由的跳转方法,钩子函数等
通过标签跳转:
<router-link to="/about"></router-link> 字符串路径
<router-link :to="{path:"路径"}"></router-link> 对象路径
<router-link :to="{name:"名字"}"></router-link> 对象名字
编程式导航:
this.$router.push(字符串路径)
this.$router.push({path:"路径"})
this.$router.push({name:"名字"})
this.$router.replace(面试中问道)
10. Vue-router跳转和location.href有什么区别
●使用 location.href= /url 来跳转,简单方便,但是刷新了页面;
●使用 router.push( /url ) 来跳转,使用了 diff 算法,实现了按需加载,减少了 dom 的消耗。vue-router用了 history.pushState() 。
11.动态路由匹配(数据跨页面传递):
$route 是“路由信息对象”,
路由信息参数{name:"组件的名字",fullPath:"完整路径",path:"路径",matched:[匹配上的所有路由],meta:"路由元信息",params:"动态路径参数",query:"查询参数"}
在路径后面加/:名字
任一路径只匹配一个页面
注意:只改后面动态路径参数是不会重新触发组件生命周期的
this.id = this.$route.params.id;
12.query和params的区别
注意:query刷新不会丢失query里面的数据 params刷新会丢失 params里面的数据。
//params传参,使用name跳转 post
this.$router.push({
name:'second',
params: {
queryId:'20180822',
queryName: 'query'
}
})
//query传参,使用path跳转 get
this.$router.push({
path:'second',
query: {
queryId:'20180822',
queryName: 'query'
}
})
//query传参接受
this.queryName = this.$route.query.queryName;
this.queryId = this.$route.params.queryId;
13.路由的重定向和别名(路径隐藏):
1.重定向的意思是,当用户访问/Home时,URL 将会被替换成/Test,然后匹配路由为 /b
const routes = [
{
path: '/Home',
redirect: '/Test', //重定向
name: 'Home',
components: {a:Home,b:About}, // 命名路由
},
redirect:"要跳转的路径"
2、别名
/a 的别名是 /b,意味着,当用户访问 /b 时,URL 会保持为 /b,但是路由匹配则为 /a,就像用户访问 /a 一样
const router = new VueRouter({
routes: [
{ path: '/a', component: A, alias: '/b' }
]
})
14、路由模式
1. hash模式
简介: hash模式是开发中默认的模式,它的URL带着一个#,例如:http://www.abc.com/#/vue,它的hash值就是#/vue
。
特点:hash值会出现在URL里面,但是不会出现在HTTP请求中,对后端完全没有影响,因此改变 hash 不会重新加载页面。。
2. history模式
简介: history模式的URL中没有#,它使用的是传统的路由分发模式,即用户在输入一个URL时,服务器会接收这个请求,并解析这个URL,然后做出相应的逻辑处理。
特点: 当使用history模式时,URL就像这样:http://abc.com/user/id。相比hash模式更加好看。但是,history模式需要后台配置支持。如果后台没有正确配置,访问时会返回404。
如果想要切换到history模式,就要进行以下配置(后端nginx配置转发):
const router = new VueRouter({
mode: 'history',
routes: [...]
})
15. 如何获取页面的hash变化
(1)监听$route的变化
// 监听,当路由发生变化的时候执行
watch: {
$route: {
handler: function(val, oldVal){
console.log(val);
},
// 深度观察监听
deep: true
}
},
(2)window.location.hash读取#值
window.location.hash 的值可读可写,读取来判断状态是否改变,写入时可以在不重载网页的前提下,添加一条历史访问记录。
16.路由优先级
path:"*",匹配404页面,放在最后一个路由
17.导航守卫
全局前置守卫
const router = new VueRouter({ ... })
router.beforeEach((to, from, next) => {
// ...
})
每个守卫方法接收三个参数:
- to: Route: 即将要进入的目标 路由对象
- from: Route: 当前导航正要离开的路由
- next: Function: 一定要调用该方法来resolve这个钩子。执行效果依赖next方法的调用参
- next(): 进行管道中的下一个钩子。如果全部钩子执行完了,则导航的状态就是 confirmed (确认的)。
next(false)
: 中断当前的导航。如果浏览器的 URL 改变了 (可能是用户手动或者浏览器后退按钮),那么 URL 地址会重置到from
路由对应的地址。- next('/') 或者 next({ path: '/' }): 跳转到一个不同的地址。当前的导航被中断,然后进行一个新的导航。
确保 next 函数在任何给定的导航守卫中都被严格调用一次;
//死循环
router.beforeEach((to,from,next)=>{
next("/Test")
})
router.beforeEach((to,from,next)=>{
if(to.path=="/Test"){
next()
}
next("/Test")
})
组件内的守卫:
const Foo = {
template: `...`,
beforeRouteEnter(to, from, next) {
// 在渲染该组件的对应路由被 confirm 前调用
// 不能!获取组件实例 `this`
// 因为当守卫执行前,组件实例还没被创建
next(vm => {
// 通过 `vm` 访问当前组件实例
})
},
beforeRouteUpdate(to, from, next) {
// 在当前路由改变,但是该组件被复用时调用
// 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
// 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
// 可以访问组件实例 `this`
},
beforeRouteLeave(to, from, next) {
// 导航离开该组件的对应路由时调用
// 可以访问组件实例 `this`
}
}
axios:Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。
npm i axios --save-dev
关于插件的注册:
1.如果是给vue量身定制的,要通过Vue.use(插件名)去注册 vue-router vuex
2.如果不是给vue量身定制的,通过挂载到原型上去注册 axios echarts
//main.js 继承 根实例加$
import axios from 'axios'
Vue.prototype.$axios=axios //axios挂载到原型上
get/post请求
//get请求
$axios.get('/user', {
params: {
ID: 12345
}
})
.then(response=>{
console.log(response);
})
.catch(error=>{
console.log(error);
});
//post请求
$axios.post('/user', {
firstName: 'Fred',
lastName: 'Flintstone'
})
自定义请求
var instance = axios.create({
// `url` 是用于请求的服务器 URL
url: '/user',
// `method` 是创建请求时使用的方法
method: 'get', // 默认是 get
// `baseURL` 将自动加在 `url` 前面,除非 `url` 是一个绝对 URL。
// 它可以通过设置一个 `baseURL` 便于为 axios 实例的方法传递相对 URL
baseURL: 'https://some-domain.com/api/',
// `headers` 是即将被发送的自定义请求头
headers: {'X-Requested-With': 'XMLHttpRequest'},
// `params` 是即将与请求一起发送的 URL 参数
// 必须是一个无格式对象(plain object)或 URLSearchParams 对象
params: {
ID: 12345
},
// `data` 是作为请求主体被发送的数据
// 只适用于这些请求方法 'PUT', 'POST', 和 'PATCH'
// 在没有设置 `transformRequest` 时,必须是以下类型之一:
// - string, plain object, ArrayBuffer, ArrayBufferView, URLSearchParams
// - 浏览器专属:FormData, File, Blob
// - Node 专属: Stream
data: {
firstName: 'Fred'
},
// `timeout` 指定请求超时的毫秒数(0 表示无超时时间)
// 如果请求话费了超过 `timeout` 的时间,请求将被中断
timeout: 1000,
});
拦截器(拦截器必须在get请求之前)
// 添加请求拦截器
instance.interceptors.request.use(config=>{
//全局的 1、带参数 3、请求验证参数
config.params.token="111"
return config;
}, error=>{
// 对请求错误做些什么
return Promise.reject(error);
});
// 添加响应拦截器
axios.interceptors.response.use(response => {
//判断请求是否成功
return response;
}, error=>{
// 对响应错误做点什么
return Promise.reject(error);
});
vue.config.js配置跨域(与src目录平行)
module.exports = {
devServer: {
proxy: {
'/api': {
/* 目标代理服务器地址 */
target: 'https://api.binstd.com/recipe/search',
/* 允许跨域 */
changeOrigin: true,
pathRewrite: {
"^/api": ""
}
},
},
},
}
服务端与客户端(跨域)
请求代理(本地服务器代理)
vue中如何实现跨域访问
1.开发环境:配置vue.config.js proxy代理
2.生产环境:配置nginx代理
Vuex 的原理
Vuex 实现了一个单向数据流
1.state:存放数据的 { }
访问数据:
<p>{{msg}}</p>
//取值的时候一定设置为当前组件的计算属性
computed:{
msg(){
return this.$store.state.msg
}
}
state: {
msg:"我是vuex数据"
},
2.getters:类似于计算属性 ,默认接受一个参数,该参数是所有的state,其他的用法跟computed是一模一样的 返回一个函数,可以传参
<p>{{msg}}</p>
computed:{
msg(){
return this.$store.getters.dollar
}
}
getters:{
dollar(state){
return state.msg+"你好啊"
}
},
传参(返回一个函数):
<p>{{msg}}</p>
computed:{
msg(){
return this.$store.getters.dollar("参数")
}
}
getters:{
dollar(state){
return m=>state.msg+m
}
},
3.Vuex 的状态存储是响应式的,改变 store 中的状态的唯一途径就是显式地提交 mutation。
mutation:类似于methods,默认两个参数,第一个为state,第二个为payload,就是你想做的事情的列表,mutation要通过commit提交
当然commit方法还可以传入额外的参数,官方给这个额外的参数起了一个高大上的名字,叫载荷(payload),一般情况下,我们很少直接传一个number或者string当参数,大部分情况下其实都是传一个对象的。
mutation必须是同步函数,否则无法追踪数据变化
<p>{{msg}}</p>
<p @click="change()">改变</p>
methods:{
change(){
this.$store.commit({type:"add"})
}
}
mutations: {
add(state){
return state.msg=20
}
},
传参:
<p>{{msg}}</p>
<p @click="change()">改变</p>
methods:{
change(){
this.$store.commit({type:"add",num:20})
}
}
mutations: {
add(state,payload){
return state.msg=state.msg+payload.num
}
},
4.action
默认接受一个参数,store实例
action提交的是mutation,而不是直接变更状态;
action可以包含任意异步操作
<p>{{msg}}</p>
<p @click="change()">改变</p>
methods:{
change(){
this.$store.dispatch("changeData",10)
}
}
actions: {
changeData({commit},n){
axios.get().then(res=>commit('add',n))
}
},
5.mapState mapActions mapMutations mapGetters
import { mapState,mapMucations } from 'vuex' //辅助函数
export default ({
computed: {
...mapState(['aa', 'bb']),
...mapGetters(['a','b'])
}
methods:{
...mapMucations(['add']),
...mapActions(['add']),
change(){
this.add()
}
}
})
6.module
分模块之后只有state是局部的(namespaced:true,//开启局部空间)
创建模块文件:store-->modules文件夹-->(moduleA.js;moduleB.js)
index.js:
导入模块文件:import moduleA from "./modules/moduleA.js"
注册模块文件:modules: {moduleA,moduleB}
访问模块文件:state:...mapState("moduleA",['cc'])(其余同理)
3. Vuex 和 localStorage 的区别
(1)最重要的区别
- vuex存储在内存中
- localstorage 则以文件的方式存储在本地,只能存储字符串类型的数据,存储对象需要 JSON的stringify和parse方法进行处理。
- 读取内存比读取硬盘速度要快
(2)应用场景
- vuex用于组件之间的传值。
- localstorage是本地存储,是将数据存储到浏览器的方法,一般是在跨页面传递数据时使用 。
- Vuex能做到数据的响应式,localstorage不能
(3)永久性
刷新页面时vuex存储的值会丢失,localstorage不会。
vuex(临时存储) localhost(持久化存储)
解决vuex临时存储:vuex-persistedstate插件(面试中问道)
插件的原理其实也是结合了存储方式,只是统一的配置就不需要手动每次都写存储方法
使用方法
- 安装
npm install vuex-persistedstate --save
-
引入及配置 在store下的index.js中 存储在sessionstory里
import createPersistedState from "vuex-persistedstate"
const store = new Vuex.Store({
// ...
plugins: [createPersistedState({
storage: window.sessionStorage
})]
})
7. Vuex和单纯的全局对象有什么区别?
- Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。
- 不能直接改变 store 中的状态。改变 store 中的状态的唯一途径就是显式地提交mutation。这样可以方便地跟踪每一个状态的变化
9. Vuex的严格模式是什么,有什么作用,如何开启?
在严格模式下,无论何时发生了状态变更且不是由mutation函数引起的,将会抛出错误。这能保证所有的状态变更都能被调试工具跟踪到。
在Vuex.Store 构造器选项中开启,如下
const store = new Vuex.Store({
strict:true,
})
for循环后computed渲染:
computed: { stars: function () { return function (star) { var count = 0 star.forEach((item, index) => { if (item) { count++ } }) return count } } }
更多推荐
所有评论(0)