0.0 课程介绍
- Vue介绍 【了解】
- Vue项目的搭建 【掌握】
- 项目目录详解【掌握】
- Vue组件化【掌握】
- Vue的表达式 【重点】
- Vue的指令【重点】
1.0 什么是Vue?【了解】
Vue是一个构建用户界面(UI)的JS库。
1.1Vue的特点
- 小 20k 【大概11000多行】
- 性能强 虚拟dom
- 双向绑定
- 生态丰富
1.2 Vue历史 [了解]
1.0 -> 2015.10
2.0 -> 2016.10 https://v2.cn.vuejs.org/v2/guide/installation.html
3.0 -> 2020.09 https://cn.vuejs.org/
2023年5月20日 :3.3.4
2.0 Vue的环境搭建【掌握】
2.1 CDN使用
2.2 脚手架安装
先安装Vue脚手架
1 2 3 4 5 6
| vue --version
安装: npm i @vue/cli -g 或 yarn add global @vue/cli
|
#注意 如果你的yarn无法使用,可能是没有安装yarn npm i yarn -g,或者是没有配置环境变量
先 yarn global bin 找到你的yarn安装位置
我的电脑-> 右键属性 -> 高级系统配置 ->环境变量 -> path、
2.3 使用脚手架创建Vue的项目
一顿操作:
见图形笔记
#如果你想删除你保存预设方案,去我的电脑->用户 ->你的电脑名 ->删掉 vuerc
C:\Users\你的电脑名
3.0 组件化【掌握】
3.1 什么是组件化?
相当于将一个大的页面拆分成多个大组件,通过小组件组合成大组件,这个用组件拼接成页面的思维就叫组件化
特点:
3.2 单文件组件
一个.vue文件就是一个单文件组件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| <template> <div> 不仅可以写样式,还可以写很多vue提供的语法及指令 ... </div> </template>
<script>
export default { data(){ return { xx } }, methods:{ fn(){ }, foo(){ }, }
} </script>
<style lang="less" scoped> // 写你的css </style>
|
注意: 推荐插件
vuter: 语法提示
Vue VSCode Snippets : 快捷键
path: 路径提示
4.0 Mustache胡须表达式【重点】
1 2 3 4 5 6 7 8 9 10 11
| {{ 表达式 }} `${ 表达式 }`
看是不是表达式? 100 let arr = [10,20,30] arr.map(v=>v+100).join('-') true?'不是':'是' if(true){ a = 10 } for(let i=0;i<10;i++){ a+=i } arr.forEach(i=>{ i+10 })
|
什么是表达式?
1、能够得到唯一结果的一句运算
2、可以放在赋值表达式右侧
5.0 指令 【重点】
vue的指令是什么?
帮助我们操作dom,提高效率
vue的指令就是一个以v-开头的自定义属性
1
| <div id="dxx" class="xxx" age="10" v-xx="表达式">
|
5.1 v-text 和 v-html
作用:帮助我们渲染dom节点
v-text: 底层是 textContent ,渲染数据,不能识别标签
v-html: 底层是 innerHTML ,渲染数据, 能够识别标签
5.2 v-if 和 v-show
作用: 帮助我们根据条件渲染页面节点
v-show: 底层是通过控制display的属性来进行显示隐藏
v-if: 底层是通过删除页面或重新渲染节点来实现显示隐藏
5.3 v-if 和 v-else-if 和 v-else
作用: 帮助我们根据条件渲染页面节点,跟我们js中的if…else if…else是一样的用法,如果从上到下开始判断,当满足条件就不渲染后面的内容
5.4 v-for 循环
作用 : 帮助我们循环渲染页面
1 2 3 4 5 6 7 8 9 10 11 12 13
| let arr = [1,2,3]
<div v-for="(item,index) in arr"> {{ item }} -- {{ index }} </div>
let obj = {name:'张无忌',age:18,like:'金花宝宝'} <div v-for="(value,key,index) in obj"> {{ value }} -- {{ key }} -- {{index}} </div>
|
5.5 v-model
作用:实现数据的双向绑定,只用使用v-model 与data里的数据就不分彼此 表单之王
1 2
| <input v-model="data的数据" />
|
5.6 v-on 事件
作用:绑定事件, 简写为@
1 2 3 4 5 6 7 8 9
| 常规写法: <button v-on:事件类型=“表达式”>xxx</button> <button v-on:事件类型=“处理函数”>xxx</button> <button v-on:事件类型=“处理函数(参数1,参数2,...)”>xxx</button>
简写: <button @事件类型=“表达式”>xxx</button> <button @事件类型=“处理函数”>xxx</button> <button @事件类型=“处理函数(参数1,参数2,...)”>xxx</button>
|
0.0 自定义组件的使用 【掌握】
1 2
| import 组件名 from '路径/文件名'
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| <script> export default { components:{ // 组件注册 组件名:组件名, 组件名1 }, data(){ // 数据 return {} }, methods:{ // 方法 }
}
</script>
|
使用组件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| <template> <div> <组件名></组件名> <组件名 /> <!-- 使用组件 --> <CommonHeader></CommonHeader> <CommonContent /> <CommonFooter></CommonFooter>
<!-- 第二用法 推荐--> <common-header></common-header> <common-content /> <common-footer /> </div> </template>
|
1.0 课程介绍
- v-bind 动态绑定属性 【重点】
- 其他指令 【了解】
- 计算属性computed 【重点】
- 过滤器 filters 【掌握】
- 侦听器 watch 【掌握】
- Vue生命周期 【掌握】
2.0 v-bind 【重点】
作用:帮助我们操作节点属性,让属性变成数据驱动
1 2 3 4 5 6 7 8 9
| <标签 v-bind:class='表达式' v-bind:style="表达式" v-bind:src="表达式"> </标签>
简写:
<标签 :class='表达式' :style="表达式" :src="表达式"> </标签>
|
3.0 其他指令 【了解】
3.1 v-pre
作用:不编译胡须表达式
3.2 v-once
作用:只渲染一次,当他所依赖的数据发生改变时,也不会更新渲染
3.3 v-cloak
作用:隐藏胡须表达式,直到有数据时才渲染,只有直接在项目里引入vuejs才会出现,当前主流脚手架版本没有这个问题
4.0 computed 计算属性 【重点】
用于一堆逻辑计算,返回一个唯一的结果 ,与methods定义方式一样,计算属性直接使用他的函数名(不需要加小括号),就等于他的返回结果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| <template> <div> {{ 函数名 }} </div> </template> <script> export default { .... computed:{ 函数名(){ 一堆的逻辑运算 return '最终的结果' } } } </script>
|
计算属性的特点:
- 计算属性用于一堆逻辑运算,直接使用函数名就等于使用了最终结果
- 计算属性依赖的数据发生改变,他就会重新计算
- 计算属性存在依赖缓存,性能强,如果依赖的数据更新就会重新计算,如果不更新就直接返回上一次的计算结果
computed计算属性 与 methods方法的区别 【面试题】
- computed计算属性必须有返回值,methods不一定有
- 调用方式不一样,computed计算属性直接使用函数名,methods方法需要
函数名()调用
- computed计算属性有依赖缓存,methods方法每次调用都会重新计算结果,计算属性如果数据没有改变,他就将上一次缓存的结果直接返回,就不重新计算了
5.0 filters 过滤器【掌握】
作用:用于处理页面数据的显示格式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| <template> <div> {{ msg | 过滤器函数名 }} </div> </template> <script> export default { data(){ return { mes:'xxx' } }, methods:{}, components:{}, computed:{}, filters:{ 过滤器函数名(参数){ 一堆参数的处理 return '处理完的结果' } } }
</script>
|
6.0 侦听器 watch 【掌握】
作用:用于监听数据的变化,进行相应函数的操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| <template> <div> {{ msg | 过滤器函数名 }} </div> </template> <script> export default { data(){ return { msg:'' } } watch:{ 需要监听的数据(newVal,oldVal){ // 一堆的后续操作 } }, }
</script>
|
7.0 生命周期 【重点】
什么是生命周期?
是指组件从创建到渲染到更新到销毁的周期过程
vue的声明周期分为4大阶段
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| #注意:他们都是内置选项
beforeCreate(){}, created(){}, #注: created 一般用于初始化页面数据发送ajax
beforeMount(){} mounted(){} #注: mounted 一般用于操作dom节点
beforeUpdate(){} updated(){}
beforeDestroy(){} destroyed(){}
|
总结:vue的生命周期的作用,在组件各个阶段执行相应的生命周期钩子函数,给用户添加自己代码的机会
作业:
1 购物车案例
2 交互代码敲3遍
3 面试题: 计算属性computed和方法methods有什么区别?
4 选做题:操作题
5 手写配置选项 和 指令
0.0 课程介绍
- 组件通信【重点】
- slot 插槽【掌握】
- 封装组件【掌握】
- UI组件库【掌握】
1.0 组件通信
组件为了实现交互,通过数据传递实现,这个就叫做组件通信
自定义组件的使用:
1.1组件通信类型:
- 父传子【重点】: 在父页面的子组件标签上定义需要传递参数,在子组件页面通过配置选项props 进行接收参数,使用方法与data里的数据一样
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
| <template> <son 参数1=“表达式” :参数2=“msg12”></son> </template> <script> import Son from 'xx/Son.vue' // 引入组件 export default{ // 注册组件 components:{ Son }, data(){ return { msg:'xxx' } } } </script>
# 子组件接收参数 <template> <div> {{ msg }} {{ 参数1 }} </div> </template> <script> // 子组件接收父组件传入的参数 export default{ // 数组接收方法1 props:['参数1','参数2'] // 对象接收方法2 【推荐】 props:{ 参数1:{ // 配置选项 required:true, // 是否必传 type:String|Number|Boolean|Object|Array, // 数据类型:构造函数 default:''|0|false // 注意:如果类型为引用类型 ()=>{return {}}、()=>{return []} } }, data(){ return { msg:’xxx‘ } } } </script>
|
子传父【重点】:vue是单向数据流,子组件不可以直接修改父组件传入的数据,只能通过触发事件进行数据修改;
发送:通过this.$emit(‘自定义事件名‘,参数),将参数传递给父组件;
接收:父组件页面在子组件的标签上绑定自定义事件名接收传入参数;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| # son.vue <template> <div> ...内容 <button @click="处理函数"> 修改 </button>
</div> </template> <script> export default{ ... // 方法 methods:{ 处理函数(){ // 通过$emit触发自定义事件,携带对应参数给父组件 this.$emit('自定义事件名',参数1,参数2...) } } }
</script>
#父组件 <template> <son 参数1=“表达式” :参数2=“msg12” @自定义事件名="处理函数"></son> </template> <script> import Son from 'xx/Son.vue' // 引入组件 export default{ // 注册组件 components:{ Son }, data(){ return { msg:'xxx' } }, // 方法 methods:{ 处理函数(参数1,参数2){ // 处理逻辑后修改数据 this.msg = 参数1 } } } </script>
|
1 2 3 4 5 6 7 8 9
| 1、创建中介 -- 创建vue的实例 挂载到Vue的原型上 Vue.prototype.$bus = new Vue() 2、传递信息 this.$bus.$emit('自定义事件名',参数) 3、接收信息 created(){ this.$bus.$on('自定义事件名',(参数)=>{ // 处理数据 }) }
|
父子关系确定: 如果你在我的页面引入,注册,使用,那么我就是你爸爸
- 依赖注入【不讲】:祖先组件注入某个属性,在子孙组件依赖这个变量
- vuex 状态管理库
- 插槽 :他传递元素
- 路由传参: Router
2.0 插槽的基本使用 【掌握】
在子组件里挖坑,在父组件使用时填坑就可以了,这就是插槽的作用
2.1 插槽的类型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| #子组件 son.vue <template> <div> <slot></slot> </div> </template>
#父组件 father.vue <template> <div> <son> 写入你想写内容包括元素标签 </son> </div> </template>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| #子组件 son.vue <template> <div> <slot name='插槽名1'></slot> <slot name='插槽名2'></slot> </div> </template>
#父组件 father.vue <template> <div> <son> <写入你想写内容包括元素标签 slot="插槽名2" /> <写入你想写内容包括元素标签 slot="插槽名1" /> </son> </div> </template>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| #子组件 son.vue <template> <div> <slot name='插槽名1' :需要传出去的属性1=“属性值1” :需要传出去的属性2=“属性值2” ></slot> <slot :需要传出去的属性1=“属性值1” :需要传出去的属性2=“属性值2”></slot> </div> </template>
#父组件 father.vue <template> <div> <son> # 具名插槽 <写入你想写内容包括元素标签 slot="插槽名1" slot-scope="scoped"> {{ scoped }} </写入你想写内容包括元素标签> # 匿名插槽 <写入你想写内容包括元素标签 slot-scope="scoped" > {{ scoped }} </写入你想写内容包括元素标签> </son> </div> </template>
|
3.0 组件库的使用
去相应的官网找到合适的组件, C + V
ElementUI (https://element.eleme.cn/#/zh-CN)
1 2 3 4 5 6 7 8 9 10 11
| 1、下载 npm i element-ui -S 或 yarn add element-ui -S
2、引入及使用(在main.js引入) import ElementUI from 'element-ui'; import 'element-ui/lib/theme-chalk/index.css';
Vue.use(ElementUI);
|
Vant UI (https://vant-contrib.gitee.io/vant/v2/#/zh-CN/)
1 2 3 4 5 6 7 8 9 10 11
| 1、下载 npm i vant@latest-v2 -S 或 yarn add vant@latest-v2 -S
2、引入及使用(在main.js引入) import Vant from 'vant'; import 'vant/lib/index.css';
Vue.use(Vant);
|
0.0 课程介绍
Vue 路由库Router 【重点】
- 安装
- 基本使用
- 路由配置
- 路由模式
- 路由传递参数
- 路由内置对象
- 路由守卫
Vue的内置API 【掌握】
ref
Vue.set
Vue.nextTick
Vue.filter
Vue.component
Vue.use
Vue.directive
1.0 Vue的路由Router 【重点】
1.1 路由作用
进行页面的跳转(相当于a标签),Vue是SPA单页面应用,他的页面跳转必须使用Vue-Router路由进行实现
1.2 路由的安装
vue create 项目名 创建一个带有Vue路由的项目
1.3 路由的使用
一级路由配置
- 1 建(建大页面)
- 2 配 (配置路由选项,一一对应)
- 3 给出口及测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| 如果你的页面需要进行路由显示,必须给出口 <router-view></router-view>,一级路由出口在App.vue页面,嵌套路由出口在父页面 路由出口:就是你页面需要渲染的位置 测试:在浏览器路径输入对应path
const routes = [ { path: '/', redirect: '/discover' }, { path: '/discover', component: DiscoverView }, { path: '/my', component: MyView }, { path: '/friend', component: FriendView }, ]
|
1 2 3 4
| <router-link to="/discover">发现音乐</router-link> <router-link to="/my">我的音乐</router-link> <router-link to="/friend">关注音乐</router-link>
|
嵌套路由配置
- 1 建 (建大页面)
- 2 配 (配置路由选项,一一对应)
- 3 给出口及测试
1 2 3 4 5 6 7 8 9 10 11 12 13
| 嵌套路由的出口在父页面 <router-view></router-view>
{ path: '/discover', component: DiscoverView, redirect: '/discover/toplist', children: [ { path: '/discover/recommend', component: RecommendView }, { path: '/discover/toplist', component: ToplistView }, { path: '/discover/playlist', component: PlaylistView }, ] },
|
1 2 3 4 5 6 7 8 9
| <div class="discover"> <!-- 嵌套路由的出口在父页面 --> <router-link to="/discover/recommend">推荐</router-link> <router-link to="/discover/toplist">排行榜</router-link> <router-link to="/discover/playlist">歌单</router-link> <!-- 嵌套路由的出口 --> <router-view></router-view> </div>
|
1.4 路由的模式 【重点】
【面试题】
hash模式 :地址栏带#, 底层实现的是用 onhashchange的一个方法
history模式 : 地址栏不带#,底层实现是用的h5的 pushState 方法
区别:
[1] : 地址栏一个带#,一个不带#
[2] : 底层实现的原理不一样
[3] : hash模式根history模式在开发中没有任何区别,但是在打包后的代码hash模式没有问题,history模式会存在刷新后页面丢失情况
#解决办法: 只能让后端或者运维,对nginx代理服务器进行相应重定向的配置
1.5 路由的传参 【掌握】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
|
1、路由跳转 this.$router.push({ path:'/路径', query:{ 键名:键值, 键名1:键值1, } }) 2、获取参数 this.$route.query
特点: 1、页面刷新参数依旧存储 2、不能直接传递引用类型(可以用JSON.stringify 转成字符串【不推荐】)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
|
1、路由跳转 this.$router.push({ name:'路由名', params:{ 键名:键值, 键名1:键值1, } }) 2、获取参数 this.$route.params
特点: 1、页面可以携带引用类型 2、刷新页面数据丢失(将刷新按钮禁用或者去除)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| 1、路由配置项中进行路径动态传参配置 { path: '/my/:变量名', component: MyView }, 2、路由跳转 this.$router.push({ path:'/my/传入的值' }) 3、获取参数 this.$route.params
特点: 1、刷新页面后不会丢失数据 2、动态路径必须携带参数
|
1.6 路由的两个内置对象【掌握】
路由实例对象,他主要提供一些页面跳转的方法(他其实就等 === VueRouter)
push
go
replace
路由信息对象,他主要提供当前页面的参数信息
params
query
path
1.7 路由守卫【理解】
全局前置路由守卫,监听路由变换,判断是有权限
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| router.beforeEach((to,from,next)=>{ })
router.beforeEach((to, from, next) => { if (to.path == '/discover/recommend') { next({ path: '/discover/playlist' }) } else { next() }
})
|
2.0 Vue的内置API【掌握】
2.1 ref
作用:用于获取Dom节点,相当于元素选择器,如果你获取的是子组件,相当于获取到自组件的实例对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| <template> <div> #dom <span ref="ref的值1">dom节点</span> #子组件 <son ref="ref的值2"></son> </div> </template>
<script> export default { methods:{ init(){ this.$refs.ref的值1 #DOM节点 this.$refs.ref的值2 #子组件的实例对象 } } } </script> 定义ref的值: 在父页面的子组件(或dom)标签上定义属性ref=“ref的值” 获取ref的值: 在js中通过this.$refs.ref的值 来获取子组件实例(或dom节点)
|
2.2 Vue.set
他可以帮助我们重新挟持【绑架】数据,让数据具备响应式
理论【面试题】:因为Vue底层会对data里进行挟持,当初始状态对象没有这个属性,后期添加的属性没有被挟持,不具备响应式,通过Vue.set方法让数据重新挟持
1 2 3 4 5 6
| import Vue from 'vue' Vue.set(需要挟持的对象, "属性", "修改的值"); 或 this.$set(需要挟持的对象, "属性", "修改的值")
|
数组怎么改?
解决方法:数组的变更方法,这是被Vue重写的方法,可以让数组里的数据修改时也具备响应式
1 2 3 4 5 6 7 8 9 10 11
| push() pop() shift() unshift() splice() sort() reverse()
以上方法已经升级啦
|
2.3 Vue.nextTick
他是一个回调函数,帮你解决异步的问题,在下一次页面节点更新完毕后触发
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| import Vue from 'vue' Vue.nextTick(()=>{ }) 或 this.$nextTick(()=>{ })
created() { console.log(document.querySelector("#msg")); Vue.nextTick(() => { console.log(document.querySelector("#msg")); }); 或 this.$nextTick(() => { console.log(document.querySelector("#msg")); }); }
|
2.4 Vue.filter
全局过滤器,注册的全局过滤器可以在任何页面使用
1 2 3 4 5 6 7 8 9
| #main.js
Vue.filter('过滤器的名字',(参数)=>{ return ’过滤后的结果‘ })
|
2.5 Vue.component
注册全局组件
1 2 3 4 5
| Vue.component('Counter', Counter)
|
2.6 Vue.use
使用插件,当插件是基于Vue.js写的,就需要use一下
1 2 3 4 5 6 7 8
| import ElementUI from 'element-ui'; import 'element-ui/lib/theme-chalk/index.css'; import App from './App.vue';
Vue.use(ElementUI);
|
2.7 Vue.directive
自定义的指令,可以根据自身需求自己定义
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| Vue.directive('指令名',{ bind #只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。 inserted #被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。 })
Vue.directive('overflow', { inserted: (dom, obj) => { dom.style.width = obj.value + 'px' dom.style.overflow = 'hidden' dom.style.whiteSpace = 'nowrap'; dom.style.textOverflow = 'ellipsis'; } })
|
作业
2 • 配置Fitness健身项目的路由(一级路由 和 二级路由)。
3 代码练习
4 xmind
5 下节课过一眼
0.0 课程介绍
1.0 Vuex 状态管理库
Vuex是一个Vue的插件,用于管理状态( 数据 )
Vuex作用场景:
祖先组件向子孙组件传递数据,层级非常深
多个组件间的数据共享
Vue的核心功能
核心State
用于注册、存放数据的仓库
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| export default new Vuex.Store({ state: { num: 250, goods: [ ], whiteHorseVip: [ { name: '凯子哥', age: 24 }, { name: '黄子姐', age: 22 }, { name: '维子哥', age: 26 }, { name: '俊子哥', age: 18 } ] } })
|
1、直接获取仓库的数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| <template> <div> <div>num:{{ $store.state.num }}</div> <div> goods: <p v-for="item in $store.state.goods" :key="item.name" >{{ item.name }} --{{ item.price*item.count }}</p> </div> </div> </template>
<script> export default { created() { console.log(this.$store.state.num); }, computed: { num() { return this.$store.state.num; }, goods() { return this.$store.state.goods; } }, }; </script>
|
2、通过辅助函数获取仓库数据
mapState 特点:map 映射 State仓库 : 与仓库里的state一一对应
1 2 3 4 5 6 7 8 9 10 11 12 13
| import {mapState} from 'vuex' export default{ computed:{ ...mapState(['要取变量1','要取变量2']), 【强烈推荐】 ...mapState({ key:(state)=>state.要取变量1, key1:(state)=>state.要取变量2, }) } }
|
核心Mutations
用于修改仓库数据的唯一方法,如果要修改仓库的数据必须提交一个mutation
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| export default new Vuex.Store({ state: { num: 250, goods: [] }, mutations: { 函数名(state,payload){ state.goods = payload } }, })
this.$store.commit('函数名',实参) this.$sotre.commit({ 【不推荐】 type:'函数名', data:实参 })
import {mapMutations} from 'vuex'
export default{ methods:{ ...mapMutations(['函数名']) ...mapMutations({ key:'函数名1', key2:'函数名2' }) }
}
|
核心Getters
相当与状态管理库的计算属性,对state进行二次处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
| export default new Vuex.Store({ state: { num: 250, goods: [ ], whiteHorseVip: [ { name: '凯子哥', age: 24 }, { name: '黄子姐', age: 22 }, { name: '维子哥', age: 26 }, { name: '俊子哥', age: 18 } ], }, getters: { whiteHorseVipList(state) { return state.whiteHorseVip.filter(v => v.age > 18) } } })
<template> <div> <div>num:{{ $store.getters.whiteHorseVipList }}</div> <div> goods: <p v-for="item in $store.getters.whiteHorseVipList" :key="item.name" >{{ item.name }} --{{ item.age }}</p> </div> </div> </template>
<script> export default { computed: { whiteHorseVipList() { return this.$store.getters.whiteHorseVipList; } }, }; </script>
import {mapGetters} from 'vuex' export default{ computed:{ ...mapGetters(['whiteHorseVipList']) } }
|
核心Actions
用于异步修改数据,但是最终修改数据还是需要调用mutation方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| export default new Vuex.Store({ state: { num: 250, }, mutations: { SET_NUM(state, payload) { state.num += payload } }, actions: { asyncSetNum(context, payload) { return new Promise(reslove => { setTimeout(() => { context.commit('SET_NUM', payload) reslove() }, 2000);
}) } }, })
this.$store.dispatch('函数名',实参) this.$store.dispatch({ 【不推荐】 type:'函数名'', data:'实参' })
// 辅助函数 import {mapActions} from 'vuex' export default{ methods:{ // 数组写法 ...mapActions(['函数名']), // 对象写法 ...mapActions({ 键名:'函数名' }) } }
|
核心modules
模块化,拆分你的仓库
1 定义模块化的仓库
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| export default new Vuex.Store({
modules: { moduleA: { namespaced: true, state: { money: 1000000 }, getters: {}, mutations: {}, actions: {} }, moduleB: { namespaced: true, state: { money: 10 }, getters: {}, mutations: {}, actions: {} } } })
|
2 获取模块化里的状态(数据)
1 2 3 4
| this.$store.state.模块名.属性名;
|
修改模块里的数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| <template> <div> home <h1>moneyA:{{ moneyA }}</h1> <h1>moneyB:{{ moneyB }}</h1>
<div>money:{{ money }}</div> <button @click="SET_MONEY(100)">改变</button> <button @click="update">直接改变</button> </div> </template>
<script> import { mapState, mapMutations } from "vuex"; export default { created() { console.log(this.$store); }, computed: { ...mapState("moduleA", ["money"]), moneyA() { return this.$store.state.moduleA.money; }, moneyB() { return this.$store.state.moduleB.money; } }, methods: { ...mapMutations("moduleA", ["SET_MONEY"]), update() { this.$store.commit("moduleA/SET_MONEY", 200); } } }; </script>
|
0.0 课程介绍
- 动态组件 【掌握】
- 修饰符 【掌握】
- 混入mixins 【掌握】
- 内置组件 【理解】
- v-model 【理解】
- 路由懒加载和组件懒加载(异步组件) 【掌握】
- 递归组件 【了解】
- Vue底层:MVVM架构模式 【理解】
- 虚拟DOM 【了解】
#目标:希望把知识点总结话术,能够大概的说出相应的理论
1.0 动态组件
通过内置组件component 的属性is 进行组件的动态渲染
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| <template> <div> <component :is="flag?Counter:HelloVue"></component> <button @click="flag = !flag">取反{{ flag }}</button> </div> </template>
<script> import Counter from './components/Counter.vue' import HelloVue from '@/views/components/HelloVue.vue'; export default { data(){ return { flag:false, Counter:Counter, HelloVue } } } </script>
|
2.0 Vue修饰符
2.1 事件修饰符
.stop // 帮助你阻止事件冒泡
.prevent // 阻止默认行为
1 2 3 4 5 6 7 8 9 10 11 12
| <template> <div> <div class="box1" @click="handleBox1"> // 阻止冒泡及默认行为 <a class="box2" @click.stop.prevent="handleBox2" href="https://www.baidu.com"></a> </div> // 阻止默认行为 <a href="https://www.baidu.com" @click.prevent>点我</a> </div> </template>
|
2.2 按键修饰符
•.enter // 输入回车时触发
•.space // 输入空格时触发
• .up 上
• .down 下
• .left 左
• .right 右
document.body.addEventListener(‘keyup’,(e)=>{console.log(e.keyCode)}) // 获取你输入的按键码
2.3 表单修饰符
.lazy // 将v-model输入事件从input改变成change事件
.number // 将输入的数据转换为number类型
.trim // 去除输入数据的首尾空格
2.4 .sync修饰符
1 2 3 4 5 6 7 8 9 10 11 12 13
| # 父页面 <template> # 注意: .sync === @update:value="msg = $event" <div> .sync修饰符{{ msg }} <!-- <son :value="msg" @update:value="msg = $event"></son> --> <son :value.sync="msg" ></son> </div> </template>
#子页面 this.$emit('update:value','嘿嘿')
|
3.0 mixins混入 【掌握】
可以抽取公共的配置选项,然后混入到你需要的页面
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| # mixin.js export default { data(){ return { user:{name:'金花宝宝'} } }, methods:{ updateUser(){ this.user.name= '张无忌' } } }
#在你需要混入的页面使用
<script> import mixin from '@/mixins/mixin' export default { mixins:[mixin], data(){ return { age:18 } }, methods:{ getData(){ console.log('嘿嘿'); } } } </script>
|
4.0 Vue内置组件
- slot : 插槽
- componet : 动态组件
- transition : 过渡动画
1 2 3 4 5 6 7 8 9 10 11 12 13
| <transition name="动画名"> <div v-show v-if></div> </transition>
.动画名-enter-active, .动画名-leave-active { transition: opacity .5s; } .动画名-enter, .动画名-leave-to { opacity: 0; }
|
1 2 3 4 5 6 7 8 9
| <keep-alive include="['组件名a', '组件名b']" :max="20" :exclude="['不缓存的组件名','不缓存的组件名']"> <router-view></router-view> </keep-alive>
:include="['组件名a', '组件名b']" :exclude="['不缓存的组件名','不缓存的组件名']" :max="20" 你最多缓存的组件数量
|
5.0 自定义的v-model
实现自定义v-model的方法
1、组件接收值的属性value
2、组件内修改这个值的自定义事件名为input
修改v-model的默认配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| <template> <div> <!-- 将默认的属性从value改成heihei 将默认的事件从input改成change --> <select :value="heihei" @change="inputData"> <option value="A">A</option> <option value="B">B</option> <option value="C">C</option> <option value="D">D</option> </select> </div> </template> export default { model: { prop: 'heihei', event: 'change' }, props:{ // 接收的属性value heihei:{ type:String, default:0 } }, methods:{ inputData(e){ console.log(e.target.value); // 输出的事件名 input this.$emit('change',e.target.value) } } }
|
6.0 路由懒加载 和 组件懒加载(异步组件)
路由懒加载的作用:
只会根据输入路径之后,再进行针对性组件页面加载,提高首屏加载速度
1 2 3 4 5 6
| { path: '/sync-modifier', name: 'sync-modifier', component: () => import('../views/02-.sync修饰符.vue') }
|
组件懒加载(异步组件)
在页面渲染到指定位置才开始加载对应的组件
1 2 3 4 5
| components:{ MyInputNumber:()=>import('./components/MyInputNumber.vue') },
|
7.0 递归组件 【理解】
组件自己调用自己
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| <template> <div> <ul > <li v-for="item in dataList" :key="item.name">{{ item.name }} <my-menu :dataList="item.children"></my-menu> </li> </ul> </div> </template>
<script> export default { name:'MyMenu', props:{ dataList:{ type:Array, default:()=>[] } } } </script>
|
8.0 MVVM的底层原理
M:Model 数据模型,主要是提供数据
V: View 视图,主要用于渲染页面
VM: ViewModel视图模型 , 他是连接 M 和V的桥梁
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| const data = { message:'这是初始的值' }
function render(){ document.querySelector('#app').innerHTML = ` <input value=${data.message} oninput="inputchange(this)"/> ${data.message} ` } render()
let val = data.message Object.defineProperty(data,'message',{ get(){ console.log('get'); return val }, set(newVal){ console.log('set'); val = newVal render() } })
function inputchange(dom){ console.log(dom.value); data.message = dom.value
}
|
9.0 虚拟DOM
虚拟是一个js的对象,vue中虚拟dom在beforeMount创建完毕,dom真实节点尚未挂载,当页面发生改变,再次创建一个新的虚拟dom,通过diff算法,将新老虚拟dom,进行比较差异,得到差异地方,进行针对性的局部渲染,大大提高了页面性能,减少不必要的消耗。
diff算法:
• v-for的key并不会在页面渲染,key就是提供给虚拟dom对比使用,优化性能.
作业
整理一份xmind, 包含6天所有vue的知识(并且回顾)