工程化开发 & 脚手架Vue CLI
基本介绍
Vue CLI是Vue官方提供的一个全局命令工具
可以帮助我们快速创建一个开发Vue项目的标准化架子。[继承了webpack配置]
好处:
- 开箱即用,零配置
- 内置label等工具
- 标准化
使用步骤
- 全局安装一次:yarn global add @vue/cli 或者 npm i @vue/cli -g
- 查看vue版本:vue --version
- 创建项目架子:vue create project-name
- 启动项目:npm run serve(找package.json)
让style支持less
- 给style加上 lang=“less”
- 安装less less-loader
npm install less less-loader -D -g
-D表示开发环境,-g表示全局安装
vscode中让所有css选择器展开和关闭命令
- 关闭:
ctrl + k, ctrl + 0
- 展开:
ctrl + k, ctrl + j
props校验
- 类型校验
- 非空校验
- 默认值
- 自定义校验
props:{ 校验的属性名:{ type:类型,//Number String Boolean ... required:true,//是否必填 default:默认值,//默认值 validator(value){ //自定义逻辑 return 是否通过校验; } } }
prop和data区别
- data的数据是自己的,随便改,prop的数据是外部的,不能直接改,要遵循单向数据流
非父子通信-event bus事件总线
- 作用:非父子组件之间,进行简易消息传递。(复杂场景->Vuex)
- 步骤
- 创建一个都能访问到的事件总线(空Vue实例)->utils/EventBus.js
import Vue from 'vue' const Bus = new Vue() export default Bus
- A组件(接收方),监听Bus实例的事件
created(){ Bus.$on('sendMsg',(msg) => { this.msg = msg }) }
- 创建一个都能访问到的事件总线(空Vue实例)->utils/EventBus.js
ref 和$refs
- 作用:利用ref和$refs可以用于获取dom元素,或者组件实例
- 特点:查找范围->当前组件内(更精确稳定)
- 示例:
- 目标标签 添加ref属性
<div ref='chartRef>我是渲染图表的容器</div>
- 恰当时机,通过this.$refs.xxx,获取目标标签
counted(){ console.log(this.$refs.chartRef) }
Vue异步更新和$nextTick
- $nextTick:等DOM更新后,才会触发执行此方法里的函数体
- 语法:this.$nextTick(函数体)
this.$nextTick(()=>{
this.$refs.inp.foucs()
})
自定义指令
- 自定义指令:自己定义的指令,可以封装一些dom操作,扩展额外功能
- 全局注册:
Vue.directiv('指令名',{ inserted(el){ //可以对el标签,扩展额外功能 el.focus() } })
- 局部注册
directives: { 'focus':{ inserted(el) { el.focus(); } } }
自定义指令-指令的值
- 需求:实现一个color指令-传入不同的颜色,给标签设置文字颜色
- 语法:在绑定指令时,可以通过‘等号’的形式为指令绑定具体的参数值
<div v-color='color'>我是内容</div>
- 通过binding.value可以拿到指令值,指令值修改会触发update的函数
directives:{ 'color':{ inserted(el,binding){ el.style.color = binding.value }, update(el,binding){ el.style.color = binding.value } } }
插槽
- 作用:让组件内部的一些结构支持自定义
- 需求:要在页面中显示一个对话框,分装成一个组件
- 问题:组件的内容部分,不希望写死,希望能使用的时候自定义
- 插槽基本语法:
- 组件内需要定制的结构部分,改用占位
- 使用组件时,2222标签内部,传入结构替换slot
<template> <div class="dialog"> <div class="dialog-header"> <h3>友情提示</h3> <span class="close">✖️</span> </div> <div class="dialog-content"> <!-- 1. 在需要定制的位置,使用slot占位 --> <slot></slot> </div> <div class="dialog-footer"> <button>取消</button> <button>确认</button> </div> </div> </template>
插槽-后备内容(默认值)
- 提示
插槽-具名插槽
- 需求:一个组件内有多出结构,需要外部传入标签,进行定制
- 语法:
- 多个slot使用name属性区分名字
<template> <div class="dialog"> <div class="dialog-header"> <!-- 一旦插槽起了名字,就是具名插槽,只支持定向分发 --> <slot name="head"></slot> </div> <div class="dialog-content"> <slot name="content"></slot> </div> <div class="dialog-footer"> <slot name="footer"></slot> </div> </div> </template>
- 调用
<MyDialog> <template v-slot:head> 大标题 </template> <template v-slot:content> 内容文本 </template> <template v-slot:footer> 按钮 </template> </MyDialog>
插槽-作用域插槽
- 基本使用
- 给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>
路由 VueRouter
- 下载
npm install vue-router@3.6.5
- 引入
import VueRouter from ‘vue-router’
- 安装注册
Vue.use(VueRouter)
- 创建路由对象
const router = new VueRouter()
- 注入,将路由对象注入到new Vue实例中,建立关联
new Vue({
render:h => h(App),
router
}).$mount(‘#app’)
- 核心步骤
- 建组件(在views中建),配规则
- 准备导航连接,配置路由出口(配置的组件展示的位置)
申明式导航-跳转传参
- 目标:在跳转路由时进行传值
- 方式
- 查询参数传参
- 语法格式如下:
to=‘/path?参数名=值’
- 对应页面组件接收传递过来的值
$route.query.参数名
- 动态路由传参
- 配置动态路由
routes: [ { path: '/home', component: Home }, { path: '/search/:words?', component: Search } ] //路由规则 routes: [ { path: '/user/:id/:name', component: User, props: true // 启用props传递参数 } ] //编程式路由编写 this.$router.push({ path:'', query:{ id:1, name:chenmin } }) //接收 export default { props: ['id', 'name'], mounted() { console.log('User ID:', this.id); console.log('User Name:', this.name); } }
- 配置导航链接
to='/path/参数值'
- 对应页面组件接收传递过来的值
$route.params.参数名
- 查询参数传参
Vue路由 404
- 配置在路由最后面
- 语法:
path:“*”(任意路径)-前面不匹配就命中最后一个
path:“*”,component:NotFind
编程式路由
//1.通过路径的方式跳转
let text = this.$refs.searchInput.value;
// 跳转到搜索结果页
this.$router.push(`/search/${text}`);
//2.通过对象(更适合传参)
this.$router.push({
path:'',
query:{
参数名:参数值
}
})
组件缓存 keep-alive
- keep-alive是什么
keep-alive是vue的内置组件,当它包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。keep-alive是一个抽象组件,它自身不会渲染成一个DOM元素,也不会出现在父组件链中 - keep-alive的优点
在组件切换过程中把切换出去的组件保留在内存中,防止重复渲染DOM,减少加载时间及性能消耗,提高用户体验 - 使用
<keep-alive>
<router-view></router-view>
</keep-alive>
- 问题
缓存了所有被切换的组件,详情页也被缓存起来了 - keep-alive属性
- include:组件名数组,只有匹配的组件会被缓存
- exclude:组件名数组,任何匹配的组件都不会被缓存
- max:最多可以缓存多少组件实例
- 示例:
//LayoutPage组件名 <keep-alive :include="['LayoutPage']"> <router-view></router-view> </keep-alive>
- keep-alive会触发两个生命周期函数:actived和deactived;组件缓存了,就不会执行组件created,mounted,所以提供了actived和deactived
ESlint代码规范
- 代码规范:一套写代码的约定规则。例如:赋值符号的左右是否需要空格,一行结束是否是要加‘;’,正规的团队需要统一的编码风格
eslint自动修正代码配置
-
确保已经安装了ESLint插件
-
打开设置
-
配置文件
// 当保存的时候,eslint自动帮我们修复错误 "editor.codeActionsOnSave": { "source.fixAll": true }, // 保存代码,不自动格式化 "editor.formatOnSave": false
vuex
-
vuex是一个vue的状态管理工具,状态就是数据
-
场景:
- 某个状态在很多个组件来使用
- 多个组件共同维护一份数据
-
使用步骤
- npm install vuex@3 -g -S
- 新建 store/index.js 专门存放vuex
- 创建仓库
Vue.use(Vuex)
- 在main.js中导入挂载到Vue实例上
-
核心概念-state状态
- 说明:state提供唯一的公共数据源,所有共享的数据都要统一放到Store中存储。在state对象中可以添加我们要共享的数据
- 使用
获取 store: 1.this.$store 2.import 导入 store 在模板中:{{$store.state.xxx}} 在组件逻辑中:this.$store.state.xxx js模块中:store.state.xxx
- 通过辅助函数(简化)
mapState是辅助函数,帮助我们把store中的数据自动映射到组件的计算属性中
-
步骤
- import {mapState} from 'vuex
- 数组方式引入state;mapState(['count])
- 展开运算符映射
computed:{ ...mapState(['count']) }
-
核心概念-mutations
- 作用:明确vuex同样遵循单向数据流,组件中不能直接修改仓库的数据
- 开启严格模式:strict:true
- mutations是一个对象,对象中存放修改state的方法
mutations: { addCount (state) { state.count += 1 } }
- 组件中提交调用mutations
this.$store.commit('addCount')
- mutations函数中传参,参数只能有一个,如果多个参数,可以封装成一个对象
this.$store.commit('addCount',1)
- 辅组函数:mapMutations
- 说明:映射方法,mapMutations和mapState很像,它是把位于mutations中的方法提取出来,映射到组件methods中
-
核心概念-actions
- 作用:处理异步操作
- 需求:一秒钟之后,修改state的count为666
- 说明:mutations必须是同步的(便于检测数据变化,记录调试)
- 提供action方法
mutations: { changeCount (state, newCount) { state.count = newCount } } actions: { setAsyncCount (context, num) { setTimeout(() => { context.commit('changeCount', num) }, 1000) } }
- 页面调用dispatch
this.$store.dispatch('setAsyncCount',200)
- 辅助函数-mapActions
- 作用:把位于actions中的方法提取出来,映射到组件methods中
-
核心概念-getters
- 类似计算属性,除了state之外,有时我们还需要从state中派生出一些状态,这些状态是依赖state的,此时会用到getters
- 示例:
getters: { filterList (state) { return state.list.filter(item => item > 5) } }
- 使用
- 通过store访问getters
{{$store.getters.filterList}}
- 通过辅助函数mapGetters映射
computed: {
…mapGetters([‘filterList’])
}
-
核心概念-模块module(进阶语法)
- user模块:store/modules/user.js
const state = { userInfo: { name: 'cs', age: 30 } } const mutations = {} const actions = {} const getters = {} export default { state, mutations, actions, getters }
使用
import user from './modules/user' const store = new Vuex.Store({ modules: { user } })
-
使用模块中的数据
- 直接通过模块名访问$store.state.模块名.xxx
- 通过mapState映射:子模块的映射 mapState(‘模块名’,[‘xxx’]),并且需要开启命名空间
- 模块中调用actions或者mutations,前面要加模块名
this.$store.dispatch('cart/updateCountAsync', { id, newCount })