监听器,组件,组件之间的传值,跨事件传递(事件总栈),生命周期钩子函数,promise的拓展(就是原生Ajax的封装和调用)

123 阅读1分钟

监听器

基本使用

<template>
  <div>
    msg
    <input type="text" v-model="msg">
    <br>
    user.name
    <input type="text" v-model="user.name">
    user.age
    <input type="text" v-model="user.age">
    <br>
    <input type="text" v-model="num1">
    总数: {{num2}}
  </div>
</template>

<script>
export default {
  data() {
    return {
      msg: '',
      user: {
        name: 'tom',
        age: 13
      },
      num1: 2,
      num2: 0
    }
  },
  watch: {
    // 以键值对的形式指定 被监听字段: 触发后回调函数
    msg(newVal, oldVal) {
      console.log(newVal, oldVal);
    },
    // user(newVal, oldVal) {
    //   console.log(newVal, oldVal);
    // }
    // 复杂类型无法直接监听, 需要多加额外配置
    user: {
      // deep 可以监听到复杂数据内部的改变
      deep: true,
      handler(newVal, oldVal) {
        console.log(newVal, oldVal);
      }
    },
    num1: {
      // immediate 可以再页面进来时马上触发一次当前监听回调
      immediate: true,
      handler (newVal) {
        this.num2 += newVal
      }
    }
  }
}
</script>

<style>

</style>

品牌案例数据持久化(缓存)

就是监听器再项目中的使用

image-20220516095216176.png

组件

创建和使用

image-20220516105153673.png

image-20220516105331697.png

image-20220516105401835.png

局部创建

<template>
  <div>
    <ip />   //当作一个标签使用即可
    <ip />
    <ip />
    <ip />
    <ip />
    <ip />
    <ip />
    <ip />
    <ip />
  </div>
</template>

