IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> Vue06 全局事件总线 TodoList-事件总线 消息订阅与发布 TodoList-pubsub TodoList-编辑$nextTick 动画效果 github案例 -> 正文阅读

[游戏开发]Vue06 全局事件总线 TodoList-事件总线 消息订阅与发布 TodoList-pubsub TodoList-编辑$nextTick 动画效果 github案例

全局事件总线

(没有新的api)利用自定义事件,实现兄弟组件之间的通信。

复习VueComponet

?复习重要的内置关系

?所以,在Vue的原型对象上添加属性。

?需要有$on(绑定事件,触发事件时的回调)、$emit(触发事件)。

$on、$emit、$off都在Vue的原型对象上。vm和vc都能看见。

利用beforeCreate钩子: 此时数据还没解析,数据代理、监测没开始。

main.js:

/*
const Demo = Vue.extend({});//Demo:一个Vuecomponent构造函数
const d = new Demo();//new调用,生成vc实例
Vue.prototype.x = d;//x是一个vc实例*/



//创建vue实例对象
new Vue({
  
  //将App组件放入容器中
  render: h => h(App),
  beforeCreate() {
    //安装全局事件总线
    Vue.prototype.$bus = this;//$bus是一个vm实例,$bus是它的名字,$bus在Vue原型对象上,vc能够看见,没有必要new一个vc
  },


}).$mount('#app')

?school.vue


<template>
  <div class="school">
    <h2>schoolname:{{ name }}</h2>
    <h2>schoolage{{ schoolage }}</h2>
    
  </div>
</template>


<script>


export default {
  name: "SchoolInfo",
  
  data() {
    return {
      name: "atguigu",
      schoolage: 20,
      stuname:'???'
    };
  },
  methods:{
    
  },
  mounted(){
    //console.log('school',this.$bus);
    //给$bus绑定hello事件、事件回调在school上
    this.$bus.$on('hello',(data)=>{
      //写成箭头函数,使this是当前组件
      this.stuname = data;
    });
  },
  beforeDestroy() {
    //销毁$bus上的hello事件
    this.$bus.$off('hello')
  },
 
};
</script>


student.vue

<template>
  <div class="student">
    <h1>{{ msg }}</h1>
    <h2>stuname:{{ name }}</h2>
    <h2>stuage:{{ stuage }}</h2>
    <button @click='sendStudentName'>把学生名给school组件</button>
  </div>
</template>


<script>

export default {
  name: "StudentInfo",
  data() {
    return {
      msg: "尚硅谷666", 
      name: "jack",
      stuage: 18,
    };
  },
  methods: {
    sendStudentName(){
      //触发$bus的hello事件
      this.$bus.$emit('hello',this.stuname);
    }
  },

 
};
</script>



TodoList事件总线

让app能够直接和item通信。之前是把app上的函数一直传递下去,item接收,触发函数。

现在app收数据,item传id。给app绑定事件,事件回调。item传入id触发事件。

此时勾选、删除,触发事件的是$bus,vm

App.vue

mounted() {
    this.$bus.$on('checkTodo',this.checkTodo)
    this.$bus.$on('deleteTodo',this.deleteTodo)
  },
  beforeDestroy() {
    this.$bus.$off('checkTodo');
    this.$bus.$off('deleteTodo');
  },

item.vue


<template>
  
     <li>
      <label>
        <input type="checkbox" :checked="todo.done" @change='handleCheck(todo.id)'/>
        <!--eslint-disable-next-line vue/no-mutating-props-->
        <!--<input type="checkbox" v-model="todo.done">-->
        <span>{{todo.title}}</span>
      </label>
      <button class="btn btn-danger" @click="handleDelete(todo.id)">删除</button>
    </li>
 
  
</template>


<script>

export default {
  name: "OptionItem",

  data() {
    return {
       
    };
  },
  //接收数据todo对象
  props:["todo"],
  methods: {
    handleCheck(id){
      //通知app组件将id对应的todo对象done取反
      //this.checkTodo(id);
      this.$bus.$emit("checkTodo",id);
    },
    handleDelete(id){
      if(confirm('确定要删除吗?')){
        //通知app组件将id对应的todo对象删除
        //this.deleteTodo(id);
        this.$bus.$emit("deleteTodo",id);
        
      }     
    },
  },
    
  
};
</script>

