vue2.0+vue3.0资料(尚硅谷)(五)

简介: vue2.0+vue3.0资料(尚硅谷)

vue2.0+vue3.0资料(尚硅谷)(四)https://developer.aliyun.com/article/1470419

10、全局事件总线

10-1、可以实现任意组件间的通信(图解)

image.png

x组件需满足

1、所有的组件都能看见x组件

2、x能被调用到(on和off以及$emit)

10-2、全局事件总线(GlobalEventBus)

  1. 一种组件间通信的方式,适用于任意组件间通信
  2. 在main.js中安装全局事件总线:
    方法一、
const Demo = vue.extend({})
const d = new Demo()
Vue.prototype.x = d

方法二、(提倡这种方法)

  1. 使用事件总线:
  1. 接收数据:A组件想接收数据,则在A组件中给$bus绑定自定义事件,事件的回调留在A组件自身。
methods(){
  demo(data){......}
}
......
mounted() {
  this.$bus.$on('xxxx',this.demo)
}


  1. 提供数据:this.$bus.$emit('xxxx',数据)
  1. 最好在beforeDestroy钩子中,用$off去解绑当前组件所用到的事件。

10-3、TodoList事件总线

全局事件总线的本质是给组件绑定自定义事件,只不过这里的组件是this.$bus也就是Vue实例对象

11、消息订阅与发布pubsub

11-1、消息订阅与发布

image.png

一种组件间通信的方式,适用于任意组件间通信

11-2、使用方法

1、调用pubsub.js库命令,安装pubsub:npm i pubsub-js

2、在所用的地方引入库: import pubsub from 'pubsub-js'

  1. 接收数据:A组件想接收数据,则在A组件中订阅消息,订阅的回调留在A组件自身。
methods(){
  demo(data){......}
}
......
mounted() {
  this.pid = pubsub.subscribe('xxx',this.demo) //订阅消息
}


  1. 提供数据:pubsub.publish('xxx',数据)
  2. 最好在beforeDestroy钩子中,用PubSub.unsubscribe(this.pid)取消订阅。

11-3、TodoList案例pubsub

12、$nextTick(视图渲染完,操作DOM)

12-1、nextTick使用

  1. 语法:this.$nextTick(回调函数)
  2. 作用:在下一次 DOM 更新结束后执行其指定的回调。
  3. 什么时候用:当改变数据后,要基于更新后的新DOM进行某些操作时,要在nextTick所指定的回调函数中执行。

13、vue封装的过度和动画

13-1、Vue封装的过度与动画

  1. 作用:在插入、更新或移除 DOM元素时,在合适的时候给元素添加样式类名。
  2. 图示: image.png
  3. 写法:
    3-1、准备好样式:
- 元素进入的样式:
  1. v-enter:进入的起点
  2. v-enter-active:进入过程中
  3. v-enter-to:进入的终点
- 元素离开的样式:
  1. v-leave:离开的起点
  2. v-leave-active:离开过程中
  3. v-leave-to:离开的终点

3-2、使用包裹要过度元素,并配置name属性:

3-3、备注:若有多个元素需要过度,则需要使用:,且每个元素都要指定key值。
3-4、可以使用第三方动画库来实现动画效果

13-2、animate.css(开箱即用的动画库)

官网:  https://animate.style/

图片: image.png

//安装animate.css库
npm install animate.css
//引入样式库
import 'animate.css'
//存放库里面的样式属性(animate__animated animate__bounce),
//然后放置属性(enter-active-class)
//和效果动画(animate__swing)
<transition-group 
  appear
  name="animate__animated animate__bounce" 
  enter-active-class="animate__swing"
  leave-active-class="animate__backOutUp"
>
  <h1 v-show="!isShow" key="1">你好啊!</h1>
  <h1 v-show="isShow" key="2">你好!</h1>
</transition-group>

14、配置代理

14-1、用脚手架去解决Ajax跨域的问题

解压文件中的test_proxy_server.zip

image.png