<script>
//局部注册的演示
//语法:import  组件名 from  组件路径
//Vue.component("组件名",组件对象)
//注意点:组件名最好不要用html标签命名,建议两个单词以上的方式来命名
import ip from "@/components/ip.vue";
export default {
  components: {
    ip,
  },
</script>

<style scoped lang="less">
</style>

全局创建

	// 全局注册
//语法:import  组件名 from  组件路径
//Vue.component("组件名",组件对象)
//注意点:组件名最好不要用html标签命名,建议两个单词以上的方式来命名
import ip from "@/components/ip.vue";
Vue.component("ip", ip);

style 中的 scoped 使用

原理就是添加一个自定义属性,限定样式是全局还是局部

image-20220516115527806.png

组件传值

父传子

image-20220516150142079.png

image-20220516150155227.png

父传子配合循环

image-20220516155004026.png

子传父

image-20220516162145832.png

image-20220516162226720.png

image-20220516162252071.png

父子组件数据传递小结

  • 无论是父传子还是子传父都是三步
  • 一方主动传递, 另一方表明愿意接受, 最后用起来
  • 父传子
    • 父组件以属性的形式传入数据
    • 子组件 props 定义需要接受的数据
    • 直接当成 data 使用即可
  • 子传父
    • 子组件主动触发自定义事件 this.$emit('自定义事件名')
    • 父组件 监听 v-on 就是 @自定义事件名
    • 父组件给个对应的处理函数

跨组件传递(事件总线)

就是两个子组件想互相传递内容,就要用主组件当作一条桥,联通两个人的信息传递,因为子组件是不同直接互相通信的,这种用法会比较麻烦,所以用的不多

image-20220517160754625.png

组件A

<template>
  <!-- 两个组件的关系非常的复杂,通过父子组件通讯是非常麻烦的。这时候可以使用通用的组件通讯方案:事件总线(event-bus)
 -->
  <div class="box" @click="sendMsgToB">组件A</div>
</template>

<script>
// 我希望这里点击一下, 组件b就会有反应
// 引入事件总线
import EventBus from "../EventBus";
export default {
  methods: {
    sendMsgToB() {
      EventBus.$emit("atob", 678);
    },
  },
};
</script>

<style scoped>
.box {
  width: 100px;
  height: 100px;
  border: 3px solid salmon;
}
</style>

组件B

<template>
  <div class="box">组件B</div>
</template>

<script>
import EventBus from "../EventBus";
export default {
  // mounted()意思等同于window.onload()
  mounted() {
    console.log("B组件挂载");
    EventBus.$on("atob", (res) => {
      console.log("接收到数据");
      console.log(res);
    });
  },
};
</script>

<style scoped>
.box {
  width: 100px;
  height: 100px;
  border: 3px solid saddlebrown;
}
</style>

渲染到页面的vue文件

	<template>
  <div>
    <ComponentA />
    <ComponentB />
  </div>
</template>

<script>
import ComponentA from "@/components/A.vue";
import ComponentB from "@/components/B.vue";
export default {
  components: {
    ComponentA,
    ComponentB,
  },
};
</script>

<style>
</style>

生命周期钩子函数

四大阶段八个函数(八个函数就是区分前后比如初始化前和后,但是比较常用都是下列几个)

  • 初始化 created

  • 挂载 mounted

  • 更新 updated

  • 销毁 destroyed

  • <template>
      <div class="box">我的盒子</div>
    </template>
    
    <script>
    // 初始化
    //   初始化前
    //   beforeCreate() {}, //生命周期 - 创建之前 (常用)
    // created() {},//生命周期 - 创建完成(可以访问当前this实例)
    //   初始化后
    // 挂载
    //   挂载前
    //   beforeMount() {}, //生命周期 - 挂载之前 (常用)
    // mounted() {},//生命周期 - 挂载完成(可以访问DOM元素) (常用)
    //   挂载后
    // 更新
    // beforeUpdate() {}, //生命周期 - 更新之前 (极少用)
    // updated() {}, //生命周期 - 更新之后 (不能修改数据 否则会死循环 递归 不常用)
    //   更新后
    //   destroyed() {}, //生命周期 - 销毁完成 (用来销毁遗留的定时器 延时器事件 等等)
    // 销毁
    // beforeDestroy() {}, //生命周期 - 销毁之前 (不常用)
    // activated() {}, //如果页面有keep-alive缓存功能,这个函数会触发(不常用)
    //   销毁后
    let timeId = null;
    export default {
      created() {
        timeId = setInterval(() => {
          console.log(new Date());
        }, 1000);
      },
      destroyed() {
        console.log("销毁");
        clearInterval(timeId);
      },
    };
    </script>
    
    <style scoped>
    .box {
      width: 100px;
      height: 100px;
      border: 3px solid salmon;
    }
    </style>
    

promise的拓展

就是原生Ajax的封装
原生封装
<template>
  <div></div>
</template>

<script>
export default function (options) {
  // const xhr = new XMLHttpRequest()
  // xhr.open(options.method, options.url)
  // xhr.send()
  // xhr.onload = function() {
  //   // xhr.responseText 其实是获取到的结果
  //   // console.log(JSON.parse(xhr.responseText));
  //   options.success(JSON.parse(xhr.responseText))
  // }
  return new Promise((resolve) => {
    const xhr = new XMLHttpRequest();
    xhr.open(options.method, options.url);
    xhr.send();
    xhr.onload = function () {
      // xhr.responseText 其实是获取到的结果
      // console.log(JSON.parse(xhr.responseText));
      // options.success(JSON.parse(xhr.responseText))
      resolve(JSON.parse(xhr.responseText));
    };
  });
}

// 只要返回一个Promise 对象, 里面的回调函数就会自动带上一个 resolve 放行方法
// 可以替换, 之前要自己写的回调函数
</script>

<style scoped lang="less">
</style>

调用
<template>
  <div>
    <button @click="sendRequest">发请求</button>
  </div>
</template>

<script>
import request from "@/utils/request";
export default {
  methods: {
    sendRequest() {
      request({
        method: "get",
        url: "https://cnodejs.org/api/v1/topics",
        // success(res) {
        //   console.log('回调函数');
        //   console.log(res);
        // }
          //一般提promise都是下面这个的回调
      }).then((res) => {
        console.log("promise形式封装");
        console.log(res);
      });
    },
  },
};
</script>

<style>
</style>