Vue工程化开发
脚手架
创建脚手架
使用步骤:
1.全局安装(一次):yarn globaladd @vue/cli 或 npm i @vue/cli -g
2.查看 Vue 版本:`vue —version
3.创建项目架子:vue create project-name(项目名-不能用中文)
4.启动项目:yarn serve 或 npm run serve( 看package.json的配置 )
官方文档网址
修改入口文件等操作,在 vue.config.js中配置
Vuecli自定义创建项目
步骤:
1、安装脚手架
2、创建项目:
vue create 项目名3、选择自定义: Manually select features
选择特性:(根据自己的项目来,需要什么选什么,上下键选择,空格键选中)

具体选择(根据自己的项目进行选择)

ESLint代码规范
代码规范:一套写代码的约定规则。例如:“赋值符号的左右是否需要空格""一句结束是否是要加;”…
JavaScript Standard Style(目前市场上使用最多的规范): https://standardis.com/rules-zhcn.html
下面是这份规则中的一小部分:
- 字符串使用单引号 ‘abc’
- 无分号 const name =‘zs’
- 关键字后加空格 if(name =‘ls’){..}
- 函数名后加空格 function name (arg){…}
- 坚持使用全等 ===、摒弃 ==
- …
一切不符合规范的代码都会报错
ESLint查找并修正错误
①手动修正:
根据错误提示来一项一项手动修改纠正, 如果你不认识命令行中的语法报错是什么意思,根据错误代码去[ESLint 规则表]中查找其具体含义

② 自动修正
基于 VsCode 插件 ESLint ** 高亮错误,并通过配置** 自动 帮助我们修复错误

// 当保存的时候,eslint自动帮我们修复错误" "editor.codeActionsOnSave": { "source.fixAll": true }, //保存代码,不自动格式化' "editor.formatOnSave":false,有可能代码声明了变量没有使用等不能自动修正的代码,也会报错,此时得自己修正手动错误
非单文件组件
基本使用
Vue中使用组件的三大步骤:
一、定义组件(创建组件) const 变量名 = Vue.extend({这里面配置和new Vue差不多,但是没有el})
二、注册组件 局部注册:new Vue内配置 components 全局注册:Vue.component(‘组件名’,组件)
三、使用组件(写组件标签) 模板内使用<组件名></组件名>
一、如何定义一个组件?
使用Vue.extend(options)创建,其中options和new Vue(options)时传入的那个options几乎一样,但也有点区别;
区别如下:
1.el不要写,为什么? ——— 最终所有的组件都要经过一个vm的管理,由vm中的el决定服务哪个容器。
2.data必须写成函数,为什么? ———— 避免组件被复用时,数据存在引用关系。
备注:使用template可以配置组件结构。
二、如何注册组件?
1.局部注册:靠new Vue的时候传入components选项
2.全局注册:靠Vue.component(‘组件名’,组件)
三、编写组件标签:
<div id="id" class=""> <h1>{{str}}</h1> <!-- 使用组件 --> <school></school> <hr> <students></students> <all></all> </div> <div id="id2" class=""> <all></all> </div> <script src="../../vue.js"></script> <script> // 创建组件 const school = Vue.extend({ template: ` <div> <div>学校 :{{name}}</div> <div>地址 :{{address}}</div> </div>`, data() { return { name: '清华', address: '北京' } } }) const students = Vue.extend({ template: ` <div> <div>学生 :{{name}}</div> <div>年龄 :{{age}}</div> </div> `, data() { return { name: '卡卡', age: 20 } } }) const all = Vue.extend({ template: `<div><h2>全局配置</h2></div>` }) // 全局注册 Vue.component('all', all) new Vue({ el: '#id', data: { str: '非单文件组件' }, // 局部注册组件 components: { school, students } }) new Vue({ el: '#id2' }) </script>注意点
1.关于组件名:
一个单词组成:
第一种写法(首字母小写):school
第二种写法(首字母大写):School
多个单词组成:
第一种写法(kebab-case命名):my-school
第二种写法(CamelCase命名):MySchool (需要Vue脚手架支持)
备注:
(1).组件名尽可能回避HTML中已有的元素名称,例如:h2、H2都不行。
(2).可以使用name配置项指定组件在开发者工具中呈现的名字。
2.关于组件标签:
第一种写法:
第二种写法:
备注:不用使用脚手架时,
3.一个简写方式:
const school = Vue.extend(options) 可简写为:const school = options
VueComponent(组件实例对象:vc)
关于VueComponent:
1.school组件本质是一个名为VueComponent的构造函数,且不是程序员定义的,是Vue.extend生成的。
2.我们只需要写
即Vue帮我们执行的:new VueComponent(options)。
3.特别注意:每次调用Vue.extend,返回的都是一个全新的VueComponent!!!!
4.关于this指向:
(1).组件配置中:
data函数、methods中的函数、watch中的函数、computed中的函数 它们的this均是【VueComponent实例对象】。
(2).new Vue(options)配置中:
data函数、methods中的函数、watch中的函数、computed中的函数 它们的this均是【Vue实例对象】。
5.VueComponent的实例对象,以后简称vc(也可称之为:组件实例对象)。
Vue的实例对象,以后简称vm。
单文件组件
使用
1.创建 .vue 文件 ,里面配置,一个文件就是一个组件,最终都要被App.vue管理,之后再到入口文件引入
Student组件 (子组件)
<template> <!-- 配置模板结构 --> <div> <h2>学生姓名:{{name}}</h2> <h2>学生年龄:{{age}}</h2> </div></template>
<script> // 默认导出 export default { //这里面配置组件信息 name:'Student',//组件名,一般和文件名相同 data(){ return { name:'张三', age:18 } };</script>
<style> /*样式结构*/</style>App.vue 统帅组件(父组件/根组件)
<template> <div> <Student></Student> </div></template>
<script>//引入 Student组件import Student from "./components/Student";export default { //组件注册 components: { Student },};</script>入口文件
//引入Vue 和 App组件import Vue from 'vue'//这是个不完整的vue,只包含核心,没有模板解析器import App from './App.vue'
new Vue({ template: `<app></app>`, el: '#app', render: h => h(App)//引入的vue不包含模板解析器,所以要用render})关于不同版本的Vue
1.vue.js与vue.runtime.xxx.js的区别:
(1).vue.js是完整版的Vue,包含:核心功能+模板解析器。
(2).vue.runtime.xxx.js是运行版的Vue,只包含:核心功能;没有模板解析器。
2.因为vue.runtime.xxx.js没有模板解析器,所以不能使用template配置项,需要使用
render函数接收到的createElement函数去指定具体内容。
注册全局组件
入口文件中 / main.js中
// 引入组件 import all from './components/all'// 全局注册 Vue.component('all', all)组件间通信
父传子

prop配置项
-
功能:让组件接收外部传过来的数据
-
传递数据:
<Demo name="xxx"/> -
接收数据:
-
第一种方式(只接收):
props:['name'] -
第二种方式(限制类型):
props:{name:String}用的最多 -
第三种方式(限制类型、限制必要性、指定默认值):
props:{name:{type:String, //类型required:true, //必要性 ,是否必填default:'老王', //默认值validator(value){//自定义校验逻辑return 是否通过校验//if (value > 100) {//return true// } else {// console.error('传入的数字必须大于100')//return false}}}}
备注:props是只读的,Vue底层会监测你对props的修改,如果进行了修改,就会发出警告,若业务需求确实需要修改,那么请复制props的内容到data中一份,然后去修改data中的数据。
-
子传父
this.$emit('事件名',数据)

自定义事件(子传父)
组件中的通信机制:子组件==>父组件 (子组件 传 数据 给 父组件)
绑定方式:
1.在组件标签中绑定:父组件中 <School @事件名=“回调函数”/> 或 <School v-on:事件名=“回调函数”/>
2.用ref绑定:父组件中
<Demo ref="标识名"/>......mounted(){ this.$refs.标识名.$on('事件名',回调函数)} 3.若想让自定义事件只能触发一次,可以使用once修饰符,或$once方法。
触发自定义事件:触发事件的组件中this.$emit('事件名',参数(根据情况传入参数,可以有多个))
解绑自定义事件:触发事件的组件中
解绑单个 :this.off('事件名')
解绑多个 :this.off(['事件名1','事件名2'])
全部解绑 :this.off()
组件上也可以绑定原生DOM事件,需要使用native修饰符。
注意:通过this.$refs.标识名.$on('事件名',回调)绑定自定义事件时,回调要么配置在methods中,要么用箭头函数,否则this指向会出问题!
全局事件总线(GlobalEventBus)
是一种组件间的通信机制:(任意组件间的通信)
使用:
1、安装全局事件总线:在入口文件中(main.js 或 index.js)
// 法一:给Vue的一个实例对象安装全局事件总线// Vue.prototype.$bus = new Vue()
// 法二:在当前管理组件的Vue实例对象的钩子上安装new Vue({ ...... beforeCreate() { Vue.prototype.$bus = this //安装全局事件总线,$bus就是当前应用的vm }, ......}) 2.使用:
①哪个组件需要接收数据就在哪个组件的mounted钩子上给$bus注册事件监听
methods(){ demo(data){......}}......mounted() { //注册事件监听 this.$bus.$on('事件名',this.demo)//可直接写回调函数,建议将回调写到方法中} ②发送数据的组件中
// 发送this.$bus.$emit('事件名',数据) ③注册事件监听解的组件绑事件监听
beforeDestroy() { // 解绑事件监听器 this.$bus.$off('事件名') }父传子孙通信-provide&inject配置项
provide&inject作用:跨层级共享数据,可以理解为后代组件共用的data,但是后代组件需要用inject接收
1.父组件 provide 提供数据
export default { data() { return { color: 'blue', userInfo: { name: 'kaka', age: 17, }, } }, provide() { return { // 普通类型 【非响应式】 color: this.color, // 复杂属性 【响应式】 userInfo: this.userInfo, } },}2.子组件 inject 获取数据
export default { inject: ['color', 'userInfo'],}mixin(混入/合)配置项
-
功能:可以把多个组件共用的配置提取成一个混入对象
-
使用方式:
第一步定义混合——创建一个名为xxx的js文件,在里面配置组件需要共用的部分:
export default {data(){....},methods:{....}....}全局也可以直接 :
Vue.mixin({这里面配置})第二步使用混入:
1.哪个组件需要使用,就引入该混合文件。
2.混入
全局混入:入口文件中配置:
Vue.mixin(xxx)局部混入:vc中配置:mixins:['xxx']
插件
-
功能:用于增强Vue
-
本质:包含install方法的一个对象,install的第一个参数是Vue,第二个以后的参数是插件使用者传递的数据。
-
定义插件:
对象.install = function (Vue, options) {// 1. 添加全局过滤器Vue.filter(....)// 2. 添加全局指令Vue.directive(....)// 3. 配置全局混入(合)Vue.mixin(....)// 4. 添加实例方法Vue.prototype.$myMethod = function () {...}Vue.prototype.$myProperty = xxxx} -
使用插件:
Vue.use(插件名(文件名))
scoped样式
在组件的样式中,样式默认是混合的,容易造成类名重复,需要用 scoped来限制
- 作用:让样式在局部生效,防止冲突。
- 写法:
<style scoped>
消息订阅与发布(pubsub)
也是一种组件间通信的技术,和全局事件总线相似 (任意组件间通信)
使用步骤:
-
安装pubsub:
npm i pubsub-js -
引入:
import pubsub from 'pubsub-js'(发送数据和接收数据的组件都需要引入) -
获取数据的组件
pubsub.subscribe('订阅名',回调函数)mounted() {// this.pid = pubsub.subscribe('订阅名',回调函数)// 回调函数的第一个参数是订阅名,第二个才是数据// 和定时器的感觉一样,会返回一个订阅idthis.pid = pubsub.subscribe('getData', (pbname, data) => {console.log(data)})},beforeDestroy() {// 取消订阅pubsub.unsubscribe(this.pid)},} -
发送数据的组件:
pubsub.publish('xxx',数据)
ref获取Dom和组件实例
给标签添加的标识,相当于(id的替代)
1.配置ref属性:内置标签 : <h1 ref="xxx"></h1> 组件标签 <School ref="xxx"/>
2.获取Dom和组件实例:this.$refs.xxx 内置标签获取到的是Dom , 组件标签获取到的是组件实例对象
3 .this$refs.xxx获取到组件实例对象,可以直接.方法名()调用该组件的方法
$nextTick
基本使用
-
- 语法:
this.$nextTick(回调函数) - 作用:在下一次 DOM 更新结束后执行其指定的回调。
- 什么时候用:当改变数据后,要基于更新后的新DOM进行某些操作时,要在nextTick所指定的回调函数中执行。(比如input输入框获取焦点时)
- 语法:
input自动获取焦点
<template> <div class="app"> <input v-if="isEdit" ref="inp" type="text" /> <span v-else>点击编辑显示输入框</span> <button @click="edit">编辑</button> </div></template>
<script>export default { data() { return { isEdit: false, } }, methods: { edit() { // 让输入框显示 this.isEdit = true // 让输入框获取焦点 // this.$refs.inp.focus()//此处报错,因为vue是异步更新DOM,此时无法获取到DOM this.$nextTick(() => { // this.$nextTick(回调函数),这里面的回调函数是当DOM更新完才执行 this.$refs.inp.focus() }) }, },}</script>插槽(父传子,子传父)
作用:
让父组件可以向子组件指定位置插入html结构,也是一种组件间通信的方式,适用于 父组件 ===> 子组件 。
作用域插槽:父组件 <===> 子组件
分类:
默认插槽、具名插槽、作用域插槽
使用方式:
默认插槽:
只是简单的一处需要插入内容时使用
父组件中: <Category> <div>html结构1</div> </Category>子组件中: <template> <div> <!-- 定义插槽 --> <slot>插槽默认内容...</slot> </div> </template>具名插槽:
子组件有多处不同需要插入时使用
父组件中: <Category> <template slot="head">//写法一 <div>html结构1</div> </template>
<template v-slot:center>//写法二 <div>html结构2</div> </template>
<template #footer>//写法三 <div>html结构2</div> </template> </Category>子组件中: <template> <div> <!-- 定义插槽 --> <slot name="head">插槽默认内容...</slot> <slot name="center">插槽默认内容...</slot> <slot name="footer">插槽默认内容...</slot> </div> </template>作用域插槽:
父组件需要子组件的数据做操作时
基本使用步骤: 1.给 slot 标签,以添加属性的方式传值
<slot :id="item.id" msg="测试文本"></slot>2.所有添加的属性,都会被收集到一个对象中
{id:3,msg:'测试文本'}3.在template中,通过#插槽名="obj" 接收,默认插槽名为 default
<MyTable :list="list"> <!-- 接收数据 --> <template #default="obj"> <button @click="del(obj.id)">删除</button> </template></MyTable>单页面应用程序
什么是单页面应用程序?
所有功能在一个html页面上实现
单页面应用优缺点?
优点:按需更新性能高,开发效率高,用户体验好缺点:学习成本,首屏加载慢,不利于SEO
应用场景?
系统类网站/内部网站/文档类网站 /移动端站点
Vue封装的过渡与动画
-
作用:在插入、更新或移除 DOM元素时,在合适的时候给元素添加样式类名。
-
图示:
-
写法:
-
准备好样式:
- 元素进入的样式:
- v-enter:进入的起点
- v-enter-active:进入过程中
- v-enter-to:进入的终点
- 元素离开的样式:
- v-leave:离开的起点
- v-leave-active:离开过程中
- v-leave-to:离开的终点
- 元素进入的样式:
-
使用
<transition>包裹要过度的元素,并配置name属性:<transition name="hello"><h1 v-show="isShow">你好啊!</h1></transition> -
备注:若有多个元素需要过度,则需要使用:
<transition-group>,且每个元素都要指定key值。
-