在文件页面打开cmd 输入node server1,然后复制(http://localhost:5000/students)网址,打开浏览器,输入页面发现是Ajax发出的get请求,端口也显示出来了

image.png

在文件页面打开cmd 输入node server1,然后复制(http://localhost:5000/students)网址,打开浏览器,输入页面发现是Ajax发出的get请求,端口也显示出来了

image.png

image.png

image.png

14-2、常用的发送一个Ajax请求的方式有哪些:(4种)

  • xhr(不常用)   new XMLHttpRequest()
    常用apixhr.open()   、 xhr.send()等
  • jQuery(不常用,经常使用DOM操作)
    常用api getget、get  、  post
  • axios(promise风格)
  • vue-resource(不常用,在vue1.0流行)
  • fetch(promise风格,但会包装两次promise)
    最致密的是他IE中的兼容性极差

14-3、axios的使用与问题解决

安装axios

//axios的安装
npm i axios

image.png

引入axios

//引入axios
import axios from 'axios.js'

设置一个按钮

<button @click="getStudents">获取学生信息</button>

在methods中写请求

methods: {
      getStudents(){
        axios.get('http://localhost:5000/students').then(
          response => {
            console.log('请求成功了',response.data)
          },
          error => {
            console.log('请求失败了',error.message)
          }
        )
      },
}

发生跨域问题

image.png

解决跨域问题的方式:

1、cors

2、jsonp script src(只能解决get请求post无法解决)

3、使用代理服务器(类似于生活中的房屋中介)

开启代理服务器方式{    1、nginx    2、vue-cli }

image.png

14-4、用脚手架的方式配置一个代理服务器

14-4A、方式一
14-4A-1、配置方法

①在vue的脚手架官网搜索devServer.proxy(英文意思为开发中如何配置代理),②在vue.config.js中输入(这里的5000是你获取axios服务器的端口),③把methods中的axios请求的地址改成8080端口的(因为数据要发送到8080端口实现跨域)

devServer: {
    proxy: 'http://localhost:5000'
  }

image.png

//修改端口号5000,改成8080端口
axios.get('http://localhost:8080/students').then(
          response => {
            console.log('请求成功了',response.data)
          },
          error => {
            console.log('请求失败了',error.message)
          }
        )
      },
14-4A-2、工作方式:

若按照上述配置代理,当请求了前端不存在的资源时,那么该请求会转发给服务器 (优先匹配前端资源)

当你请求的内容代理服务器中原本就有则不会发送给5000的目标服务器public中有students,(即实现不了下面图片黄色箭头)

image.png

image.png

14-4A-3、方式一配置代理缺点

这种情况下只能配置一个单独的代理,并且不能灵活的控制走不走代理服务器。

14-4B、方式二
14-4B-1、配置方法

下图两个颜色为配置的两套代理(分别为红色和绿色,且红色是精简版),并且这里'/api'的意思是当你发送请求到代理服务器时,它会判断代理是否是 /api 形式如果是走代理,否则不走。target 为请求跳转的目标地址,pathRewrite:{'^/api':''}这里是请求后发给目标地址是把/api  替换成空字符串

image.png

此时请求完还得改axios跳转代理服务器的路径为

//原本
axios.get('http://localhost:8080/students')
//修改后添加了个/api
axios.get('http://localhost:8080/api/students')
/*
   changeOrigin设置为true时,服务器收到的请求头中的host为:localhost:5000
   changeOrigin设置为false时,服务器收到的请求头中的host为:localhost:8080
   changeOrigin默认值为true
*/
14-4B-2、配置优缺点:
  1. 优点:可以配置多个代理,且可以灵活的控制请求是否走代理。
  2. 缺点:配置略微繁琐,请求资源时必须加前缀。

14-5、github案例

image.png

1、先在index.html中引入bootstrap样式

2、main.js代码

//引入Vue
import Vue from 'vue'
//引入App
import App from './App.vue'
//关闭Vue的生产提示
Vue.config.productionTip = false
//创建vm
new Vue({
  el:'#app',
  render: h => h(App),
  beforeCreate() {
    Vue.prototype.$bus = this
  },
})

3、App.vue

<template>
  <div class="container">
    <Search/>
    <List/>
  </div>
</template>
<script>
  import Search from './components/Search'
  import List from './components/List'
  export default {
    name:'App',
    components:{Search,List}
  }
</script>

4、Search.vue

<template>
  <section class="jumbotron">
    <h3 class="jumbotron-heading">Search Github Users</h3>
    <div>
      <input type="text" placeholder="enter the name you search" v-model="keyWord"/>&nbsp;
      <button @click="searchUsers">Search</button>
    </div>
  </section>
</template>
<script>
  import axios from 'axios'
  export default {
    name:'Search',
    data() {
      return {
        keyWord:''
      }
    },
    methods: {
      searchUsers(){
        //请求前更新List的数据
        this.$bus.$emit('updateListData',{isLoading:true,errMsg:'',users:[],isFirst:false})
        axios.get(`https://api.github.com/search/users?q=${this.keyWord}`).then(
          response => {
            console.log('请求成功了')
            //请求成功后更新List的数据
            this.$bus.$emit('updateListData',{isLoading:false,errMsg:'',users:response.data.items})
          },
          error => {
            //请求后更新List的数据
            this.$bus.$emit('updateListData',{isLoading:false,errMsg:error.message,users:[]})
          }
        )
      }
    },
  }
</script>

5、List.vue

<template>
  <div class="row">
    <!-- 展示用户列表 -->
    <div v-show="info.users.length" class="card" v-for="user in info.users" :key="user.login">
      <a :href="user.html_url" target="_blank">
        <img :src="user.avatar_url" style='width: 100px'/>
      </a>
      <p class="card-text">{{user.login}}</p>
    </div>
    <!-- 展示欢迎词 -->
    <h1 v-show="info.isFirst">欢迎使用!</h1>
    <!-- 展示加载中 -->
    <h1 v-show="info.isLoading">加载中....</h1>
    <!-- 展示错误信息 -->
    <h1 v-show="info.errMsg">{{info.errMsg}}</h1>
  </div>
</template>
<script>
  export default {
    name:'List',
    data() {
      return {
        info:{
          isFirst:true,
          isLoading:false,
          errMsg:'',
          users:[]
        }
      }
    },
    mounted() {
      this.$bus.$on('updateListData',(dataObj)=>{
        this.info = {...this.info,...dataObj}
      })
    },
  }
</script>
<style scoped>
  .album {
    min-height: 50rem; /* Can be removed; just added for demo purposes */
    padding-top: 3rem;
    padding-bottom: 3rem;
    background-color: #f7f7f7;
  }
  .card {
    float: left;
    width: 33.333%;
    padding: .75rem;
    margin-bottom: 2rem;
    border: 1px solid #efefef;
    text-align: center;
  }
  .card > img {
    margin-bottom: .75rem;
    border-radius: 100px;
  }
  .card-text {
    font-size: 85%;
  }
</style>

效果图

image.png

15、vue-resource(不常用)

15-1、使用方法

安装vue-resource

npm i vue-resource

在main.js中引入vue-resource插件

import vueResource from 'vue-resource'

在main.js中使用插件

vue.use(vueResource)

在一个vue实例内使用this.$http代替axios

// 在一个Vue实例内使用$http
this.$http.get(`https://api.github.com/search/users?q=${this.keyWord}`).then(
  response => {
    console.log('请求成功了')
    //请求成功后更新List的数据
    this.$bus.$emit('updateListData',{isLoading:false,errMsg:'',users:response.data.items})
  },
  error => {
    //请求失败后更新List的数据
    this.$bus.$emit('updateListData',{isLoading:false,errMsg:error.message,users:[]})
  }
)

16、插槽

  1. 作用:让父组件可以向子组件指定位置插入html结构,也是一种组件间通信的方式,适用于 父组件 ===> 子组件
  2. 分类:默认插槽、具名插槽、作用域插槽
  3. 使用方式:
  1. 默认插槽:
父组件中:
        <Category>
           <div>html结构1</div>
        </Category>
子组件中:
        <template>
            <div>
               <!-- 定义插槽 -->
               <slot>插槽默认内容...</slot>
            </div>
        </template>


  1. 具名插槽:
父组件中:
        <Category>
            <template slot="center">
              <div>html结构1</div>
            </template>
            <template v-slot:footer>
               <div>html结构2</div>
            </template>
        </Category>
子组件中:
        <template>
            <div>
               <!-- 定义插槽 -->
               <slot name="center">插槽默认内容...</slot>
               <slot name="footer">插槽默认内容...</slot>
            </div>
        </template>


  1. 作用域插槽:
  1. 理解:数据在组件的自身,但根据数据生成的结构需要组件的使用者来决定。(games数据在Category组件中,但使用数据所遍历出来的结构由App组件决定)
  2. 具体编码:
父组件中:
    <Category>
      <template scope="scopeData">
        <!-- 生成的是ul列表 -->
        <ul>
          <li v-for="g in scopeData.games" :key="g">{{g}}</li>
        </ul>
      </template>
    </Category>
    <Category>
      <template slot-scope="scopeData">
        <!-- 生成的是h4标题 -->
        <h4 v-for="g in scopeData.games" :key="g">{{g}}</h4>
      </template>
    </Category>
子组件中:
        <template>
            <div>
                <slot :games="games"></slot>
            </div>
        </template>
    
        <script>
            export default {
                name:'Category',
                props:['title'],
                //数据在子组件自身
                data() {
                    return {
                        games:['红色警戒','穿越火线','劲舞团','超级玛丽']
                    }
                },
            }
        </script>


17、动态组件

17-1、动态组件的is

  • 动态组件就是几个组件放在一个挂载点下,然后根据父组件的某个变量来决定显示哪个,或者都不显示。
  • 在挂载点使用 component 标签,然后使用 is =“组件名”,它会自动去找匹配的组件名,如果有,则显示;

看例子:

<!-- html部分 -->
<div id="app">
    <component is="one"></component>
</div>
// js 部分
new Vue({
    el: '#app',
    components: {
        one: {template: '<div>我是线路一</div>'},
        two: {template: '<div>我是线路二</div>'},
        thr: {template: '<div>我是线路三</div>'}
    }
})

上面代码注册了三个组件,在 component 标签里有个属性 is,is=one,所以页面会渲染名字叫 one 的组件,显示结果如下:

我是线路一

如果给 is 属性绑定动态值,那么就可以实现组件的动态切换,例子如下:

<!-- html 部分 -->
<div id="app">
    <button v-for="item in tabs" @click="change = item.id">
      {{ item.text }}
    </button>
    <component :is="change"></component>
</div>
// js 部分
new Vue({
  el: '#app',
  data: {
    change: 'one' // 默认显示组件 one
    tabs: [
      {id: 'one', text: '线路一'},
        {id: 'two', text: '线路二'},
        {id: 'thr', text: '线路三'}
    ]
  },
  components: {
    one: {template: '<div>我是线路一</div>'},
    two: {template: '<div>我是线路二</div>'},
    thr: {template: '<div>我是线路三</div>'}
  }
})

上面代码用 v-bind 给属性 is 动态传递了值,实现了组件的动态切换,效果如下:

image.png

17-2、动态组件的keep-alive

在面试的时候,很多面试官再问vue的时候可能就会提一嘴,你知道keep-alive有什么作用吗?

keep-alive是vue内置的一个组件,而这个组件的作用就是能够缓存不活动的组件,我们能够知道,一般情况下,组件进行切换的时候,默认会进行销毁,如果有需求,某个组件切换后不进行销毁,而是保存之前的状态,那么就可以利用keep-alive来实现

我这里利用脚手架创建项目后会生成home和about两个组件,并且通过路由进行切换

home组件

<template>
  <div class="home">
    <input type="text">
  </div>
</template>
<script>
// @ is an alias to /src
import HelloWorld from '@/components/HelloWorld.vue'
export default {
  name: 'home',
  components: {
    HelloWorld
  }
}
</script>

我在home组件中写了一个input输入框

about组件

<template>
  <div class="about">
    <input type="text">
  </div>
</template>
<script>
export default {
  name:"about"
}
</script>

同样的about组件也放了一个输入框

image.png

当我们在home组件的输入框输入一些内容的时候,然后切换到about组件,在切换回home组件,我们会发现之前输入的内容被清空了,其实也容易理解,就是当切换到about组建的时候,home组件就被销毁了,输入框的值自然被清空了

当切换到about组件的时候home组件的destroyed就触发了,所以home组件被销毁了

那么此时我们就可以利用keep-alive组件进行包裹router-view组件,将不活动的组件缓存起来

App组件

<template>
  <div id="app">
    <div id="nav">
      <router-link to="/">Home</router-link> |
      <router-link to="/about">About</router-link>
    </div>
    <keep-alive>
      <router-view />
    </keep-alive>
    
  </div>
</template>

写完之后会发现当切换到about组件时,home组件中的destroyed并没有触发,并且home组件的值也保存了下来

image.png

但是这样也肯定不好,我们会发现,about组件的值也被缓存了,就是所有的路由组件都被缓存了,严重浪费性能,而且也不符合需求,我们现在只想缓存home组件

在keep-alive上有两个属性

字符串或正则表达式。只有匹配的组件会被缓存。

  • include 值为字符串或者正则表达式匹配的组件name会被缓存。
  • exclude 值为字符串或正则表达式匹配的组件name不会被缓存。

首先利用include实现,匹配到组件中定义的name,将进行缓存

<keep-alive include="home">
   <router-view />
</keep-alive>

image.png

我们会发现home已经被缓存了,但是about没有被缓存

而exclude就是排除了,这个就不在演示了,很简单,除了这个我们还可以利用路由中的meta属性来控制

{
      path: '/',
      name: 'home',
      meta:{
        keepAlive:true
      },
      component: Home
    }

将home的路由规则钟的meta添加keepAlive属性为true,也就是当前路由组件要进行缓存

keep-alive代码可以结合v-if进行包裹,如果meta中的keepAlive为true进行缓存,否侧不进行缓存,这样可以更灵活一些

<keep-alive>
      <router-view v-if="$route.meta.keepAlive" />
</keep-alive>
<router-view v-if="!$route.meta.keepAlive" />

这样组件的缓存是实现了,但是还是会有一些问题,就是因为组件被缓存,并没有被销毁,所以组件在切换的时候也就不会被重新创建,自然也就不会调用created等生命周期函数,所以此时要使用activated与deactivated来获取当前组件是否处于活动状态

我在home组件里面写入了activated与deactivated生命周期函数

activated(){
    console.log("哎呀看见我了")
    console.log("----------activated--------")
  },
  deactivated(){
    console.log("讨厌!!你又走了")
    console.log("----------deactivated--------")
  }

image.png

通过上面的gif图相信已经看得很清楚了,此时keep-Alive也就差不多了


vue2.0+vue3.0资料(尚硅谷)(六)https://developer.aliyun.com/article/1470430

目录
相关文章
|
30天前
|
缓存 JavaScript 前端开发
vue2.0+vue3.0资料(尚硅谷)(一)
vue2.0+vue3.0资料(尚硅谷)
63 0
|
6月前
|
JavaScript 前端开发 API
尚硅谷Vue3 笔记总结及代码-1
尚硅谷Vue3 笔记总结及代码-1
201 0
|
30天前
|
JavaScript 搜索推荐 程序员
vue2.0+vue3.0资料(尚硅谷)(三)
vue2.0+vue3.0资料(尚硅谷)
33 0
|
30天前
|
存储 JavaScript API
vue2.0+vue3.0资料(尚硅谷)(四)
vue2.0+vue3.0资料(尚硅谷)
86 0
|
30天前
|
JavaScript 前端开发 安全
vue2.0+vue3.0资料(尚硅谷)(二)
vue2.0+vue3.0资料(尚硅谷)
80 0
|
30天前
|
存储 JavaScript 前端开发
vue2.0+vue3.0资料(尚硅谷)(六)
vue2.0+vue3.0资料(尚硅谷)
61 0
|
30天前
|
JavaScript 前端开发 API
vue2.0+vue3.0资料(尚硅谷)(七)
vue2.0+vue3.0资料(尚硅谷)
75 0
|
8月前
|
缓存 JavaScript 网络架构
[Vue]学习笔记目录 【Vue2与Vue3完结】 (尚硅谷Vue2.0+Vue3.0全套教程丨vuejs从入门到精通)
[Vue]学习笔记目录 【Vue2与Vue3完结】 (尚硅谷Vue2.0+Vue3.0全套教程丨vuejs从入门到精通)
|
2天前
|
JavaScript 前端开发 API
Vue 2 vs Vue 3:开发者之争,究竟选择哪个版本?
Vue 2 vs Vue 3:开发者之争,究竟选择哪个版本?
8 1
|
2月前
|
存储 JavaScript
总结vue3 的一些知识点:​Vue3 起步
Vue 进阶系列教程将在本号持续发布,一起查漏补缺学个痛快!若您有遇到其它相关问题,非常欢迎在评论中留言讨论,达到帮助更多人的目的。若感本文对您有所帮助请点个赞吧!