消息订阅与发布

pubsub.js库 :

回调函数为普通函数时,this为undefined,所以需要写成箭头函数,使this为当前vc。

或者把回调定义在外部

?

student.vue

 methods: {
    sendStudentName(){
      pubsub.publish('hello',this.name)
    }
  },

?school.vue

mounted(){
    /*//console.log('school',this.$bus);
    //给$bus绑定hello事件、事件回调在school上
    this.$bus.$on('hello',(data)=>{
      //写成箭头函数,使this是当前组件
      this.stuname = data;
    });*/


    //订阅一个消息
   this.pubId = pubsub.subscribe('hello',(msgName,data)=>{
      console.log('有人发布了hello消息,hello消息的回调执行了',msgName,data)
    })
    
  },

  beforeDestroy() {
    //取消订阅
    pubsub.unsubsribe(this.pubId)
  },
 

?TodoList pubsub

app和item之间的通信用pubsub:

item.vue

methods: {
    handleCheck(id){
      //通知app组件将id对应的todo对象done取反
      //this.checkTodo(id);
      this.$bus.$emit("checkTodo",id);
    },
    handleDelete(id){
      if(confirm('确定要删除吗?')){
        //通知app组件将id对应的todo对象删除
        //this.deleteTodo(id);
        /*this.$bus.$emit("deleteTodo",id);*/
        pubsub.publish('deleteTodo',id);
        
      }     
    },
  },

app.vue

//删除对象
    deleteTodo(_,id){
      this.todos = this.todos.filter( todo => todo.id !== id);
    },


 mounted() {
    this.$bus.$on('checkTodo',this.checkTodo)
    /*this.$bus.$on('deleteTodo',this.deleteTodo)*/
    this.pubId = pubsub.subscribe('deleteTodo',this.deleteTodo);

  },
  beforeDestroy() {
    this.$bus.$off('checkTodo');
    /*this.$bus.$off('deleteTodo');*/
    pubsub.unsubscribe(this.pubId);
  },

TodoList 编辑

添加响应式的属性:

?给item添加按钮,绑定事件回调handleEdit。handleEdit(todo)中判断有没有isEdit这个属性,有就修改(出现input框,span消失),没有就添加todo.isEdit = true属性。

然后给input框绑定失去焦点事件,修改todo.isEdit = false;,然后触发update事件并传递数据到app,this.$bus.$emit('updateTodo',todo.id,e.target.value),app触发事件回调updateTodo,修改todo的title属性。

需要点击编辑,input框自动获取焦点:

此时执行完46行,并没有立刻重新解析模板,而是执行51行,然后再解析模板。

执行51行的时候,因为通过v-show控制(display:none 隐藏了),input框并没有出现在页面上,隐藏了调focus不能获取焦点。

?

?app.vue


<template>
  <div id="root">
    <div class="todo-container">
      <div class="todo-wrap">

        <header-item 
          @addTodo='addTodo'>
        </header-item>

        <option-list 
          :todos='todos' 
          >
        </option-list>

        <footer-item 
          :todos='todos' 
          @checkAllTodo='checkAllTodo' 
          @clearAllTodo='clearAllTodo'>

        </footer-item>

      </div>
    </div>
  </div>
</template>


<script>
import pubsub from 'pubsub-js';
import HeaderItem from "./components/HeaderItem.vue";
import FooterItem from "./components/FooterItem.vue";
import OptionList from "./components/OptionList.vue";

