vue3学习笔记
vue基础
1-1 组件的概念
组件就是页面中的一部分,最小粒度的组件其实可以是一个html 的标签
// createApp 表示创建一个vue应用,存储到 app变量中
//传入的参数表示,这个应用最外层的组件,应该如何展示
// mvvm 设计模式,m -> model 数据,v ->view 视图,vm ->viewModel 视图数据连接层;在vue中代表的是一个一个的组件
const app = Vue.createApp({ //创建一个vue应用
data(){
return {
message:'hello world'
}
},
template:"<div>{{message}}</div>"
})
// vm 代表的就是 vue 应用的根组件
const vm = app.mount('#root') // 只挂载到div 是 root的下面
1-2 Vue中的生命周期函数
// 使用vm.unmount() 触发数据销毁
//生命周期函数:在某一时刻自动执行的函数
const app = Vue.createApp({
data(){
return {
message:'hello world'
}
},
// 在实例生成之前会自动执行的函数
beforeCreate() {
console.log('beforeCreate')
},
// 在实例生成之后会自动执行的函数
created() {
console.log('created')
},
//在组件内容被渲染到页面之前 立即自动执行的函数
beforeMount() {
console.log( document.getElementById('root').innerHTML,'beforeMount')
},
// 在组件内容被渲染到页面之后自动执行的函数
mounted() {
console.log( document.getElementById('root').innerHTML,'mounted')
},
// 当数据发生变化时会自动执行
beforeUpdate() {
console.log(document.getElementById('root').innerHTML,'beforeUpdate')
},
// 当数据发生变化,同时页面完成更新后,会自动执行的函数
updated() {
console.log( document.getElementById('root').innerHTML,'updated')
},
// 当Vue 应用失效时,自动执行的函数
beforeUnmount() {
console.log( document.getElementById('root').innerHTML,'beforeUnmount')
},
// 当vue 应用失效时,且 dom 完全销毁之后,自动执行的函数
unmounted() {
console.log( document.getElementById('root').innerHTML,'unmounted')
},
template:"<div>{{message}}</div>"
})
const vm = app.mount('#root')
1-3 模板语法
template:`<div
v-bind:title="message"
v-html="message"
:[name] = "message"
@[event] = "handleClick"
>
{{message}}
</div>
<form action="http://baodi.com" @click = "handle">
<button type="submit">提交</button>
</form>
`
//v-html 使用html的形式在页面上展示
// v-bind:title="message" : 绑定属性值;
// v-once div里面的变量只使用一次,在次更改message的时候不会改变值,降低无用的渲染
// v-if
// v-on @事件的绑定 动态绑定 @[event] = "handleClick"
//属性名不定,动态绑定 :[name] = "message"
// 提交阻止默认行为 @click = "handle" e.preventDefault();
// 修饰符直接阻止默认行为 @click.prevent = "handle"
1-4 数据方法计算属性和侦听器
// computed 和 methods 都能实现的功能,建议使用computed 因为有缓存 // computed 和 watcher 都能实现的功能,建议使用computed 因为更加简洁
data(){
return {
message:'hello world',
count:2,
price:5,
newTotal:10
}
},
watch:{
//price 发生变化时,函数会执行
price(current,prev){
this.newTotal = current * this.count
// setTimeout(()=>{ // 当数据改变后,3m执行
// console.log('price changed')
// },3000)
}
},
computed:{
// 当计算属性依赖的内容发生变更时,才会重新计算
total(){
return Date.now()
// return this.count * this.price
}
},
methods: {
formatString(string) {
return string.toUpperCase()
} ,
getTotal(){
//只要页面重新渲染,才会重新计算
return Date.now()
// return this.count * this.price
}
},
template:`
<div>{{formatString(message)}}</div>
<div>{{total}} {{newTotal}}</div>
`
})
/**
* data 定义数据
methods
1 定义函数的时候 不能写成箭头函数的形式,因为箭头函数的this不会指向vue实例
比如 handleClickL: () => {console.log(this)} 指向window
2 可以在插值表达式中使用定义的方法
computed 当既可以用计算属性也可以用方法的时候,建议用计算属性
watcher 侦听器
*/
1-5 样式绑定语法
- 1 通过字符串形式控制样式展示 :classString:'red'
- 2 对象或是数组形式 classObject:{red:true,green:true}, classArray:['red','green',{blue:true}], 3 :class="$attrs.class" 子组件上的class样式是父组件属性上的值
1-6条件渲染
v-if 控制元素在 dom上的存在与否,来控制显示隐藏的 v-show 通过 display:none 来控制隐藏
1-7列表循环渲染
data(){
return {
listArray:['dell','lee','teacher'],
listObject:{
firstName:'dell',
lastName:'yee',
job:'student'
}
}
},
methods: {
handleAdd(){
//1 使用数组的变更函数push ,pop,shift,unshift,slice,sort,reverse
// this.listArray.push('hello') // 从下增加
// this.listArray.pop() // 从下删除
// this.listArray.shift() //从上删除
// this.listArray.unshift('aaa') // 从上增加
// this.listArray.reverse() // 反转
//2 直接替换数组 改变了数组的引用
// this.listArray = ['AAA','BBB']
// this.listArray = ['aaa'].concat(['world'])
// this.listArray = ['aaa','bbb'].filter(item => item ==='aaa')
// 3 直接更新数组的内容
// this.listArray[1] = 'hello'
// 直接添加对象的内容,也可以自动的展示出来
this.listObject.age = 100
this.listObject.sex = 'male'
}
},
template:`
<div v-for="(item,index) in listArray" :key="index">
{{item}} -- {{index}}
</div>
<br>
// 当v-for 和v-if 在一个标签上使用时, v-if不生效,v-for 优先级高于 v-if
// 需要同时使用的时候,可以在外层添加一个template,类似于占位符,避免选项多包裹一层div,
// 把v-if 写在div上 v-if="key !=='lastName'" 可以去掉key =lastName的项
<template
v-for="(value,key,index) in listObject"
:key="index"
>
<div v-if="key !=='lastName'">{{value}} -- {{key}}</div>
</template>
<button @click="handleAdd">新增</button>
<div v-for="item in 10">{{item}} </div>
`
})
1-8 事件绑定
/**
* 1 调用多个函数的调用 @click="handleBtn(),handleBtn1()"
* 2 @click.self = "handleBtn" //只要点击自己的时候才会触发
* 3 事件修饰符 prevent 阻止默认行为
* capture 事件的运营模式编程捕获的形式
* once 事件绑定只执行一次
* stop 用来防止冒泡
* 4 按键修饰符
@keydown.enter tab delete esc up down left right
5 鼠标修饰符:left right middle
6 精确修饰符:exact
*
*/
1-9 双向绑定指令的使用
2-1 全局组件和局部组件
- 组件的定义 app.component 组件的复用性 组件里面的数据是单独被独享的,不会被组件共用
- 全局组件,只要定义,处处可以使用,性能不高,但是使用起来简单 app.component
- 局部组件 要注册之后才能使用,性能比较高,使用起来有些麻烦,建议大写字母开头,驼峰命名 局部组件使用时,要做一个名字和组件间的映射对象,你不写映射,Vue底层也会帮你尝试做映射 components:{'dell':counter}, 如果组件名字和标签一样,可以省略 components:{'counter':counter}, 简写 components:{counter}
const Counter = {
data(){
return{
count:1
}
},
template:`<div @click="count +=1">{{count}}</div>`
}
const HelloWorld = {
template:`<div>helo111</div>`
}
const app =Vue.createApp({
components:{
'dell':Counter,
// ' hello-world': HelloWorld,
// 'counter':Counter,
HelloWorld,Counter //这样也会自动映射成上面的形式
},
template:`
<div>
<dell />
<hello-world />
<counter />
</div>
`
})
2-2 组件间传值和校验
/**
type string bollean,Array,Object,Function,Symbol
required 必填
default 默认值
父组件向子组件传值:父:参数的形式 :content1="num" ; 子: props 接收
动态传参 :content1="num"
props:{ 接收一个content参数,类型是number,比传
content:{
type:Number,
required:true,
default:222,
default:()=>{ // 也可以一个函数
return 222
},
validator:function(){ //校验
return value < 1000
}
}
}
<div> <test v-bind="params" /> </div> 等价于
<div> <test :a="params.a" :b="params.b" :c="params.c" /> </div>
属性传的时候,使用content-abc这种命名,接的时候,使用contentAbc命名
<div> <test :content-abc="content" /> </div>
props:['contentAbc']
*/
单向数据流的理解: 子组件可以使用父组件传递过来的数据,但是子组件里绝对不能修改传递过来的数据
2-3 non-props 属性
/** *non-props 属性 :指的就是父组件向子组件传值的时候,不会被接收的属性 使用:在模板里面 通过 v-bind = "attrs */
template:`
<div>
<counter msg="hello" msg1="hello1" />
</div>
`
})
app.component('counter',{
// props:['msg'],
// inheritAttrs:false, // div上不会有msg属性
mounted() {
console.log(this.$attrs.msg)
},
template:`
<div v-bind:mag="$attrs.msg">Counter</div> // 得到某一个属性
<div v-bind="$attrs">Counter</div> // 把父组件传过来的所有属性在这个标签上展示
<div>Counter</div>
`
})
2-4父子组件事件通信
/**
子组件告诉父组件,让父组件来修改count值 在组件里调用this.$emit(adOne);
父组件监听@add-one="handleAddOne"
注意:子组件触发的时候使用驼峰命名 addOne;父组件监听的时候使用 横线连接add-one
emits:['add'] 表示组件会向外触发 add 这个事件;它的意义是可以明显的知道向外触发了哪些事件
父子组件存在双向绑定的时候,可以使用
父: <counter v-mode="count" />
子: props:[modelValue] this.$emit('updata:modeValue',this.modelValue +3)
渲染的时候 {{modelValue}}
备注:modelValue 和updata:modelValue是固定语法,
如果想更换 modelValue的值 在父组件上的v-model:app
可以在父 :<counter v-mode:app="count" />
子: props:[app] this.$emit('updata:app',this.app +3)
渲染也用{{app}}
*/
2-5 组件间双向绑定高级内容
// 如果一个子组件有多个数据想通过 v-model 和父组件的 的data建立关系的时候, 可以在后面加冒号跟参数名字 v-model:title 可以写多个v-model 的绑定
修饰符:v-model.uppercase 在子组件上通过modelModifiers接收 props: { 'modelValue':String, 'modelModifiers':{ // modelModifiers 默认语法 default: ()=>{ // 默认值,不传的时候是一个空对象
}
}
},
2-6 使用插槽和具名插槽解决组件内容传递问题
/**
调用子组件内部的一个东西 slot 插槽
如果父组件想往子组件传递一些dom 节点或是元素标签的时候,没有必要通过属性的方式传递,可以使用插槽
使用slot 希望可以定制
slot 中使用的数据,作用域问题
父模板里调用的数据属性,使用的都是父模板里的数据
子模板里调用的数据属性,使用的都是子模板里的数据
具名插槽:把插槽拆分几部分,每个部分分开调用,给每片段都命名上名字 v-slot 不能直接写在标签上,需要写在 上,加一个占位符
使用
插槽的简写 v-solt:header 等价于 #header 作用域插槽:解决的问题,当子组件渲染的内容由父组件决定的时候,可以使用作用域插槽 比如怎么展示列表,能够让父组件调用子组件里面item的数据 父: 这里也可以直接使用结构的语法 {{slotProps.item}} // 这里直接使用{{item}} 子:
2-7动态组件和异步组件
// 动态组件
// <input-item v-show="currentItem ==='input-item'" />
// <input-text v-show="currentItem ==='input-text'"/>
// 上面这两句可以使用动态语法替换 <component :is="currentItem" />
// template:`
// <keep-alive>
// <component :is="currentItem" />
// </keep-alive>
// <button @click="handleClick">切换</button>
// `,
/**
* 动态组件:根据数据的变化,结合component这个标签,来随时动态切换组件的实现
<component :is="currentItem" /> 要显示一个组件,由currentItem决定,直接获得数据,做更改
在使用动态组件的时候,会有一些问题,比如之前的输入会清除,可以使用<keep-alive>缓存
<keep-alive>
<component :is="currentItem" />
</keep-alive>
异步组件:异步执行某些组件的逻辑
<input-text /> 在调用的时候,这个组件会立马执行
创建一个异步组件
通过异步的方式,动态的加载一些组件,好处,把大型项目拆分很多小的js文件
app.component('async-common-item',Vue.defineAsyncComponent(()=>{ return new Promise((resolive,reject)=>{
})
}))
2-8查漏补缺
v-once 让某个元素标签只被渲染一次 ref 1 实际上是获取dom 节点/或是组件引用的一个语法 在页面渲染完毕后,需要操作或是获取dom,可以使用ref引用的方式
mounted(){ this.$refs.count } provide / inject 父组件传给孙子的时候,通过 props 传给子,在传给 孙 ..... ,如果有多级会很麻烦
- 父:provide:{ 提供数据 count:1 } //子组件不需要传递
- 孙:inject:['count'] 跨越多层组件使用 如果想把父组件里面 data里的数据传递下来,需要把provide写成函数
- 父:provide(){ return {count:this.count} } 但是这种传递的方式是一次性的,如果data里面的数据改变,孙子组件里面的数据不会从新渲染到页面上,解决办法 --vue3 后续更新
Vue 和 css动画效果
3-1 vue实现基础的css过度与动画效果
过度:从一个状态到缓慢到另一个状态 动画:一个元素运动的情况 1 通过class 名字控制
3-2 使用transition 标签实现 单元素组件的过度和动画效果
单元素 , 单组件的入场 出场动画 单元素:
<div >hello world</div> 就是一个单元素,下面没有其他标签
- 入场:从隐藏 -- 展示
- 出厂:从展示 -- 隐藏
- transition 标签 需要配合一些固定的css样式才会有效果 .v-enter-from
- 固定的样式名字 入场样式
.v-enter-from { opacity: 0; }
v-enter-active // 过度效果是什么样式的
v-enter-active { transition:opacity 3s ease-out ; }
.v-enter-to { opacity: 1; }
- 出场动画:
.v-leave-from { // 此处可以省略,效果不受影响 opacity: 1; }
.v-leave-active{ transition:opacity 3s ease-in ; }
.v-leave-to{ opacity: 0; }
- 更改固定的 v-enter-from 名字
1 <transition name="hello"> hello-enter-from 以hello开头
2 <transition leave-active-class ="bye"> .bye 自定义动画名字 自定义动画名字好处:可以做复杂的动画效果,或是动画效果库 比如 animate.css动画库
可以给元素添加过渡和动画效果 通过type 控制以哪一个为准结束动画和过渡 :duration = 1000 直接定义 或是定义一个对象 :duration{enter:1000,leave:3000}
js动画 钩子函数 @before-enter ="handleBeforeEnter" 接收一个参数 el 元素 //在动画进入之前 @enter="handleEnterActive" el ,done //在动画执行过程中 clearInterval(animation) // 结束动画 在调用done() 才算结束 @after-enter ="handleEnterEnd" // 动画执行后调用的函数
3-3 组件和元素切换动画
/**
*多个单元素标签动画切换
期望实现 一个隐藏完毕,另一个在展示
在 transition上添加 out-in 先隐藏,在展示 <transition mode="out-in">
in-out 先进来,在隐藏
注:如果不添加,会两个一起执行
执行刷新页面就有动画 添加 appear 属性
多个单组件之间的切换
<aompon-a v-if="show"></aompon-a>
<aompon-b else-if="show"></aompon-b>
1 v-if v-else 2 动态组件也可以实现
3-4 列表动画
{{item}} .v-move { transition: opacity .5s ease-in }
状态动画
通说逻辑改变动画效果,比如 从 1 到 10数字的变化
SVG
通过数字来控制展示的效果
4-1 Mixin混入的基础语法
/** mixin 混入 把一些内容混入到那里去 mixins:[myMixin], // 在vue的实例上使用 myMixin data 可以混入 // 组件data,methods 优先级高于mixin data优先级 1 当组件中没有对应的数据的时候,会使用混入的数据
2 2 当组件中有对应的数据的时候,会使用组件中的数据自定义的属性,(不在data中,直接定义的属性)组件中的属性优先级高于 minxin 属性的优先级
自定义属性,修改优先级 自定义合并属性策略修改 // 优先使用minxin的 app.config.optionMergeStrategies.number = (mixinVal,appValue) => { return mixinVal || appValue // 如果minxin 有value 就用minxin,否则就用app的 }
// 这种方式定义的是局部的minxin,使用的时候,需要在组件里添加 mixins:[myMixin], 才可以使用
4-2 Vue中的自定义指令
//全局定义
// app.directive('focus',{ // 定义focus指令
// mounted(el) { //el 当前的元素
// el.focus()
// },
// })
局部定义 const directives = { focus:{ mounted(el) { //el 当前的元素 el.focus() }, } }
4-3 Teleport 传送门功能
/** * teleport传送门 把一个组件的某些元素或是一个组件直接挂到其他dom上 比如一些模态框 蒙层 < teleport to=""> < /teleport>
4-4 render函数
template在底层被编译后会生成render函数
render 调用Vue的 h 方法,去返回的一个内容,这个内容就是虚拟dom //虚拟dom -- dom节点 js对象的表述 对真实dom的映射 // 1 性能更好 // 2 Vue具有跨平台的能力,去编写移动端的内容 // { // tagName:'div', // test:'hello', // attributes:{}
总结: template ---》 render --> h --》 虚拟dom(js对象)--》真实 DOM -> 展示到页面上
4-5 插件的定义和使用
plugin 插件 把一些通用性的功能封装起来 定义:
const myPlugin = { install(app,options){ // 两个参数,app 是vue的实例,options 就是调用传递的对象{name:'dell'}
}
}
使用 :app.use(myPlugin)
5-1 setup函数的使用
- 1 产生的背景 当组件越来越大的时候,传统的Vue定义 data,methods (分开定义)维护性困难 vue3 的compositions API 可以解决这种问题
- 2 使用 setup 函数: 在组件created 实例被完全初始化之前 setup(props,context) 接收2个参数 ;props外部组件传递过来的内容,contenxt上下文 在setup里不能使用this 备注:compositions API 所有代码编写要建立在 setup函数之上,这个函数是实例被完全初始化之前调用的 会return 出去一些数据,这些数据会被 template使用
setup(props,context){
return {
name:'dell',
handleClick:()=>{
alert(123)
}
}
},
5-2 ref和reactive响应式的用法
原理: 通过proxy 对函数进行封装,当数据变化时,触发模板等内容的更新 ref:处理基础类型的数据
引用的作用:当改变值的时候,页面是可以渲染出来的
reactive :处理非基础类型的数据
roRefs 原理 proxy ({name:'dell'}) 转化成 {name:proxy{value:'dell'} const {name} = toRefs(nameObj) //直接使用reactive不可以直接使用name做响应式的,需要使用toRefs做转化
setup(props,context){
const { ref } = Vue
// proxy ref 把 'dell' 变成proxy({value:'dell'})这样的响应式引用
let name = ref('dell')
setTimeout(()=>{
name.value='lee'
},2000)
return {name}
const { reactive } = Vue
// proxy ,{name:'dell'} 变成了proxy({name:'dell'})这样的响应式引用
const nameObj = reactive({name:'dell'})
setTimeout(()=>{
nameObj.name = 'lee1'
},2000)
return {nameObj}
},
5-3 toRef 以及context参数
toRefs 如果是一个对象里没有对应的属性值,比如age,toRefs是不会做更改的
解决办法,使用toRef const age = toRef(data,'age')
context有三个值
attrs 父组件传递过来的 None-Props 属性 slots 父组件传递过来的插槽 替换 this.emit
setup(props,context){
const {reactive,toRef} = Vue
const data = reactive({name:'dell'})
const age = toRef(data,'age')
// const {name} = toRefs(data) //name 被转化成 refs setTimeout(()=>{ age.value = 'lee' },2000)
5-4 CompositionAPI 开发 tolist
做了两件事 1 改变input的值 2 往list里放数据
5-5 computed 方法生成的计算属性
copmputed 计算属性
1 接收一个函数
computed (()=>{
return count.value + 5
})
2 接收一个对象 ,有两个方法 set get
let countAddFive = computed({
get:() => {
return count.value + 5
},
set:()=>{
count.value = 10
}
})
5-6 vatch 和 watchEffect的使用差异
watch 具备一定的惰性 ,首次页面展示不执行,只有改变的时候才会执行 参数可以拿到原始和当前值
- 1 监听的是一个ref watch(name,(currentValue,prevValue) => { console.log(currentValue,prevValue) })
- 2 如果监听的是一个reactive 数据 需要在参数 前面写一个箭头函数 watch( () => nameObj.name,(currentValue,prevValue) => { console.log(currentValue,prevValue) })
- 3 监听多个数据的变化,用一个侦听器承载 -- 参数接收一个数组 watch( [() => nameObj.name,() => nameObj.englishName], ([curName,engcur],[prevName,prevEng]) => { console.log(currentValue,prevValue) })
watchEffect 侦听器,偏向于effect
- 1 立即执行,没有惰性
- 2 当数据改变的时候,如果对应的数据有依赖,就会侦听;如果没有,就不会侦听 监听器失效:可以添加一个定时器 watch 可以配置第三个参数,immediate:true 就会立即执行
差异
- 1 立即执行,没有惰性
- 2 不需要传递你要侦听的内容,自动会感知代码依赖,不需要传递很多参数,只要传递一个回调函数
- 3 watchEffect 不能获取之前数据的值
5-7 生命周期函数
把生命周期函数z在 setup中引入 const {onBeforeMount} = Vue
onBeforeUnmount 子组件的显示和隐藏会触发
在 CompositionAPI 有两个生命周期函数是没有的
beforeCreate created 这是因为setup 函数执行时间在这两个周期之间 onRenderTracked 每次渲染后重新收集响应式依赖 onRenderTriggered 每次触发页面重新渲染时自动执行
5-8 Provide inject ref
谁提供的数据,在哪里修改
dom ref
在setup中获取dom
const hello = ref(null)
获取一个真实的dom节点 setup(){ const {ref,onMounted} = Vue const hello = ref(null) // 这里的ref生成的一个响应式的引用 onMounted(() => { console.log(hello.value) }) return {hello} }, //ref 获取一个dom节点的引用,这两个不一样,单需要配合使用 template:<div ref="hello"> hello world </div>
6-1 VueCli 的使用和单文件组件
1 先安装 node LTS 稳定版本 node 和 npm 会一起安装上
2 安装nrm npm install -g nrm 会有很多国内的镜像源
nrm ls 查看所有的镜像源
nrm use xxx 使用的镜像源
vue-cli:vue3.0之前版本使用此名称
@vue/cli:vue3.0之后版本包括3.0版本使用此名称
// 清除之前的脚手架
//卸载3.0之前的版本
npm uninstall -g vue-cli
yarn global remove vue-cli
//卸载3.0之后的版本(可以统一使用此指令卸载)
npm uninstall -g @vue/cli
yarn global remove @vue/cli
// 安装最新的版本
npm install -g @vue/cli 或者 yarn global add @vue/cli 安装指定版本
//安装2.9.6版本
npm install -g vue-cli@2.9.6
yarn global add vue-cli@2.9.6
//安装3.0.3版本
npm install -g @vue/cli@3.0.3
yarn global add @vue/cli@3.0.3
//安装4.0.5版本
npm install -g @vue/cli@4.0.5
yarn global add @vue/cli@4.0.5
入口文件 main.js 创建一个app应用 挂载到节点上 createApp(App).mount('#app') app.vue
单文件组件 -- 这个文件就是一个组件 模板 样式 逻辑在一个.vue文件里,就形成了一个单文件组件
6-2Vue-router路由的理解和使用
路由是指根据 url 的不同,展示不同的内容 指跳转路由的标签,跳转不同的路由里面去 负责展示当前路由对应的组件内容
component: () => import('../views/AboutView.vue') 异步懒加载路由 一开始加载打开的时候没有加载about组件,当访问的时候才会加载 可以降低首屏加载量,带来的影响,当点击切换页面的时候,可能会加载的慢
6-3 Vue 的语法解析
-
为什么要使用vuex
-
vueX 数据管理框架
- 当项目变得越来越复杂,使用props project来传递数据 可维护性不太好 VueX创建了一个全局唯一的仓库,用来存放全局的数据 createStore 存放全局的数据在state里面 定义 :state:{name:'dell'} 使用/获取:在页面写一个计算属性: computed:{ myName(){ return this.$store.state.name } }
-
修改全局的数据
- 1 不能随便修改,需要一套完整的机制才可以修改 流程: 想改变数据,
vuex 要求第一步,必须派发一个action this.$store.dispatch('change') // dispatch就是派发;change 就是一个action 派发一个叫change 的action
回到仓库的代码里,就有一个actions actions:{ //第二步,store感知到你触发了一个叫change的action,执行change方法 change(){ // 第三步 , 提交一个commit ,触发一个mutation this.commit('change') // 这个mutation名字叫 change } }
mutation:{ //第四步,对应的mutation 被执行 change(){ // 第五步 在mutation里面修改数据 this.state.name = 'lee' } }
总结: 1 dispatch 方法,派发一耳光action,名字叫做change
2 感知到 change这个action,执行store中actions 下面的change
3 commit 提交一个叫做change 的数据改变
4 mutation感知到提交的change改变,执行change方法改变数据
为什么要存在actions
在没有异步的情况下,可以直接commit修改数据,省略第2步 this.$store.commit('change')
mutation里面只允许写同步代码,不允许写异步代码 (写了也不会报错)
actions里面可以写 异步代码
this.$store.dispatch('change',hello world) 第二个参数是 带过去的数据
mutations:{ change(state,str) //对应的第一个参数是
state state.name = str }
actions:{ change(store,str){ // 对应的第一个参数是store
store.commit('changge,'str) } }
dispatch 和actionns 做关联
commit和mutation 做关联
6-4CompositionAPI中如何使用
import {useStore} from 'vuex'
export default {
name:'Home',
setup() {
const store = useStore()
const name = store.state.name
return {name}
} }
6-5 使用axios 发送ajax请求
axios.post('https://www.fastmock.site/mock/5b04a994a775f6524f683b6e7c843a5e/jingdongvue3/api/user/login',{
username:'data.username',
password:'data.password'
}).then(() => {
alert('成功')
}).catch (()=>{
alert('失败')
})
//把Content-Type 改成json
axios.defaults.headers.post['Content-Type'] = 'application/json';
异步路由 component: () => import(/* webpackChunkName: "Home" */ '../views/home/Home') 访问哪个页面就加载对应的页面,路
7-1 移动端真机调试
把ip地址直接粘贴到手机浏览器即可访问