【Vue】生命周期+组件间五大通信+ajax异步通信AIOS

1.生命周期

在这里插入图片描述

1)初始化显示
beforeCreate() created() beforeMount() mounted() //这些方法只执行一次
2) 更新状态: this.xxx = value
beforeUpdate() updated() //可执行多次
3) 销毁 vue实例:vm.$destory()
beforeDestory() destoryed() //只执行一次

常用的生命周期方法
created()/mounted(): 发送ajax请求, 启动定时器等异步任务
beforeDestory(): 做收尾工作, 如: 清除定时器

2.组件间通信

除路由组件外,数据定义在哪个组件,更新数据的行为(方法)就应该定义在哪个组件

2.1 props

父子组件间通信的基本方式

<!--父组件:App.vue->
<TodoList :items="items" :del="del"/>
//子组件TodoList.vue
      props:{
    
      // 声明接收标签属性 会成为当前组件对象的属性
          items:Array,
          del:Function
      }

缺点:
隔层组件间传递: 必须逐层传递(麻烦)
兄弟组件间: 必须借助父组件(麻烦)

2.2 自定义事件

父子组件的通信方式

<!--父组件:App.vue->
<TodoHeader @add="add"/>   <!--父组件中绑定监听-->
//子组件TodoHeader.vue
      methods:{
    
    
        addItem() {
    
    
          const name = this.name.trim();  //注意需要this
          if (!name) {
    
    
            alert("need input!");
            return;
          }
          const Item = {
    
    state:false,name};
          this.$emit('add',Item); //子组件中触发事件
          this.name = "";
        }
      }

缺点:不适合隔层组件和兄弟组件间的通信

2.3 pubsub

(消息订阅与发布)适合于任何关系的组件间通信

//TodoList的父组件App.vue
<TodoList :items="items"/>
。。。
import PubSub from 'pubsub-js'
。。。
mounted(){
    
     //执行异步代码
        PubSub.subscribe('del', (msg, index) => {
    
     //订阅消息,类似绑定事件监听  这里的msg参数没啥用但必须要有
          this.del(index) //此处的this为当前vm组件对象
        });

// 回调函数中的this是当前的,若改成 => 函数则没有this 故 =>函数中的this为引用外部的

//TodoList的子组件(即App.vue的孙组件)TodoItem.vue
          delItem(){
    
    
            const index = this.index;
            if (window.confirm(`确认删除${
      
      this.item.name}么?`)) {
    
    
              // this.del(index);
              PubSub.publish("del", index); //发布消息,类似于触发事件
            }
          }

2.4 slot

通信是带数据的页面标签 注意: 标签是在父组件中解析 即若用到的相关属性计算属性,都需在父组件

<!--父组件:App.vue-->
      <TodoFooter>
        <span slot="size">已完成{
    
    {
    
    completeSize}} / 全部{
    
    {
    
    items.length}}</span>
      </TodoFooter>
<!--子组件:TodoFoot.vue-->
    <span>
      <slot name="size"></slot> <!--变量槽占位-->
     <!-- 相当于<span>已完成{
    
    {
    
    completeSize}} / 全部{
    
    {
    
    todos.length}}</span>-->
    </span>

2.5 路由组件

多组件共享状态(数据的管理),组件间的关系也没有限制,功能比pubsub强大, 更适用于vue项目
//别的路由组件需用props接收为自身属性再使用,类似组件间props方式通信

3 AIOS

//Main.vue
<template>
  <h2 v-if="firstView">输入用户名搜索</h2>
  <h2 v-else-if="loading">loading。。。</h2>
  <h2 v-else-if="errorMsg">{
    
    {
    
    errorMsg}}</h2>
  <div v-else class="row">
    <div class="card" v-for="(user,index) in users" :key="index">
      <a :href="user.url" target="_blank">
        <img :src="user.avatar_url" style='width: 100px'/>
      </a>
      <p class="card-text">{
    
    {
    
    user.name}}</p>
    </div>
  </div>
</template>
。。。
  import PubSub from "pubsub-js"
  import axios from "axios"
。。。
mounted() {
    
    
          PubSub.subscribe("search",(msg,searchName)=>{
    
      // 订阅消息(search)
            const url = `https://api.github.com/search/users?q=${
      
      searchName}`;
            this.firstView = false;
            this.loading = true;
            this.users = [];
            this.errorMsg = "";
            axios.get(url).then(response=>{
    
         //访问成功
              const result = response.data; // 得到返回结果数据
              const users = result.items.map(item => (   //这个括号 ( 很重要,标识返回的是对象
                {
    
    
                  url: item.html_url,
                  avatar_url: item.avatar_url,
                  name: item.login
                }
              ));
              // let users = result.items.map(item => {
    
    
              //   let json = {};
              //   json.url = item.html_url;
              //   json.avatar_url = item.avatar_url;
              //   json.name = item.login;
              //   // console.log(json);
              //   return json;
              // });
              this.loading = false;
              this.users = users;
            }).catch(error=>{
    
      //访问失败
              this.loading = false;
              this.errorMsg = "请求失败";
            })
          })
      }
//Seaarch.vue
     methods:{
    
    
        doSearch() {
    
    
          const searchName = this.searchName.trim();
          if (searchName) {
    
    
            PubSub.publish("search", searchName)  // 发布一个search的消息
          }
        }
      }

附录

   watch:{
    
    
        items:{
    
    
          deep:true,  // 深度监视
          // handler: function (value) {
    
    
          //   console.log(JSON.stringify(value));
          //   // window.localStorage.setItem("Items_key", JSON.stringify(value)); //将数据(json)保存到localStorage
          //   storageUtil.saveItems(value);
          // }
          handler: storageUtil.saveItems  //handler的值应该是一个函数, 且函数应该要有一个形参(接收items最新的值)
        }
      }
    }
 add(item) {
    
    
   this.items.unshift(item)  //从前面添加   从后面添加则push
 },
 del(index){
    
    
   this.items.splice(index, 1);
 },
 delCompleted() {
    
    
   this.items = this.items.filter(item=>!item.state); //过滤器,改变总项数  而map是不改变总项数,对每一项的信息进行筛选保留
 },
 selAll(isCheck) {
    
     //全选/全不选
   this.items.forEach(item => item.state=isCheck) //迭代器
 }
completedSize() {
    
    
  const items = this.items;
  return items.reduce((preTotal,item)=>preTotal+(item.state?1:0),0) //累加器
}

猜你喜欢

转载自blog.csdn.net/qq_40265247/article/details/108436130