就是localstorage和sessionstorage这两个( 前者浏览器关闭不会清空,后者关闭浏览器会清空 ),二者常用的API都一模一样,二者里面存的数据都是key-value的形式
二者存储的内容大小一般为5M的字符串( 不同浏览器可能会不一样 )
mounted()中是可以进行异步操作的啊,所以才可以让这种自定义事件更灵活
另外:既然是事件,那么也可以使用事件修饰符:prevent、stop、once
这玩意用的就是VueComponent.$off( ['要解绑的事件名'] )这个内置函数来实现解绑的,
说在beforeDestroy中,会销毁子组件和自定义事件
子组件是如下的样子
1、在ref属性实现的方式中,关于this的指向问题
第一种就是将回调函数放到父组件的methods中
第二种:将回调函数直接放到this.\(refs.people.\)on( 'event',xxxx ) ]中的xxxx中:
2、组件使用原生DOM事件的坑【 ps:了解native修饰符,学后端的人看源码的时候,对这个修饰符再熟悉不过了 】
自定义事件是一种组件间通信的方式,适用于:子组件 ——> 父组件通信
使用场景:想让子组件给父组件传递数据时,就在父组件中给子组件绑定自定义事件【 ps:事件回调在父组件methods / 其他地方 中 】,而要解绑自定义事件就找子组件本身
绑定自定义事件:
1、在父组件中:<Person @zixieqing="demo"/>
或 <Person v-on:zixieqing="demo"/>
2、在父组件中:
3、若想让自定义事件只能触发一次,可以使用once修饰符【 ps:使用v-on的方式实现的那种 】 或 $once【 ps:使用ref属性实现方式的那种 】
触发自定义事件: this.$emit('eventName',sendData)
【 ps:给谁绑定自定义事件,就找谁去触发 】
解绑自定义事件:this.$off(['eventName',.......])
【 ps:给谁绑定自定义事件,就找谁解绑;另:注意解绑事件是单个、多个、全解的写法 】
组件上也可以绑定元素DOM事件,但是:需要使用native修饰符
注意项:通过this.$refs.xxxx.$on('eventName',回调)
绑定自定义事件时,回调要么配置在父组件的methods中,要么用兰姆达表达式【 ps:或箭头函数 】,否则:this执行会出现问题
VueComponent.prototype._ _proto _ _ === Vue.prototype
从而实现出来的一个开发技巧但是:现在把思路换一下来实现它
通过上面的分析图了解之后,就可以分析出:单独选取的那个组件需要具有如下的特性:
1、那么为了实现第一步:能够让所有的组件都看得到可以怎么做?
1)、使用window对象,可以做到( 但是:不推荐用 )
2、就是利用Vue中的内置关系VueComponent.prototype._ _proto _ _ === Vue.prototype
,即:公共组件选为Vue实例对象vm,这个诶之关系怎么来的,这里不再说明了,在基础篇VueComponent()中已经说明过了,利用此内置关系就是利用:VueComponent可以获取Vue原型上的属性和方法,同时选取了Vue实例对象之后,\(on()、\)emit()、$off()都可以调用了,这些本来就是Vue的内置函数啊,Vue实例对象还没有这些函数吗
实例演示:
全局事件总线又名GlobalEventBus
它是一种组件间的通信方式,可以适用于任何组件间通信
全局事件总线的玩法:
1、安装全局事件总线
2、使用事件总线
发送数据:this.$bus.$emit('EventName',sendData)
接收数据:A组件想接收数据,则:在A组件中给$bus绑定自定义事件,把事件的回调放到A组件自身中【 ps:靠回调来得到数据 】
什么是消息订阅与发布?
基础代码
1、给项目安装pubsub-js库,指令:npm install pubsub-js
2、消息发布方
2.1、引入pubsub-js库
2.2、使用publish( 'msgName' , sendData )这个API进行数据发送
3、消息接收方
4、效果如下
它是一种组件间通信的方式,适用于:任意组件间通信
使用步骤:
1、安装pubsub-js 指令:npm install pubsub-js
2、消息接收方、发送方都要引入pubsub 代码;:import pubsub from "pubsub-js"
数据发送方:pubsub.publish('msgName',sendData)
数据接收方:
1、基础代码
需求、让食品分类中显示具体的一张食品图片、让电影分类中电视某一部具体的电影,使用默认插槽改造
需求、在电影分类的底部显示"热门"和"悬疑" 基础代码 需求:多个组件一起使用,数据都是一样的,但是有如下要求: 开始改造代码: 第一步:提data 第二步:使用作用域插槽进行改造 既然作用域插槽会玩了,那就实现需求吧 另外:父组件接收数据时的scope还有一种写法,就是使用slot-scope 1、作用:让父组件可以向子组件指定位置插入HTML结构,也是一种组件间通信的方式,适用于:父组件 ===》 子组件 2、分类:默认插槽、具名插槽、作用域插槽 3、使用方式 1)、默认插槽 // 父组件 2)、具名插槽 // 父组件 3)、作用域插槽 // 子组件 所以:把官网的原图改一下 1、在项目中安装vuex 指令:npm install vuex 2、编写store 3、让store在任意组件中都可以拿到 vuex环境搭建小结 1、创建文件src/store/index.js // 引入vuex 2、在main.js中配置store import App from "./App.vue" 1、先把要操作的数据 / 共享数据放到state中 2、在组件中使用dispatch这个API把key-value传给actions 2、actions接收key-value【 ps:要是有逻辑操作,也放在这里面,ajax也是 】 3、mutations接收key-value 4、查看开发者工具【 ps:简单了解,自行万一下 】 另外:vuejs devtools开发工具版本不一样,则:页面布局也不一样,但是:功能是一样的 当然:前面说过,直接在组件中调commit这个API从而去和mutations打交道,这种是可以的,适用于:不需要逻辑操作的过程,示例就自行完了 以上便是简单了解vuex,前面的例子看起来没什么用,但是vuex这个东西其实好用得很 1、改造源代码 —— 使用计算属性实现 2、使用mapState改造获取state中的数据,从而生成计算属性 3、使用mapGetters把getters中的东西生成为计算属性 1、mapActions —— 调的API就是dispatch 使用mapActions改造 2、mapMutations —— 这个和mapActions一模一样,只是调用的API是commit 1、在state中再加一点共享数据 2、新增Person组件 3、共享数据 操作如下: 路由:就是一组key-value的映射关系 也就是route 路由器 router:就是专门用来管理路由的【 ps:理解的话,就参照生活中的那个路由器,它背后有很多插孔,然后可以链接到电视机,那个插孔就是key ,而链接的电视机就是value嘛 】 在vue中,router路由器是一个插件库,所以需要使用 所谓的单页面网站应用就是 SPA,即:只在一个页面中进行操作,路径地址发生改变即可,然后就把相应的东西展示到当前页面,不会发生新建标签页打开的情况【 参照美团网址,进行点一下,看看地址、页面更新、是否新建标签页打开、美团就是单页面网站应用 】 路由:就是一组key-value的映射关系 也就是route 路由器 router:就是专门用来管理路由的【 ps:理解的话,就参照生活中的那个路由器,它背后有很多插孔,然后可以链接到电视机,那个插孔就是key ,而链接的电视机就是value嘛 】 在vue中,router路由器是一个插件库,所以需要使用 所谓的单页面网站应用就是 SPA,即:只在一个页面中进行操作,路径地址发生改变即可,然后就把相应的东西展示到当前页面,不会发生新建标签页打开的情况【 参照美团网址,进行点一下,看看地址、页面更新、是否新建标签页打开、美团就是单页面网站应用 】 1、准备工作: 1)、引入bootstrap.css 2、开始玩路由器 router 1)、给项目安装路由 指令: 2)、在main.js中引入并使用路由器【 ps:路由器是一个插件 】 3)、编写组件 4)、配置路由器【 ps:这也叫配置路由规则,就是key-value的形式,在前端中,key是路径,value是组件 】 5)、把配置的路由规则引入到main.js中 6)、在静态页面中使用路由【 ps:需要记住两个标签 页面结构源码如下:
7)、运行效果如下: 另外:从此处开始,可以先摸索Element-ui组件库了,这是专门搭配vue来做页面的网站 和 bootstrap一个性质,这个东西后续要用,网址如下: vue-router使用小结 1、安装vue-router ,命令: 2、在main.js中 指令: 3、应用vue-router插件,指令: 4、编写router路由规则 // 引入路由器 5、实现切换( active-class 可配置高亮样式 ) 6、指定展示位置 1、在src/page下再新建两个路由组件 2、给home路由规则编写多级路由 3、重新编写Hmoe.vue路由组件 源码如下:
4、运行效果如下 1、query的字符串传参写法【 ps:也就是路径传参嘛,适合传递少量参数 】 1)、编写数据,改造Message.vue路由组件【 ps:传递数据者 】 2)、编写Detail.vue路由组件【 ps:数据接收者 】 3)、编写路由规则 4)、效果如下: 2、query的对象写法 【 ps:适合传递大量参数 】 实例: 1)、修改路由规则 2)、使用命名路由精简path 3)、运行效果如下 命名路由小结 作用:简化路由跳转时的path写法 使用: 给命令命名 简化路由跳转写法 1、使用params传递参数【 ps:数据的传递者 】,这一步和以前的query传递没什么两样,只是改了一个名字而已 1)、字符串写法 / 对象写法 2)、修改路由规则 3)、获取参数 【 ps:和query相比,就是数据存放的位置变了一下而已,可以在mounted中输出this.$route看一下结构 】 4)、效果如下 路由params传参小结 1、配置路由 2、传递参数 注意点:路由携带params参数时,若使用的to的对象写法,则:不能使用path配置项,必须用name配置项 3、接收参数 1、布尔值写法 为true时,则把path接收到的所有params参数以props的形式发给所需路由组件, 如:这里的Detail 2、函数写法 这种写法:是最灵活的一种,props为函数时,该函数返回的对象中每一组key-value都会通过props传给所需数据的路由组件【 ps:如这里的Detail 】 3、另外的方式 上面这种模式就是push模式,它的原理就是栈空间,压栈push嘛【 ps:router-link中的默认模式就是push模式 】 但是还有一种模式是:replace模式,这种模式是产生一个记录之后,就把上一次的记录给干掉了,所以效果就是不会有回退的记录,回退按钮都点不了【 ps:就是走一路短一路,没后路了 ^ _ ^ ,要实现这种模式也简单,就是:在router-link中加一个replace属性即可 】 router-link的replace属性小结 1、玩一下push和replace这两个API 2、玩一下back和forward这两个API 3、玩一下go这个API 1、缓存一个路由组件 —— 字符串写法 2、缓存多个路由组件 —— 数组写法 1、另一对生命钩子 这一对生命钩子就是:activated 和 deactivated,其中: 实例: 2、另外一个钩子函数就是nextTick **所谓的全局前置路由守卫,特点之一就体现在前置二字上,它的API是beforeEach( ( to, from, next ) => { } ),也就是:在路由切换之前回调会被调用 / 初始化渲染时回调会被调用 ** 实例: 现在做一个操作,在浏览器中缓存一个key-value,然后访问News、Message路由时判断key-value是否对得上,对就展示相应的路由组件,否则:不展示 当然:前面的过程有一个小技巧可以简化 给路由规则添加一个meta配置项,就是路由元数据,利用这个配置项,我们可以给路由中放一些我们想放的东西进去【 ps:哪个路由需要权限验证,就在哪个路由中加入meta配置项 】,那就改造吧 这玩意儿就和全局前置路由守卫反着的嘛,但是:处理场景不一样 全局后置路由守卫 调用的API是afterEach( ( to, from ) => { } ),注意:和全局前置路由守卫相比,少了next参数,后置了嘛,都已经在前面把权限判断完了,你还考虑放不放行干嘛,这个全局后置路由守卫做的事情其实不是去判断权限问题,而是收尾,做一些过了权限之后的判断问题,比如:点击某个路由组件之后,只要可以查看这个组件内容,那么:就把网页的页签标题给换了 这个API是 初始化渲染时回调会被调用 / 路由组件切换之后会被调用, 实例: 操练一手:【 ps: 先用纯的全局前置路由守卫来做 】 先加点东西进去 上面看起来成功了,但是有bug,可以试着把network中的网络调成slow 3G,可以稍微清楚地看到效果 ,想要改成功,就算把项目中 public/index.html的title改了,也是一样,会有加载过程,因此:想在全局前置路由守卫中达到想要的效果,改出花儿来也莫得办法,而且在全局前置路由守卫中写两遍一样的代码根本不标准 想要实现前面的效果,那就需要全局后置路由守卫登场了,掉一下API,里面一行代码搞定 这玩意儿就是指:某一个路由独享的路由守卫,调用的API是:beforeEnter( ( to, from, next )=>{ } ),它是指:在进入配置这个API的路由之前回调会被调用,其中:to、from、next的意思和前面全局前置路由守卫一样,但注意:这种没有什么后置之类的,它只有这一个前置,即:独享路由守卫 最后:路由守卫之间,是可以随意搭配的 实例: 这两种模式是:hash和history模式 hash模式 路由器的默认模式 就是路径中有一个#,这#后面的内容不用随http传给服务器,服务器也不会收到【 ps:前端玩一下而已 】,注意:这个hash和后端中的hash算法哪些东西不一样啊,别搞混了 history模式 这个就好理解了嘛,就是没有了那个#,然后路径中ip:port之后的东西是会随着http传给服务器的 hash和history两种模式的区别: 在路由器中hash和history两种模式的切换 在路由规则中加个全新的配置项mode即可 1、编写完了程序之后打包项目 2、使用node+express框架编写一台小服务器模拟一下上线 自行新建一个文件夹,然后使用vscode打开 1)、让文件夹变成合法包 指令: 2)、安装express 指令: 3)、新建一个js文件,编写内容如下 源码如下: // 1、引入express 注意:这里就不是ES6的模块化了,而是commanjs模块化 4)、启动服务器 指令: 5)、访问服务器中的端口测试一下 3、准备工作弄完了,现在把刚刚使用 4、让复制进去的文件能够被服务器认识 Vue2到此结束,另外还有一些Vue UI组件库 移动端 PC端 接下来的技术点就是:Vue3
<Category title = "游戏">
<ul>
<li v-for=" (game,index) in games" :key="index">{{game}}</li>
</ul>
</Category>
<Category title = "电影">
<video controls src="./assets/枕刀歌(7) - 山雨欲来.mp4"></video>
</Category>
</div>
</template>
<script>
import Category from "./components/Category.vue"
export default {
name: 'App',
components: {Category},
data() {
return {
foods: ['紫菜','奥尔良烤翅','各类慕斯','黑森林','布朗尼','提拉米苏','牛排','熟寿司'],
games: ['王者荣耀','和平精英','英雄联盟','文明与征服','拳皇','QQ飞车','魔兽争霸'],
filems: ['无间道','赤道','禁闭岛','唐人街探案1','肖申克的救赎','盗梦空间','无双']
}
},
}
</script>
<style>
.container {
display: flex;
justify-content: space-around;
}
img,video {
width: 100%;
}
</style></code></pre></li>
3.6.2、具名插槽
3.6.3、作用域插槽
3.6.4、插槽总结
// 子组件
<template>
<div>
<!-- 定义插槽 -->
<slot>插槽默认内容</slot>
</div>
</template>
// 子组件
<template>
<div>
<!-- 定义插槽 并 起个名字-->
<slot name = "footer">插槽默认内容</slot>
</div>
</template>
{{title}}分类
<script>
export default {
name: 'Category',
props: ['title'],
data() { // 数据在子组件自身中
return {
filems: ['无间道','赤道','禁闭岛','唐人街探案1','肖申克的救赎','盗梦空间','无双']
}
},
}
</script>
// 父组件
<template>
<div class="container">
<Category title = "电影">
<!--
2、父组件( 接收数据 )
前面说的 多了一个要求 就是这里"必须用template标签套起来"
怎么接收?使用scope="xxxx"属性 xxx就是接收到的数据,这个名字随便取
这个名字不用和子组件中用的 :filems 这个filems这个名字保持一致,因:它接收的就是这里面传过来的东西
但是:这个数据有点特殊,需要处理一下
-->
<template scope="receiveData">
<!-- {{receiveData}} -->
<!-- 拿到了数据,那"页面的结构就可以随插槽的使用者随便玩"了 -->
<ul>
<li v-for="(filem,index) in receiveData.filems" :key="index">{{filem}}</li>
</ul>
</template>
</Category>
</div>
</template>
<script>
import Category from "./components/Category.vue"
export default {
name: 'App',
components: {Category},
}
</script></code></pre></li></ul>&lt;Category title = "电影"&gt;
&lt;!-- ES6中的"结构赋值"简化一下 --&gt;
&lt;template scope="{filems}"&gt;
&lt;ol&gt;
&lt;li v-for="(filem,index) in filems" :key="index"&gt;{{filem}}&lt;/li&gt;
&lt;/ol&gt;
&lt;/template&gt;
&lt;/Category&gt;
&lt;Category title = "电影"&gt;
&lt;!-- ES6中的"结构赋值"简化一下 --&gt;
&lt;template scope="{filems}"&gt;
&lt;h4 v-for="(filem,index) in filems" :key="index"&gt;{{filem}}&lt;/h4&gt;
&lt;/template&gt;
&lt;/Category&gt;
&lt;!-- scope还有一种写法 使用slot-scope--&gt;
&lt;Category title = "电影"&gt;
&lt;!-- ES6中的"结构赋值"简化一下 --&gt;
&lt;template slot-scope="{filems}"&gt;
&lt;h4 v-for="(filem,index) in filems" :key="index"&gt;{{filem}}&lt;/h4&gt;
&lt;/template&gt;
&lt;/Category&gt;
3.7、Vuex
3.7.1、vuex原理
3.7.2、搭建Vuex环境
import vuex from "vuex"
// 使用vuex —— 需要vue 所以引入vue
import Vue from "vue"
Vue.use(vuex)
// 创建store中的三个东西actions、mutations、state
const actions = {}
const mutations = {}
const state = {}
// 创建store ———— 和创建vue差不多的套路
export default new vuex.Store({
// 传入配置项 ———— store是actions,mutations,state三者的管理者,所以配置项就是它们
actions, // 完整写法 actions:actions ,是对象嘛,所以可以简写
mutations,state
})</code></pre></li></ul>
import Vue from "vue"
// 引入store
import store from "./store"
// 由于起的名字是index,所以只写./store即可,这样默认是找index,没有这个index才报错
const vm = new Vue({
render: h=>h(App),
components: {App},
// 让store能够被任意组件看到 ———— 加入到vm配置项中【 ps:和全局事件总线很像 】
store,
template: `<App></App>`,
}).$mount('#app')</code></pre></li></ul>
3.7.3、简单玩一下vuex的流程
3.7.4、认识getters配置项
3.7.5、四个map方法
3.7.5.1、mapState和mapGetters
import {mapState} from "vuex"
...mapState({sum:'sum'})
这里面的sum:'sum'
这两个是一样的,那么:一名多用
import {mapState,mapGetters} from "vuex"
3.7.5.2、mapActions 和 mapMutations
import {mapActions} from 'vuex'
3.7.6、简单玩一下组件共享数据
3.8、路由器 router
3.8.1、认识路由和路由器
npm install vue-router
来进行安装,这个东西就是专门用来做单页面网站应用的
一个完整的页面
、点击页面中的导航链接不会刷新页面
,只会做页面的局部刷新
、数据需要通过ajax请求获取3.12、路由器 router
3.12.1、认识路由和路由器
npm install vue-router
来进行安装,这个东西就是专门用来做单页面网站应用的
一个完整的页面
、点击页面中的导航链接不会刷新页面
,只会做页面的局部刷新
、数据需要通过ajax请求获取3.12.2、简单使用路由器
npm install vue-router
<router-link ..... to = "路径名"></router-link>
和 <router-view></router-view>
]
<router-link ..... to = "路径名"></router-link>
是指:跳转 其中:路径名 就是 路由规则中配置的 path 参照a标签来理解 本质就是转成了a标签<router-view></router-view>
是指:视图显示 就是告知路由器 路由规则中配置的component应该显示在什么位置,和slot插槽一样,占位
Vue Router Demo
<script>
export default {
name: 'App',
}
</script>
npm install vue-router
import VueRouter from "vue-router"
Vue.use(VueRouter)
import VueRouter from "vue-router"
// 引入需要进行跳转页面内容的组件
import About from "../components/About.vue"
import Home from "../components/Home.vue" // 创建并暴露路由器
export default new VueRouter({
routes: [ // 路由器管理的就是很多路由 所以:routes 是一个数组
{ // 数组里面每个路由都是一个对象 它有key和value两个配置项【 ps:还有其他的 】
path: '/about', // 就是key 也就是路径名,如:www.baidu.com/about这里的about
component: About // 就是value 也就是组件
},{
path: '/home',
component: Home
},
]
})
3.12.3、聊聊路由器的一些细节
$route
属性,里面存储这自己的路由信息
$router
属性获取到【 ps:验证自行把不同组件的这个东西绑定到window对象上,然后等路由组件挂载完毕了,拿到它们进行比对,答案是:false 】
3.12.4、多级路由
我是Home的内容
<script>
export default {
name: 'Home'
}
</script>
3.12.5、路由传参
3.12.6、命名路由
path: '/home',
component: Home,
children: [
{
path: 'news',
component: News
},{
path: 'message',
component: Message,
children: [
{
path: 'detail',
// 使用另一个配置项name 命名路由,从而让path更精简
name: 'detail',
component: Detail
}
]
},
]
},
<!-- 简化后写法 -->
<router-link
:to="{
name: 'detail',
query: {
id: m.id,
title: m.title
}
}">
{{m.title}}
</router-link>
3.12.7、路由另一种传参 - params
path: '/home',
component: Home,
children: [
{
path: 'news',
component: News
},{
path: 'message',
component: Message,
children: [
{
// 使用params传参,则:需要把path的规则改了,就是占位,接对应参数
path: 'detail/:id/:title',
name: 'detail', // 对象写法,必须保证有这个配置项
component: Detail
}
]
},
]
},
<!-- 对象写法
这种写法必须保证里面是name,而不是params,否则:页面内容会丢失的
-->
<router-link
:to="{
name: 'detail',
params: {
id: m.id,
title: m.title
}
}">
{{m.title}}
</router-link>
{{$route.params.title}}3.12.8、路由的props配置项
this.$route.queru / params.xxxx
代码量大的话,这不就还得多写N多this吗
3.12.9、router-link中的replace属性
push
和replace
,其中:push
是追加历史记录,replace
是替换当前记录,路由跳转时默认为push
<router-link replace ......>News</router-link>
3.12.10、编程式路由导航
router-link
来实现路由跳转,前面玩了$route
,而现在就是来玩的$router
$router
这个东西,顺便知道掌握哪些API,就是下图中的五个
3.12.11、缓存路由组件
<keep-alive include = "componentName"></keep-alive>
标签来实现
3.12.12、另外的生命钩子
keep-alive include = "xxx"
保留改组件,切换后不让其销毁【 ps:beforeDestroy不起作用了 】,那么:又想要最后关掉定时器之类的,就可以使用这两个钩子函数
3.12.13、路由守卫 - 重要、开发常用
3.12.13.1、全局前置路由守卫
3.12.13.2、全局后置路由守卫
3.12.13.3、独享路由守卫
3.12.14、路由器的两种工作模式
3.12.15、关于项目上线的问题
npm run serve
,在脚手架时就说过还有一个命令:npm run build
,那时说过:后端要的前面资源是HTML+CSS+JS,所以此时项目打包就需要用到它了
npm init
npm install express
注意:这一步很容易因为自己当初配置nodejs时操作不当,导致权限不够啊,就会报一堆warn和error
const express = require('express')
// 2、创建一个app服务实例对象
const app = express()
// 3、端口号监听
app.listen(8001,(err)=>{ // err是一个错误对象
if( !err ) console.log("服务器启动成功");
})
// 4、配置一个后端路由
app.get('/person',(req,res)=>{ // req就是request res就是response
res.send({
name: '紫邪情',
age: 18
})
})</code></pre></li></ul>
node server
npm run build
打包的dist中的文件复制到服务器中去
node server
开始演示路由器的两种工作模式的另一个坑【 ps:别忘记有个权限认证啊,在缓存把对应东西放上,不然有些路由组件点不了 】
http://localhost:8001/home/news
中的/home/news,服务器中那有这个资源,所以:404呗
3.13、结语
手机扫一扫
移动阅读更方便
你可能感兴趣的文章