文章目录
- 目录
- 1.vue简介
- 1.1 vue是什么
- 1.2 Vue的特点
- 1.3 学习Vue之前需要掌握哪些JavaScript基础知识
- 1.4 初识vue需要知道的地方
- 2. vue的核心基础
- 2.1 模板语法
- 2.2 数据绑定
- 2.3 el和data的两种写法
- 2.4 MVVM
- 2.5 数据代理
- 2.6 事件处理
- 2.61事件的基本使用:
- 2.62 事件修饰符
- 2.63 键盘事件
- 2.7 计算属性
- 2.8 监视属性
- 2.9 绑定样式
- 3.0 条件渲染
- 3.1 列表渲染
- 3.11 key的作用和原理
- 3.12 列表过滤
- 3.13 列表排序
- 3.2 vue监测数据原理
- 3.3 如何利用v-model收集表单数据
- 3.4 过滤器
- 3.5 v-text
- 3.6 cookie小知识
- 3.7 vue内置指令
- 3.71 v-html
- 3.72 v-cloak
- 3.73 v-once
- 3.74 v-pre
- 3.8 自定义指令
- 3.9 vue的生命周期
- 4.0 vue的组件化编程
- 4.1 模块与组件,模块化与组件化
- 4.2 非单文件组件
- 4.21 vuecomponent
- 4.22 一个重要的内置关系
- 4.3 单文件组件
- 4.4 使用vue脚手架
- 4.5 ref
- 4.6 props
- 4.7 mixin(混入)
- 4.8 插件
- 4.9 scoped
- 5.0 组件化编码流程
- 5.1 儿子怎么给爸爸传数据
- 5.2 做完记事本案例的小结
- 5.3 WebStronge游览器的本地存储
- 5.4 组件内自定义事件
- 5.5 全局事件总线
- 5.6 消息订阅与发布
- 5.7 nextTick
- 5.8 Vue封装的过渡与动画
- 5.9 配置代理
- 5.91 跨域
- 5.92 插槽slot
- 6.0 VueX
- 6.1 什么是Vuex
- 6.2 什么时候用
- 6.3 vuex的 工作原理 重点
- 6.4 安装配置使用
- 6.5 mapState
- 6.6 vuex的模块化
- 7.0 v-router 路由
- 7.1 spa应用
- 7.2 对于路由
- 7.21 路由分类
- 7.22 安装
- 7.3 嵌套路由
- 7.4 路由传参
- 7.4 路由的params参数
- 7.5 路由的props设置
- 7.6 replace
- 7.7 编程式路由导航
- 7.8 缓存路由组件
- 7.9 路由守卫
- 8.0 打包和部署
- 8.1 ui库
目录
- vue基础(本篇)
- vue-cli
- vue-router
- vuex
- element-ui
- vue3
1.vue简介
1.1 vue是什么
一套用于构建用户界面的渐进式JavaScript框架
前端的职责:在合适的时候发出合适的请求把数据展示到合适的位置
- 渐进式:vue可以自底向上的应用
- 简单应用:只需一个轻量小巧的核心库
- 复杂应用:可以引入各式各样的Vue插件
Vue的官网
cdn引入
vue2 的版本用下面这个
<script src="https://cdn.jsdelivr/npm/vue@2.6.14/dist/vue.js"></script>
1.2 Vue的特点
- 采用组件化模式,提高代码复用率、且让代码更好维护。
- 声明式编码,让编码人员无需直接操作DOM,提高开发效率
1.3 学习Vue之前需要掌握哪些JavaScript基础知识
- ES6语法规范
- ES6模块化
- 包管理器
- 原型、原型链
- 数组常用方法
- axios
- promise
- …
1.4 初识vue需要知道的地方
- 想让Vue工作,就必须创建一个Vue实例,且要传入一个配置对象
- root容器里的代码依然符合html规范,只不过混入了一些特殊的Vue语法
- root容器里的代码被称为【Vue模板】
- Vue实例和容器是一一对应的
- 真实开发中只有一个Vue实例并且会配合着组件一起使用
- {{xxx}}中的xxx要写js表达式,且xxx可以自动读取到data中的所有属性
- 一旦data中的数据发生改变,那么模板中用到该数据的地方也会自动更新(数据驱动视图)
2. vue的核心基础
2.1 模板语法
vue 的模板语法有两大类:
- 差值语法 :
- 功能:用于解析标签体内容
- 写法: {{xxx}},xxx会作为标签体去解析,且可以自动读取到data中的属性
- 指令语法 :
- 功能:用于解析标签(包括:标签属性,标签内容,绑定事件…)
2.2 数据绑定
单向数据绑定(v-bind)
数据只能从data流向了页面
双向数据绑定 v-model
数据不仅能从data流向页面,还可以从页面流向data
小结
- v-model一般应用于表单元素,要有value值
2.3 el和data的两种写法
el有两种写法:
- 第一种:
new Vue ({
el:'#root',
data:{
msg:'小帅'
}
})
第二种不常用的:
const vm = new Vue ({
data:{
msg:'xiba'
}
})
vm.$mount('#root')
- data的两种写法:
第一种: 对象式
第一种写法,data是一个对象
data:{
msg:'小帅'
}
第二种:函数式
data的第二种写法,data是一个函数,返回数据对象(组件中用的多)
data(){
return {
msg:'xiba'
}
组件化必须使用函数式的data
- 一个重要的原则
由Vue管理的函数,一定不要写箭头函数,一旦写了箭头函数,this就不再是Vue实例了。变成window了
2.4 MVVM
- M:模型(Model):对应data中的数据
- V:视图(View):模板代码
- VM :视图模型(ViewModel):Vue的实例对象
我的理解:
Model相当于冰箱放的什么,例如一个西瓜对应data,view相当于你看着西瓜放在冰箱的哪里,viewmodel就是这个冰箱
观察可以发现
- data中所有的属性,最后都出现在了vm身上。
- vm身上所有的属性及Vue原型上所有属性,在Vue模板中都可以直接使用。
<div id="root">
<!-- 这里是view -->
<div>{{name}}</div>
</div>
<script src="https://cdn.jsdelivr/npm/vue@2.6.14/dist/vue.js"></script>
<script>
// 这里是ViewModel
new Vue({
el:'#root',
// 这里是Model
data:{
name:'xiba'
}
})
</script>
vue实例做的是什么
就是靠数据绑定和数据监听
2.5 数据代理
数据代理:通过一个对象代理对另一个对象中属性的操作(读/写)
- Vue中的数据代理:
通过vm对象来代理data对象中属性的操作(读/写)
- Vue中数据代理的好处:
更加方便的操作data中的数据
- 基本原理:
通过object.defineProperty()把data对象中所有属性添加到vm上.为每一个添加到vm上的属性,都指定一个getter/setter。
在getter/setter内部去操作(读/写)data中对应的属性。
2.6 事件处理
2.61事件的基本使用:
- 使用v-on :XXX或@XXX绑定事件,其中xxx是事件名;
- 事件的回调需要配置在methods对象中,最终会在vm 上;
- methods中配置的函数。不要用箭头函数!否则this就不是vm了;
- methods中配置的函数,都是被Vue所管理的函数,this的指向是vm或组件实例对象;
- @click="xxx”和@clicl="xxx($event)”效果一致,但后者可以传参;
2.62 事件修饰符
Vue中的事件修饰符:
- prevent:阻止默认事件(常用);
- stop:阳止事件冒泡(常用);
- once:事件只触发一次(常用):
- capture:使用事件的捕获模式;
- self:只有event.target是当前操作的元素是才触发事件;
- passive:事件的默认行为立即执行,无需等待事件回调执行完毕;
2.63 键盘事件
- Vue中常用的按键别名:
- 回车=> enter
- 删除=> delete(插获“删除”和"退格”健)
- 退出=> esc
- 空格=> space
- 换行=>tab (特殊,必须配合keydown使用)
- 上=> up
- 下 =>down
- 左=>left
- 右=> right
- Vue未提供别名的按健,可以使用按健原始的key值去绑定,但注意要转为kebab-case(短横线命名)
- 系统修饰键(用法特殊):ctrl、alt、shift、meta
- 配合keyup使用:按下修饰键的同时,再按下其他健,随后释放其他健,事件才被触发。
- 配合keydown使用:正常触发事件。
- 也可以使用keyCode去指定具体的按键(不推荐)
- Vue.config . keyCodes.自定义健名=健码,可以去定制按键别名
2.7 计算属性
计算属性:
- 定义:要用的属性不在在,要通过已有属性计算得来
- 原理:底层借助了objcet.defineproperty方法提供的getter和lsetter.
- get函数什么时候执行?
- 初次读取时会执行一次。
- 当依赖的数据发生改变时会被再次调用。
- 优势:与methods实现相比,内部有缓存机制(复用),效率更高,调试方便。
- 备注:
- 计算属性最终会出现在vm上,直接读取使用即可。
- 如果计算属性要被修改,那必须写set函数去响应修改,且set中要引起计算时依赖的数据发生
可以简写为一个函数
2.8 监视属性
监视属性watch:
- 当被监视的属性变化时,回调函数自动调用,进行相关操作
- 监视的属性必须存在。才能进行监视!!
- 监视的两种写法:
- new Vue时传入watch配置
- 通过vm.$watch监视
深度监视:
deep :true 监视多级结构里的数据改变
watch:{
xxx:{
immediate:true //初始化调用
deep:true // 深度监视
handler(newValue,oldValue){
}
}
}
computed和lwatch之间的区别:
- computed能完成的功能,watch都可以完成。
- watch能完成的功能,computed不一定能完成,例如: watch可以进行异步操作。
两个重要的小原则:|
- 所被Vue管理的函数,最好写成普通函数,这样this的指向才是vm或组件实例对象。
- 所有不被Vue所管理的函数(定时器的回调函数、ajax的国调函数等),最好写成箭头函数,这样this的指向才是vm或组件实例对象。
2.9 绑定样式
绑定class
三种方法
- 字符串写法
适用于:样式的类名不确定,需要动态指定
<div class="basic" :class='mood' @click="changeMood">{{name}}</div>
data:{
name:'xiba',
mood:'happy'
},
- 数组写法
适用于:要绑定的样式个数不确定、名字也不确定–>
<div class="basic" :class="classArr[1]">{{name}}</div><br>
classArr:['happy','sad','normal'],
- 对象写法
适用于:要绑定的样式个数确定、名字也确定,但要动态决定用不用
<div class="basic" :class="classObj">{{name}}</div>
classObj:{
happy:false,
normal:true
}
绑定style
写成对象的方式
3.0 条件渲染
条件渲染:
- v-if
写法:
- v-if=“表达式”
- v-else-if=”表达式"
- v-else=“表达式”
- 适用于:切换频率较低的场景。
- 特点:不展示的DOM元素直接被移除。
- 注意: v-if可以和:v-else-if、 v-else一起使用,但要求结构不能被"打断”。
- v-show
写法: v-show=“表达式”
- 适用于:切换频率较高的场景。
- 特点:不展示的DOM元素未被移除,仅仅是使用样式隐藏掉
3.备注:使用v-if的时,元素可能无法获取到,而使用v-show一定可以获取到。
3.1 列表渲染
v-for指令:
- 用于展标列表数据
- 语法: v-for=“(item,index) in xxx” : key=“yyy”
- 可遍历:数组、对象、字符串(用的很少)、指定次数(用的很少)
3.11 key的作用和原理
key的作用:
数据变得时候,vue根据新数据生成新的虚拟dom,新dom和旧dom会进行比较
比较的规则:
一看key,而看内容,
key相同:
- 内容没变,用以前的真实dom
- 内容变了,生成新的真实dom,替换以前的真实dom
key不同 :
创建新的真实dom,随后渲染页面
用index作为key的问题:
- 对数据做逆序等破坏顺序的操作,就会产生没必要的真实dom更新,影响效率
- 有输入类的dom,会产生错误的dom更新,让界面出现问题
开发中如何选择key:
要用唯一标识
3.12 列表过滤
可以说是一种模糊搜索
watch和computed都能实现,watch复杂点,不如computed
computed: {
filpersons() {
return this.persons.filter((p) => { //这个return把结果给filpersons
return p.name.indexOf(this.keyWord) !== -1 //通过这个return返回过滤出来的结果
})
}
}
3.13 列表排序
利用计算属性实现
创建一个新数组,对新数组进行排序
computed: {
filpersons() {
const arr = this.persons.filter((p) => {
return p.name.indexOf(this.keyWord) !== -1
})
if (this.sortType) {
arr.sort((a, b) => {
return this.sortType === 1 ? b.age - a.age : a.age - b.age
})
}
return arr
}
}
3.2 vue监测数据原理
通过 object.defindeProperty 中的get 和set 方法
data中的数据都会被加工,读取的时候自动调用get ,修改用set ,然后把数据告诉wacher,把新旧dom重新对比渲染
vue监视数据的原理:
- vue会监视data中所有层次的数据。
- 如何监测对象中的数据?
通过setter实现监视,且要在new Vue时就传入要监测的数据。
1. 对象中后追加的属性,Vue默认不做响应式处理
2. 如需给后添加的属性做响应式,请使用如下API:
Vue.set(target.propertyName/index. value)或vm.$set(target. propertyName/index. value)
-
如何监测数组中的数据?
通过包裹数组更新元素的方法实现,本质就是做了两件事:
- 调用原生对应的方法对数组进行更新
- 重新解析模板,进而更新页面。
-
在Vue修改数组中的某个元素一定要用如下方法:
使用这些API:
- push()
- pop()
- shift()
- unshift()
- splice()
- sort()
- reverse()
2.Vue.set()或vm.$set()
特别注意:Vue.set()和 vm.$set()不能给vm 或vm的根数据对象添加属性!
vue的数据劫持就是你修改数据,被vue逮住,他给你用set来修改,帮你改完后还往网页上丢
3.3 如何利用v-model收集表单数据
收集表单数据:
- 若input type=“text”/>,则v-model收集的是value值,用户输入的就是value值。
- 若:,则v-modei收集的是value值,且要给标签配置value值。
- 若:
- 没有配置input的value属性,那么收集的就是checked(勾选or未勾选,是布尔值>
- 配置input的value属性:
- v-model的初始值是非数组,那么收集的就是checked(勾选 or未勾选,是布尔值)
- v-model的初始值是数组,那么收集的的就是value组成的数组
备注:v-model的三个修饰符:
- lazy:失去焦点再收集数据
- number:输入字符串转为有效的数字
- trim:输入首尾空格过滤
3.4 过滤器
vue3移除了 不学了
3.5 v-text
v-text指令:
- 作用:向其所在的节点中渲染文本内容。
- 与插值语法的区别: v-text会替换掉节点中的内容,{{xx}}则不公。
3.6 cookie小知识
他就像我们的身份证 很重要,服务器给我们的,通过这个识别使身份
如何获取别人的cooki?
一个链接,跳转,a
3.7 vue内置指令
3.71 v-html
- v-html可以识别htm1结构。
- 严重注意: v-html有安全性问题!!!
- 在网站上动态渲染任意HTML是非常危险的,容易导致XSS政击.
- 一定要在可信的内容上使用v-html,不要用在用户提交的内容上!
3.72 v-cloak
v-cloak指令(没有值):
- 本质是个特殊属性,Vue实例创建完毕并接管容器后,会那掉v-cloak属性。
- 使用css配合v-cloak可以解决网速慢时页面展示出{{xXx]}的问题。
3.73 v-once
v-once指令:
- v-once所在节点在初次动态渲染后,就视为静态内容了。
- 以后数据的改变不会引起v-once所在结构的更新,可以用于优化性能。
3.74 v-pre
v-pre指令:
- 跳过其所在节点的编译过程。
- 可利用它跳过:没有使用指令语法、没有使用插值语法的节点,会加快编译。
3.8 自定义指令
自定义指令总结:
一、定义语法:
- 局部指令:
new vue
directives:{指令名:配置对象}或
directives(){指令名:回调函数}
directives:{
big(element,binding){
console.log('big')
element.innerText = binding.value * 10
},
fbind:{
bind(){
},
inserted(){},
update(){}
}
}
})
2. 全局指令:
Vue.directive(指令名,配置对象)或Vue.directive(指令名,回调函数)
二、配置对象中常用的3个回调:
- bind:指令与元素成功绑定时调用。
- inserted:指令所在元素被插入页面时调用
- update:指令所在模板结构被重新解析时调用。
三、备注:
- 指令定义时不加v-。但使用时要加v-;
- 指令名如果是多个单词,要使用kebab-case命名方式,不要用camelCase命名。
3.9 vue的生命周期
生命周期:
- 又名:生命周期回调的数、生命周期函数、生命周期钩子。
- 是什么:Vue在关键时刻帮我们调用的一些特殊名称的函数。
- 生命周期函数的名字不可更改,但函数的具体内容是程序员根据需求编写的。
- 生命周期函数中的this指向是vm或组件实例对象。
常用的生命周期钩子:
- mounted:发送ajax请求、启动定时器、绑定自定义事件、订阅消息等【初始化操作】
- beforeDestroy:清除定时器、解绑自定义事件、取消订阅消息等【收手工作】。
关于销毁Vue实例:
- 销毁后借助Vue开发者工具看不到任何信息。
- 销毁后自定义事件会失效,但原生DOM事件依然有效。
- 一般不会在beforeDestroy操作数据,因为即便操作数据,也不会再触发更新流程了。
4.0 vue的组件化编程
传统方式编写应用:
- 依赖关系混乱,不好维护
- 代码复用率不高
组件的定义——实现应用中局部功能代码和资源的集合
4.1 模块与组件,模块化与组件化
模块:
- 定义:特定功能的js程序
- 为什么:js文件太多了
- 作用:复用js,简化js
组件:
- 定义:实现应用中局部功能代码和资源的集合
- 为什么:一个界面东西太多了
- 作用:复用编码,简化编码,提高效率
模块化:
当应用中的js都以模块来编写的,那这个应用就是一个模块化的应用。
组件化:
当应用中的功能都是多组件的方式来编写的。那这个应用就是一个组件化的应用
4.2 非单文件组件
Vue中使用组件的三大步骤:
- 定义组件(创建组件)
- 注册组件
- 使用组件(写组件标签)
如何定义一个组件?
使用Vue.extend(options)创建,其中options和new Vue(options)时传入的那个options几乎一样,但也有点区别;区别如下:
- el不要写,为什么?—最终所有的组件都要经过一个vm的管理,由vm中的el决定服务哪个容器。
- data必须写成函数,为什么?一
避免组件被复用时,数据存在引用关系。
备注:便川template可以配置组件结构。
如何注册组件?
- 局部注册:new Vue的时候传入components选项
- 全局注册:作vueponent(‘组件名’,组件)
三、编写组件标签:
<div id="root">
<school></school>
<hr>
<student></student>
</div>
// 创建school组件
const school = Vue.extend({
template:`
<div>
<h2>学校名称:{{schoolName}}</h2>
<h2>学校地址:{{address}}</h2>
</div>`,
data() {
return {
schoolName:'家里蹲',
address:'湖北武汉',
}
},
})
new Vue({
el:'#root',
components:{
school,
student
}
})
- 关于组件名:
一个单词组成:
- 第一种写法(首字母小写):school
- 第二种写法(首字母大写): School
多个单词组成:
- 第一种写法(kebab-case命名):my-school
- 第二种写法(CamelCase命名):MySchool(需要Vue脚手架支持)备注:
-
组件名尽可能回避HTAL中已有的元素名称,例如: h2、H2都不行。
-
可以使用name配置项指定组件在开发者工具中生现的名字。
-
关于组件标签:
第一种写法:第二种写法:
备注:不用使用脚手架时,会导致后续组件不能渲染。
- 一个简写方式:
const school = Vue.extend(options)可简写为: const school = options
4.21 vuecomponent
关于VueComponent:
- 组件本质是一个名为VueComponent的构造函数,且不是程序员定义的,是Vue.extend生成的
- 用的时候,Vue解析时会括我们创建组件的实例对象,vue帮我们执行的: new Vuecomponent(options).
- 特别注意:何次调用vue.extend,返回的都是一个全新的VueComponent! !!!
- this指向:
- 组件配置中:
data函数、methods中的函数、watch中的函数、computed中的函数·它们的this均是Vuecomponent - new Vue()h置中:
data函数、methods中的函数、watch中的函数、computed中的函数·它们的this均是Vue实例对象
- 组件配置中:
- VueComponent的实例对象,以后简称vc(也可称之为:组件实例对象)
vue的实例对象,以后简称vm
4.22 一个重要的内置关系
- 一个重要的内置关系:VueComponent. prototype.proto =a= Vue. prototype
- 为什么要有这个关系:让组件实例对象(vc)可以访问到Vue原型上的属性、方法。
4.3 单文件组件
他的标准结构
其实省略了一个vue.extend()
<template>
<!-- 组件的结构 -->
<div>
</div>
</template>
<script>
export default {
name:'',
data() {
return {
}
},
methods: {
},
}
</script>
<style>
</style>
4.4 使用vue脚手架
- 安装
npm install -g @vue/cli
- 创建项目
vue create xxx
4.5 ref
- 被用来给元素或子组件注册引用信息(id的替代者)
- 应用在html标签上获取的是真实DON元素,应用在组件标签上是组件实例对象(vc)
- 使用方式:
打标识:
<h1 ref="xxx"></h1>或<School ref="xxx"></School>
获取:
this.$refs.xxx
4.6 props
功能:让组件接收外部传过来的教据
- 传递数据:
-
接收数据:
-
(只接收):props: [ "name " ]
-
(限制类型):props:{
name : Number} -
(限制类型、限制必要性、指定默认值):
props:{
name:{
type : String,//类型
required:true,//必要性
default:'帅哥'//默认值
}
}
备注: props是只读的,Vue底层会监测你对props的修改,如果进行了修改,就会发出警告,若业务需求确实需要修改,那么请复制props的内容到data中一份,然后去修改data中的数据。
4.7 mixin(混入)
功能:可以把多个组件共用的配置提取成一个混入对象
使用方式:
第一步定义混合,例如:
{
data(){....},
methods:{....}
}
第二步使用混入,例如:
- 全局混入:Vue.mixin(xxx)
- 局部混入: mixins : [ "xxx "]
4.8 插件
功能:用于增强Vue
本质:包含install方法的一个对象,install的第一个参数是Vue,第二个以后的参数是插件使用者传递的数据。
export default {
install(Vue){
console.log('@@@install',Vue);
}
}
使用:
//引入插件
import plugins from './plugins'
//使用插件
Vue.use(plugins)
4.9 scoped
作用:让样式在局部生效,防止冲突。
写法:
<style lang="less" scoped>
.xuexiao {
background-color: pink;
}
</style>
5.0 组件化编码流程
- 实现静态组件:抽取组件,使用组件实现静态页面效果
- 展示动态数据:
- 数据的类型、名称是什么?
- 数据保存在哪个组件?
- 交互——从绑定事件监听开始·
5.1 儿子怎么给爸爸传数据
爸爸这里定制一个函数,把函数传给儿子
儿子调用这个函数
5.2 做完记事本案例的小结
- 组件化编码流程:
- 拆分静态组件:组件要按照功能点拆分,命名不要与html元素冲突。
- 实现动态组件:考虑好数据的存放位置,数据是一个组件在用,还是一些组件在用:
- 一个组件在用:放在组件自身即可。
- 一些组件在用:放在他们共同的父组件上(状态提升)。
- 实现交互:从绑定事件开始。
- props适用于:
- 父组件==>子组件通信
- 子组件==>父组件通信(要求父先给子一个函数)
- 使用v-model时要切记: v-model绑定的值不能是props传过来的值,因为props是不可以修改的!
- props传过来的若是对象类型的值,修改对象中的属性时Vue不会报错,但不推荐这样做。
5.3 WebStronge游览器的本地存储
loacal Storage 得用操作来清
Session Storage 关了游览器就没了
- 存储内容大小一般支持5MB左右(不同浏览器可能还不一样)
- 浏览器端通过Window.sessionStorage和Window.localStorage属性来实现本地存储机制。
- 相关API:
- xxxxxStorage.setItem( ’ key ’ , 'value ’ );该方法接受一个键和值作为参数,会把键值对添加到存储中,如果键名存在,则更新其对应的值。
- xXxxxStorage-getItem( ’ person ’ );该方法接受一个键名作为参数,返回键名对应的值。
- xxxxxStorage.removeItem( ’ key ');该方法接受一个键名作为参数,并把该键名从存储中删除。
- ×XXxxStorage.clear()该方法会清空存储中的所有数据。
- 备注:
- SessionStorage存储的内容会随着浏览器窗口关闭而消失。
- LocalStorage存储的内容,需要手动清除才会消失。
- xxxxxStorage.getItem(xxx)如果xxx对应的value获取不到,那么getltem的返回值是null。
- jSON.parse(null)的结果依然是null。
5.4 组件内自定义事件
- 一种组件间通信的方式,适用于子组件===→>父组件
- 使用场景:A是父组件,B是子组件,B想给A传数据,那么就要在A中给B绑定自定义事件(事件的回调在A中)。
- 绑定自定义事件:
1.第一种方式,在父组件中:
<Demo @xiba="test"/>或<Demo v-on:xiba="test"/>
- 第二种方式,在父组件中:
<Demo ref="demo" />
mounted(){
this.$refs.xxx.$on( 'xiba ' ,this.test)}
-
若想让自定义事件只能触发一次,可以使用once修饰符,或$once方法。
-
触发自定义事件:this.$emit( 'xiba ’ ,数据)
-
解绑自定义事件this.$off( 'xiba ')
-
组件上也可以绑定原生DOM事件,需要使用native修饰符。
-
注意:通过this.$refs.xx. $on(" xiba’,回调)绑定自定义事件时,回调要么配置在methods中,要么用箭头函数,否则this指向会出问题!
5.5 全局事件总线
- 一种组件间通信的方式,任意组件通信
- 先配置一下
在main.js的vue实例对象里
// 创建vm实例
new Vue({
el:'#app',
render:h =>h(App),
//创建全局公交车
beforeCreate() {
Vue.prototype.$bus=this
},
})
- 使用
// 1.接收数据:A组件想接收数据,则在A组件中给$bus绑定自定义事件,事件的回调留在A组件自身。
methods(){
demo(data){ ......}
}
mounted() {
this.$bus.$on( 'xxxx ' ,this.demo)}
//2. 提供数据:this.$bus. $emit( 'xxxx',数据)
- 最好在beforeDestroy钩子中,用$off去解绑当前组件所用到的事件。
5.6 消息订阅与发布
- 组件通信的方法,适用于任何组件通信
- 使用步骤
- 安装 npm i pubsub-js
- 引入 import pubsub from ‘pubsub-js’
- 接受数据
//组件A要数据,在A里订阅,回调也放A
methods(){
demo(data){xxx}
}
mouted(){
this.id=pubsub.subscribe('xxx',this.demo)//订阅消息
}
- 提供数据pubsub.publish(‘xxx’,data)
- 在beforeDestory里销毁一下
- pubsub.unsubscribe(pid)
5.7 nextTick
- 语法 :this.$nextTick
- 作用 :在下一次dom跟新结束后执行其指定的回调
- 什么时候用:当改变数据后,要基于更新后的dom进行操作时,在nextTick指定的回调函数中执行
5.8 Vue封装的过渡与动画
作用:在插入跟新移除dom元素时,给元素添加样式类名
进入 v-enter-active
离开 v-leave-active
元素要用transition包裹,配置name属性
多个元素用transition-grop
5.9 配置代理
用axios
5.91 跨域
协议名,主机名,端口名
服务器东西给我了 ,我拿不到
解决办法
- cors
让后端配置响应头
- jsopn 行 但几乎不用,只能解决get
借助script src 引入外部资源不受限制
-
nginx
-
vue-cli (重点)
在vue.config.js里配置
module.exports = {
pages:{
index:{
//入口
entry:'src/main.js',
}
},
// lintOnSave:false,//关闭语法检查
// 开启代理服务器
devServer:{
Proxy:'http://localhost:4000'
}
- 优点:配置简单,请求资源时直接发前端(8080)即可。
- 缺点:不能配置多个代理,不能灵活的控制请求是否走代理。
- 工作方式:若按照上述配置代理,当请求了前端不存在的资源时,那么该请求会转发给服务器(优先匹配前端资源)
解决办法
配置多个代理的方式
在axios加前缀
devServer: {
proxy: {
'/api': {
target: 'https://autumnfish',
changeOrigin: true,// 请求头hots
ws: true,
pathRewrite: { '^/api': '' }
}
}
- 优点:可以配置多个代理。且可以灵活的控制请求是否走代理
- 缺点:配置略微繁琐,请求资源时必须加前缀。
5.92 插槽slot
挖个洞准备放东西
- 默认插槽 没名字的
- 具名插槽 有名字的
- 作用域插槽
最新写法
template v-slot:xxx
作用域插槽
理解: 数据在组件的自身,但根据数据生成的结构需要组件的使用者来决定。
就像创建了奇异博士的传送门,把数据传过去
6.0 VueX
6.1 什么是Vuex
- 概念: 专门在 Vue中实现集中式状态(数据)管理的一个Vue插件,对vue应用中
多个组件的共享状态进行集中式的管理(读/写),也是一种组件间通信的方式,且适用于任意组件间通信。
6.2 什么时候用
- 多个组件依赖于同一状态
- 来自不同组件的行为需要变更同—状态
6.3 vuex的 工作原理 重点
- 组件实例vue components 消费者来吃饭的
- 他的操作 服务员 来份大碗宽面{dispatch(‘dawamkuanmian’,1)}
- Actions 服务员
- 提交给大厨{commit(‘dawankuanmian’,1)}
- Mutaions 后厨
- 开始操作
- state 菜
- store 餐馆
6.4 安装配置使用
- npm i vuex
- 在src 中 创建store 文件夹 ,index.js文件
//该文件创建vuex的store
import Vue from 'vue'
// 引入vuex
import Vuex from 'vuex'
Vue.use(Vuex)
// 用于响应组件的动作
const actions = {}
//mutaions操作数据
const mutations = {}
//state存取数据
const state = {}
// 创建store 导出store
export default new Vuex.Store({
actions,
mutations,
state,
})
- 在main.js 中导入stroe
// 引入vue
import Vue from "vue";
//引入app
import App from './App.vue'
// 引入store
import store from './store'
// 关闭vue的生产提示
Vue.config.productionTip = false
// 创建vm实例
new Vue({
el:'#app',
render:h =>h(App),
store,
//创建全局公交车
beforeCreate() {
Vue.prototype.$bus=this
},
})
- 读取数据 $store.state.xxx
- 修改vuex的数据 $store.dispatch(‘action中的方法名’,数据)
没有网络请求或其他业务逻辑,
组件可以直接提交,写commit
getters 不常用,像commputed
要写返回值的
state像data
6.5 mapState
对象写法
computed:{
...mapState({he:'sum'})
},
数组写法
computed:{
...mapState(['sum',xxx])
},
mapGetters 同理
6.6 vuex的模块化
作用: 让代码更好维护,让多种数据分类明确
- 修改store,js
const countAbout = {
namespaced:true, //开启命名空间
state:{sum:0},
actions:{
add(context,value){
contextmit('ADD',value)
}
},
mutations:{
ADD(state,value){
state.sum+=value
}
}
}
// 用于响应组件的动作
//mutaions操作数据
//state存取数据
// 创建store 导出store
export default new Vuex.Store({
modules:{
countAbout
}
})
- 读取state数据
借助mapState读取
computed:{
...mapState('countAbout',['sum'])
},
自己读取
this.$store.state.对象名.xxx
- 读取getters数据
借助mapGetters
...mapGetters('countAbout',['xxx'])
自己读取
this.$store.getters['xxx/xxx']
- 调用dispatch
methods: {
...mapActions('countAbout',{addNumber:'add'})
},
- 调用commit
借助mapMuteions
...mapMutations('countAbout',addNumber:'add')
7.0 v-router 路由
是一个插件库,用来实现spa应用
7.1 spa应用
- 单页Web应用(single page web application,SPA)。
- 整个应用只有一个完整的页面
- 点击页面中的导航链接不会刷新页面,只会做页面的局部更新。
- 数据需要通过ajax请求获取。
7.2 对于路由
- 什么是路由
- 一个路由就是一组映射关系(key-value)
- key是路径,value是function或component
7.21 路由分类
后端路由:
- 理解: value是function,用于处理客户端提交的请求。
- 工作过程:服务器接收到一个请求时,根据请求路径找到匹配的函数来处
理请求,返回响应数据。
前端路由:
- 理解:value是component,用于展示页面内容
- 当浏览器的路径改变时,对应的组件就会显示。
7.22 安装
- npm 安装
npm i vue-router
- vue.use(vueRouter)应用
- 编写router
//用于创建整个应用的路由器
import VueRouter from 'vue-router'
import About from '../components/About'
import Home from '../components/Home'
//创建一个路由器
export default new VueRouter ({
routes:[
{path:'/about',
component:About
},
{path:'/home',
component:Home
},
]
})
- 实现切换
router-link to
<router-link to="/about" active-class="active">About</router-link>
<router-link to="/home" active-class="active">Home</router-link>
- 指定展示位置
<router-view></router-view>
注意:
- 路由组件通常存放在pages文件夹,一般组件通常存放在 components文件夹。
- 通过切换,“隐藏"了的路由组件,默认是被销毁掉的,需要的时候再去挂载。
- 每个组件都有自己的$route属性,里面存储着自己的路由信息。
- 整个应用只有一个router,可以通过组件的$router 属性获取到。
7.3 嵌套路由
- 配置children配置
page要去掉/
- 跳转的时候写完整路径
routes: [
{
path: '/about',
component: About
},
{
path: '/home',
component: Home,
children:[
{
path:'news',
component:News
},
{
path:'message',
component:Message
}
]
},
7.4 路由传参
- 传递参数
//字符串写法
<router-link :to="`/home/message/detail?id=$(m.id)&title=$(m.title)`">{{m.title}}</router-link>
//对象写法
<router-link :to="{
path:'/home/message/detail',
query:{
id:m.id,
title:m.title
}
}">
{{m.title}}</router-link>
- 接受参数
this.$route.query.xxx
给路由器命名
简化路由跳转
//加个name属性
children:[
{
name:'xiangqing',
path:'detail',
component:Detail,
}
]
可以写成这样
<router-link :to="{
path:'xiangqing',
query:{
id:m.id,
title:m.title
}
}">
{{m.title}}</router-link>
7.4 路由的params参数
- 声明接收函数
path:'xxx/:xx/:xxx'
- 传递参数
:to ="home/xx/参数/参数"
//对象写法
:to="{
name:'xxx',
params:{
id:xxx,
title:'xxx'
}
}"
特别注意:路由携带params参数时,若使用to的对象写法,则不能使用path配置项,必须使用name配置!
- 接受参数
$route.params.id
$route.params.title
7.5 路由的props设置
三种写法
//第一种写法:
props值为对象,该对象中所有的key-value的组合最终都会通过props传给Detail组件
//props:{a:9}
//第二种写法:props值为布尔值,布尔值为true,则把路由收到的所有params参数通过props传给Detail组件
//props :true
//第三种写法:
props值为函数,该函数返回的对象中每一组key-value都会通过props传给Detail组件
props(route){
return {
id:route.query.xxx,
title:route.query.xxx
}
}
7.6 replace
- 作用:控制路由跳转时操作浏览器历史记录的模式
- 浏览器的历史记录有两种写入方式:分别为push和replace,push 是追加历史记录,replace 是替换当前记录。路由跳转时候默认为push
- 如何开启replace模式:
属性里加个replace
7.7 编程式路由导航
- 作用:不借助 实现路由跳转,让路由跳转更加灵活
具体编码:
用router的两个api
pushShow(m){
this.$router.push({
name:'xiangqing',
query:{
id:m.id,
title:m.title
}
})
},
replace(m){
this.$router.replace({
path:'/home/message/detail',
query:{
id:m.id,
title:m.title
}
})
}
- forward 前进
- back 后退
- go 正进后退
7.8 缓存路由组件
- 作用:让不展示的路由组件保持挂载,不被销毁
- 具体编码:
<keep-alive include="News" >
<router-view></router-view></ keep-alive>
//写法二:
:include="['xxx','xxx']"
新生命钩子
被激活 :activated
失活:deactivated
7.9 路由守卫
- 作用:对路由进行权限控制
- 分类:全局守卫.独享守卫、组件内守卫
router.beforeEach 前置守卫
前置守卫有三个参数 to from next ,next代表放行 ,to代表要去的地方,from 代表从哪儿来的
router.afterEach 后置守卫
beforEnter 独享路由守卫 某个路由独享,只有前置
组件内路由守卫
进入的时候
通过路由规则
beforeRouteEnter 进入组件被调用
beforeRouteLeave 离开时组件被调用
8.0 打包和部署
- 在项目运行 npm run serve
- 新建文件夹 npm init
- 配置一个server.js
const express = require('express')
const app = express()
app.use(express.static(__dirname+'/static'))
app.get('/person',(req,res)=>{
res.send({
name:'yuehan',
age:18
})
})
app.listen(5005,(err)=>{
if(!err) console.log('服务器启动成功')
})
-
把dist文件弄过来
-
node server
-
对于一个url来说,什么是hash值?——#及其后面的内容就是hash值。
-
hash值不会包含在HTTP请求中,即: hash值不会带给服务器。
-
hash模式:
- 地址中永远带着#号,不美观。
- 若以后将地址通过第三方手机app分享,若app校验严格,则地址会被标记为不合法。
- 兼容性较好。
-
history模式:
- 地址干净,美观。
- 兼容性和hash模式相比略差。
- 应用部署上线时需要后端人员支持,解决刷新页面服务端404的问题。
8.1 ui库
移动端
Vant
Cube UI
Mint ui
pc端
element ui
iview ui
按需引入很重要
要这么配置
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset',
["@babel/preset-env", { "modules": false }]
],
plugins: [
[
"component",
{
"libraryName": "element-ui",
"styleLibraryName": "theme-chalk"
}
]
]
}
更多推荐
vue详细知识,语法和必备知识
发布评论