export default {
  name: "App",
  data() {
    return {
      //从本地中获取数据
      //初始为null  把null传给了footer,foot计算length,null没有length
      todos:JSON.parse(localStorage.getItem('todos')) || [],
    };
  },
  components: {
    // eslint-disable-next-line vue/no-unused-components
    HeaderItem,
    // eslint-disable-next-line vue/no-unused-components
    FooterItem,
    // eslint-disable-next-line vue/no-unused-components
    OptionList,
  },
  methods: {
    //添加对象
    //把addTodo事件传给了header
    addTodo(obj){
      this.todos.unshift(obj);
    },
    //修改勾选状态todo
    checkTodo(id){
      this.todos.forEach((todo)=>{
        if(todo.id === id){
          todo.done = !todo.done;
        }
      });
    },
    //删除对象
    deleteTodo(_,id){
      this.todos = this.todos.filter( todo => todo.id !== id);
    },
    //全选or取消全选
    //接收参数
    checkAllTodo(done){
      this.todos.forEach((todo)=>{
          //遍历,使每一个todo的done都为传入的done值
          todo.done = done;
      });
    },
    //清除已完成的todo
    clearAllTodo(){
       this.todos = this.todos.filter((todo)=>{
         return !todo.done
       })
       //console.log('app',this.todos.length)
    },
    //修改title
    updateTodo(id,title){
      this.todos.forEach((todo)=>{
        if(todo.id === id){
          todo.title = title;
        }
      });
    }



  },
  watch:{
    //监视todos的变化,一变化就存入本地
    todos:{
      deep:true,
      handler(value){
        localStorage.setItem('todos',JSON.stringify(value))
      }
    }
  },
  mounted() {
    this.$bus.$on('checkTodo',this.checkTodo)
    /*this.$bus.$on('deleteTodo',this.deleteTodo)*/
    this.pubId = pubsub.subscribe('deleteTodo',this.deleteTodo);
    //绑定修改事件
    this.$bus.$on('updateTodo',this.updateTodo);
    //APP的mounted下写个初始化就解决了
    this.todos.forEach((todo)=>{todo.isEdit=false})

  },
  beforeDestroy() {
    this.$bus.$off('checkTodo');
    this.$bus.$off('updateTodo');
    /*this.$bus.$off('deleteTodo');*/
    pubsub.unsubscribe(this.pubId);
  },
};
</script>

item.vue


<template>
  
     <li>
      <label>
        <input type="checkbox" :checked="todo.done" @change='handleCheck(todo.id)'/>
        <!--eslint-disable-next-line vue/no-mutating-props-->
        <!--<input type="checkbox" v-model="todo.done">-->
        <span v-show='!todo.isEdit'>{{todo.title}}</span>
        <input 
          v-show='todo.isEdit' 
          type="text" 
          :value='todo.title' 
          @blur='handleBlur(todo,$event)'
          ref='inputTitle'>

      </label>
      <button class="btn btn-danger" @click="handleDelete(todo.id)">删除</button>
      <button v-show='!todo.isEdit' class="btn btn-edit" @click='handleEdit(todo)'>编辑</button>
    </li>
 
  
</template>


<script>
import pubsub from 'pubsub-js';
export default {
  name: "OptionItem",

  data() {
    return {
       
    };
  },
  //接收数据todo对象
  props:["todo"],
  methods: {
    handleCheck(id){
      //通知app组件将id对应的todo对象done取反
      //this.checkTodo(id);
      this.$bus.$emit("checkTodo",id);
    },
    handleDelete(id){
      if(confirm('确定要删除吗?')){
        //通知app组件将id对应的todo对象删除
        //this.deleteTodo(id);
        /*this.$bus.$emit("deleteTodo",id);*/
        pubsub.publish('deleteTodo',id);
        
      }     
    },
    //编辑
    handleEdit(todo){
      //判断有没有isEdit这个属性
      //用'isEdit' in todo也可以,只不过要保证原型对象里没有isEdit属性
      if(Object.prototype.hasOwnProperty.call(todo, 'isEdit')){
        todo.isEdit = true;
      }else{
        //当点击编辑的时候添加属性
      this.$set(todo,'isEdit',true)
      }

      /*
      setTimeout(()=>{
         this.$refs.inputTitle.focus()
      },0)*/

      //$nextTick的回调会在dom节点更新之后再执行
      this.$nextTick(function(){
        console.log(this)//vc
        this.$refs.inputTitle.focus()
      })

      /*
       this.$nextTick(()=>{
         console.log(this)//vc
       })*/

    },

    //失去焦点完成编辑,完成修改数据
    handleBlur(todo,e){
      todo.isEdit = false;
      //事件总线,触发update事件。
      if(!e.target.value.trim()) return alert('输入不能为空')
      {
        this.$bus.$emit('updateTodo',todo.id,e.target.value)
      }
   

    }
  },
    
  
};
</script>



css3复习

?

?

?

实现反弹

动画效果

transition标签:

<template>
    <div>
        <button @click="change">显示/隐藏</button>
        <transition name='hello' :appear="true">
            <h1 v-show="isShow" class="go">Hello!</h1>
        </transition>
        

    </div>

</template>



<script>
export default {
    name:'AnTest',
    data(){
        return{
            isShow:true,
        }
    },
    methods:{
        change(){
            this.isShow = !this.isShow
        }
    }
    
}
</script>


<style>
    h1{
        background-color: yellow;
    }

    .hello-enter-active{
        animation: atguigu 1s;
    }

    .hello-leave-active{
        animation: atguigu 1s reverse;
    }

    @keyframes atguigu{
        from{
            transform: translateX(-100%);
        }
        to{
            transform: translateX(0px);
        }
    }
</style>

过度效果

<template>
    <div>
        <button @click="change">显示/隐藏</button>
        <transition name='hello' :appear="true">
            <h1 v-show="isShow" class="go">Hello!</h1>
        </transition>
        

    </div>

</template>



<script>
export default {
    name:'AnTest',
    data(){
        return{
            isShow:true,
        }
    },
    methods:{
        change(){
            this.isShow = !this.isShow
        }
    }
    
}
</script>


<style>
    h1{
        background-color: yellow;
    }
    
    .hello-enter-active,.hello-leave-active{
        transition: 1s linear;
    }

    /* 进入的起点*/
    .hello-enter,.hello-leave{
        transform: translateX(-100%);
    }

    /* 进入的终点*/
    .hello-enter-to,.hello-leave-to{
        transform: translateX(0);
    }


     /* 离开的起点*/
    /*.hello-leave{
        transform: translateX(-100%);
    }*/

    /* 离开的终点*/
    /*.hello-leave-to{
        transform: translateX(0);
    }*/

   
</style>

配置代理_方式一

原生ajax:

?JQuery(主要用来操作dom)(对xhr封装):

?axios(对xhr封装):

fetch:(兼容性)

此时跨域了。同源策略:1.协议名字,2.主机名字,3.端口号。

请求发送了,服务器接收了,并交给了浏览器,但浏览器没有呈现出来。

利用8080代理服务器解决跨域问题。

?把请求发给8080代理服务器,然后转发给5000.

当请求的资源8080代理服务器本身就有,就不会转发给5000.

public文件夹下的文件,8080都有。

配置代理_方式二

第一种只能配置一个代理,并且不能灵活的控制走不走代理。

?

github案例静态

<template>
  <div id="app">
    <div class="container">
      <SearchOption><SearchOption/>
      <SearchList><SearchList/>
    </div>
  </div>
</template>


<script>
//import axios from "axios";
import SearchOption from "./components/SearchOption.vue";
import SearchList from "./components/SearchList.vue";

export default {
  name: "App",
  methods: {},
  comments: {
    SearchOption,
    SearchList,
  },
};
</script>

github案例列表

SearchOption获取数据,需要传递给List。(全局事件总线)

List获取数据后需要处理数据,v-for遍历? key为login(唯一标识)。

SearchOption发请求:

methods: {
    search(){
      //ES6模板字符串
      axios.get(`https://api.github.com/search/users?q=${this.keyword}`).then(
        response =>{
          //请求成功并获取了数据
          console.log('请求成功了');
          //触发事件
          this.$bus.$emit('getUsers',response.data.items)
        },
        error =>{
          console.log('请求失败了',error.message);
        }
      )
    }
  },

List处理数据:

<template>
  <div class="row">
    <div class="card" v-for='user in 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>
  </div>
</template>

<script>
export default {
  name: "SearchList",
  data(){
    return{
      users:[]
    }
  },
  mounted() {
    //绑定事件和事件回调函数
    this.$bus.$on('getUsers',(users)=>{
      console.log("List获取到了数据",users)
      this.users = users;
    })
  },
};
</script>

  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章      下一篇文章      查看所有文章
加:2022-03-15 22:58:26  更:2022-03-15 23:02:15 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年1日历 -2025/1/16 18:05:02-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码