【前端-VUE】Vue3组件组成部分及组件通信(详解)

一、父子间通信

1.父传子:

2.子传父:

3.什么是prop

Prop定义:组件上注册的一些自定义属性

Prop作用:向子组件传递数据

特点

  • 可以传递任意数量的prop
  • 可以传递任意类型的prop

3.1 props校验

思考:组件的prop可以乱传么?

不可以

作用:为组件的prop指定验证要求,不符合要求,控制台就会有错误提示——>帮助开发者,快速发现错误

语法

①类型校验

②非空校验

③默认值

④自定义校验

props:{

校验的属性名: 类型 //Number String Boolean Array Object…

},

3.2更详细的props校验

props:{
    校验的属性名:{
        type:类型, // Number String Boolean …
        required: true, // 是否必填
        default: 默认值, // 默认值
        validator (value){
            // 自定义校验逻辑
            return 是否通过校验
        }
    }
},

4.prop & data、单向数据流

共同点:都可以给组件提供数据。

区别

  • data的数据是自己的——> 随便改
  • prop的数据是外部的 ——> 不能直接改,要遵循 单向数据流

总结:

谁的数据谁负责

1.data:自己的数据,随便改(谁的数据谁负责)

2.prop传过来的数据(外部的数据)不能直接改

3.单向数据流:父组件的prop更新,会单向向下流动,影响到子组件

4.1综合案例

4.2核心代码

App.vue

<template>
  <!-- 主体区域 -->
  <section id="app">
    <TodoHeader @add="handleAdd"></TodoHeader>
    <TodoMain @del="handleDel" :list="list"></TodoMain>
    <TodoFooter @clear="handleClear" :list="list"></TodoFooter>
  </section>
  <router-view></router-view>
</template>
<script>
import TodoHeader from './components/TodoHeader.vue';
import TodoMain from './components/TodoMain.vue';
import TodoFooter from './components/TodoFooter.vue';
// 渲染功能:
// 1.提供数据 ——> 提供在公共的父组件 App.Vue
// 2.通过父传子,将数据传递给TodoMain
// 3.利用v-for渲染
// 添加功能
// 1.收集表单数据 v-model
// 2.监听事件(回车+点击 都要进行添加)
// 3.子传父,将任务名称传递给父组件App.vue
// 4.进行添加 unshift(自己的数据自己负责)
// 删除功能:
// 1.监听事件(监听删除的点击)携带 id
// 2.子传父,将删除的id传递给父组件App.vue
// 3.进行删除 filter(自己的数据自己负责)
// 底部合计:父传子传list ——> 渲染
// 清空功能:子传父 通知到父组件 ——> 父组件进行清空操作
// 持久化存储:watch深度监视list的变化 ——> 往本地存储 ——> 一进入页面优先读取本地
export default {
  data () {
    return {
      list: JSON.parse(localStorage.getItem('list')) || [
        { id: 1, name: '打篮球' },
        { id: 2, name: '看电影' },
        { id: 3, name: '逛街' },
      ]
    }
  },
  methods: {
    handleAdd (todoName) {
      this.list.unshift({
        id: +new Date(),
        name: todoName
      })
    },
    handleDel (id) {
      this.list = this.list.filter(item => item.id !== id)
    },
    handleClear () {
      this.list = []
    }
  },
  watch: {
    list: {
      deep: true,
      handler (newValue) {
        localStorage.setItem('list', JSON.stringify(newValue))
      }
    }
  },
  components: {
    TodoHeader,
    TodoMain,
    TodoFooter
  }
}
</script>

TodoMain.vue

<template>
  <section class="main">
    <ul class="todo-list">
      <li v-for="(item, index) in list" class="todo">
        <div class="view">
          <span class="index">{{ index + 1 }}</span><label>{{ item.name }}</label>
          <button @click="handleDel(item.id)" class="destroy"></button>
        </div>
      </li>
    </ul>
  </section>
</template>
<script>
export default {
  props: {
    list: Array
  },
  methods: {
    handleDel (id) {
      this.$emit('del', id)
    }
  }
}
</script>

Todoheader.vue

<template>
  <header class="header">
    <h1>小黑笔记本</h1>
    <input @keyup.enter="handleAdd" v-model="todoName" placeholder="请输入任务" class="new-todo" />
    <button @click="handleAdd" class="add">添加任务</button>
  </header>
</template>
<script>
export default {
  data () {
    return {
      todoName: ''
    }
  },
  methods: {
    handleAdd () {
      // console.log(this.todoName)
      if (this.todoName.trim() === '') {
        alert('任务名称不能为空')
        return
      }
      this.$emit('add', this.todoName)
      this.todoName = ''
    }
  }
}
</script>

TodoFooter.vue

<template>
  <!-- 统计和清空 -->
  <footer class="footer">
    <!-- 统计 -->
    <span class="todo-count">合 计:<strong>{{ list.length }}</strong></span>
    <!-- 清空 -->
    <button @click="clear" class="clear-completed">
      清空任务
    </button>
  </footer>
</template>
<script>
export default {
  props: {
    list: Array
  },
  methods: {
    clear () {
      this.$emit('clear')
    }
  }
}
</script>

4.3总结

核心步骤:

①拆分基础组件

新建组件——> 拆分存放结构 ——> 导入注册使用

②渲染待办事项

提供数据(公共父组件)——> 父传子传递list ——> v-for渲染

③添加任务

收集数据 v-model ——>监听事件 ——> 子传父传递任务 ——> 父组件unshift

④删除任务

监听删除携带id ——> 子传父传递id ——> 父组件filter删除

⑤底部合计 和 清空功能

底部合计:父传子传递list ——> 合计展示

清空功能:监听点击 ——>子传父通知父组件 ——> 父组件清空

⑥持久化存储

watch监视数据变化,持久化到本地

二、非父子通信

1.非父子通信- event bus 事件总线

作用:非组件之间,进行简易消息传递。(复杂场景——>Vuex)

1.创建一个能够访问到的事件总栈(空Vue实例)——>utils/EventBus.js

improt Vue form 'vue'
const Bus = new Vue()
export default Bus

2.A组件(接收方),监听Bus实例的事件

created (){
	Bus.$on('sendMsg',(msg)=>{
		this.msg = msg
	})
}

3.B组件(发送方),触发Bus实例的事件

Bus.$emit('sendMsg','这是一个消息')

代码:

App.vue

<template>
  <div>
    <BaseA></BaseA>
    <BaseB></BaseB>
    <BaseC></BaseC>
  </div>
</template>
<script>
import BaseA from './components/BaseA.vue'
import BaseB from './components/BaseB.vue'
import BaseC from './components/BaseC.vue'
export default {
  components: {
    BaseA,
    BaseB,
    BaseC
  }
}
</script>

 BaseA.vue

<template>
  <div class="baseA">
    我是A组件(接收方)
    <p>{{ msg }}</p>
  </div>
</template>
<script>
import Bus from '../utils/EventBus'
export default {
  created () {
    // 2.在A组件(接收方),进行监听(订阅消息)
    Bus.$on('sendMsg', (msg) => {
      this.msg = msg
    })
  },
  data () {
    return {
      msg: ''
    }
  }
}
</script>
<style>
.baseA {
  width: 200px;
  height: 150px;
  padding: 10px;
  margin-top: 10px;
  border: 3px solid #000;
  border-radius: 5px;
  font-size: 20px;
}
</style>

 BaseB.vue

<template>
  <div class="baseB">
    我是B组件(发布方)
    <button @click="clickSend">发布通知</button>
  </div>
</template>
<script>
import Bus from '../utils/EventBus'
export default {
  methods: {
    clickSend () {
      // 3.B组件(发件方)触发事件的方式传递参数(发布消息)
      Bus.$emit('sendMsg', '今日晴天,适合郊游')
    }
  }
}
</script>

BaseC.vue

<template>
  <div class="baseC">
    我是C组件(接收方)
    <p>{{ msg }}</p>
  </div>
</template>
<script>
import Bus from '../utils/EventBus'
export default {
  created () {
    // 2.在C组件(接收方),进行监听(订阅消息)
    Bus.$on('sendMsg', (msg) => {
      this.msg = msg
    })
  },
  data () {
    return {
      msg: ''
    }
  }
}
</script>
<style>
.baseA {
  width: 200px;
  height: 150px;
  padding: 10px;
  margin-top: 10px;
  border: 3px solid #000;
  border-radius: 5px;
  font-size: 20px;
}
</style>

EventBus.js

// 1.创建一个都能访问到的事件总线(空的Vue实例)
import { createApp } from 'vue';
 
const Bus = createApp({}); // 创建一个空的Vue实例
export default Bus

2.非父子通信(拓展)-provide & inject

provide & inject 作用:跨层级共享数据

1.父组件provide提供数据

export default {
	provide (){
		return {
			//普通类型【非响应式】
			color: this.color,
			// 复杂类型【响应式】
			userInfo: this.userInfo,
		}
	}
}

2./孙组件inject取值使用

export default {
	inject: ['color','userInfo'],
	created(){
		console.log(this.color,this.userInfo)
	}
}

代码:

App.vue

<template>
  <div class="app">
    <span>我是App组件</span>
    <button @click="change">修改数据</button>
    <SonA></SonA>
    <SonB></SonB>
  </div>
</template>
<script>
import SonA from './components/SonA.vue'
import SonB from './components/SonB.vue'
export default {
  provide () {
    return {
      color: this.color,
      userInfo: this.userInfo
    }
  },
  data () {
    return {
      color: 'pink', // 简单类型(非响应式)
      userInfo: { // 复杂类型(响应式) - 推荐
        name: 'zs',
        age: 18
      }
    }
  },
  methods: {
    change () {
      this.color = 'green'
      this.userInfo.name = 'ls'
    }
  },
  components: {
    SonA,
    SonB
  }
}
</script>

SonA.vue

<template>
  <div class="SonA">
    我是SonA组件
    {{ color }} - {{ userInfo.name }} - {{ userInfo.age }}
  </div>
  <GrandSon></GrandSon>
</template>
<script>
import GrandSon from './GrandSon.vue';
export default {
  inject: ['color', 'userInfo'],
  created () {
    console.log(this.color, this.userInfo)
  },
  components: {
    GrandSon
  }
}
</script>

SonB.vue

<template>
  <div class="SonB">
    我是SonB组件
    {{ color }} - {{ userInfo.name }} - {{ userInfo.age }}
  </div>
</template>
<script>
export default {
  inject: ['color', 'userInfo'],
  created () {
    console.log(this.color, this.userInfo)
  }
}
</script>

GrandSon.vue

<template>
  <div class="GrandSon">
    我是GrandSon组件
    {{ color }} - {{ userInfo.name }} - {{ userInfo.age }}
  </div>
</template>
<script>
export default {
  inject: ['color', 'userInfo'],
  created () {
    console.log(this.color, this.userInfo)
  }
}
</script>

 

三、v-model原理

1.原理:

v-model本质上是一个语法糖。例如应用在输入框上,就是value属性和input事件的合写。

作用:提供数据的双向绑定

①数据变,视图跟着变 :value

②页面输入改变,数据会自动改变 @input

注意:$event用于模板中,获取时间中的形参

<template>
  <div class="app">
    <input v-model="msg" type="text">
	// 等价于
    <input :value="msg" @input="msg = $event.target.value" type="text">
  </div>
</template>

2.表单类组件封装&v-model简化代码

2.1表单类组件 封装

①父传子:数据 应该是父组件props传递过来的,v-model拆解 绑定数据

②子传父:监听输入,子传父传值给父组件修改

本质:实现了子组件 和 父组件数据 的双向绑定

2.2 父组件v-model 简化代码,实现 子组件 和父组件数据 双向绑定

①子组件中:props通过value接收,事件触发input

②父组件中:v-model给组件直接绑数据 (:value + @input)

代码:

App.vue

<template>
  <div class="app">
    <!-- <BaseSelect :cityId="selectId" @changeId="selectId = $event"></BaseSelect> -->
    <BaseSelect v-model="selectId"></BaseSelect>
  </div>
</template>
<script>
import BaseSelect from './components/BaseSelect.vue'
export default {
  data () {
    return {
      selectId: '104'
    }
  },
  components: {
    BaseSelect
  }
}
</script>

BaseSelect.vue

<template>
  <div>
    <!-- <select :value="cityId" @change="handleChange"> -->
    <select :value="value" @change="handleChange">
      <option value="101">北京</option>
      <option value="102">上海</option>
      <option value="103">武汉</option>
      <option value="104">深圳</option>
      <option value="105">广州</option>
    </select>
  </div>
</template>
<script>
export default {
  props: {
    // cityId: String
    value: String
  },
  methods: {
    handleChange (e) {
      // console.log(e.target.value)
      // this.$emit('changeId', e.target.value)
      this.$emit('input', e.target.value)
    }
  }
}
</script>

四、sync修饰符

  • 作用:可以实现 子组件 与 父组件数据 的双向绑定,简化代码
  • 特点:prop属性名,可以自定义,非固定为value
  • 场景:封装弹窗类的基础组件,visible属性 true显示 false隐藏
  • 本质:就是 :属性名 和 @update:属性名 合写

代码:

App.vue

<template>
  <div class="app">
    <button class="logout" @click="isShow = true">退出按钮</button>
    <!-- :visible.sync => :visible + @update:visible -->
    <BaseDialog :visible.sync="isShow"></BaseDialog>
  </div>
</template>
<script>
import BaseDialog from './components/BaseDialog.vue';
export default {
  data () {
    return {
      isShow: false
    }
  },
  components: {
    BaseDialog
  }
}
</script>

BaseDialog.vue

<template>
  <div v-show="visible">
    <div>
      <div>
        <h3>温馨提示:</h3>
        <button class="close" @click="close"></button>
      </div>
      <div>
        <p>你确定要退出本系统吗?</p>
      </div>
      <div>
        <button @click="close">确认</button>
        <button @click="close">取消</button>
      </div>
    </div>
  </div>
</template>
<script>
export default {
  props: {
    visible: Boolean
  },
  methods: {
    close () {
      this.$emit('update:visible', false)
    }
  }
}
</script>

五、ref和$refs

作用利用ref$refs可以用于获取dom(文档对象模型中代表HTML元素的JavaScript对象)元素,或组件实例

特点:查找范围——>当前组件内(更精准稳定)

获取dom

1.目标标签-添加ref属性

<div ref="chartRef">我是渲染表的容器</div>

2.恰当时机,通过this.$refs.xxx,获取目标标签

mounted(){
console.log(this.$refs.chartRef)
},

代码:

App.vue

<template>
  <div class="app">
    <BaseChart></BaseChart>
  </div>
</template>
<script>
import BaseChart from './components/BaseChart.vue'
export default {
  data () {
    return {
    }
  },
  components: {
    BaseChart
  }
}
</script>

BaseChart.vue

<template>
  <div ref="mychart" id="base-chart-box" style="width: 600px; height: 400px"></div>
</template>
<script>
// 装包:yarn add echarts
import * as echarts from 'echarts';
export default {
  mounted () {
    // const myChart = echarts.init(document.querySelector('.base-chart-box'))
    const myChart = echarts.init(this.$refs.mychart)
    // 指定图表的配置项和数据
    const option = {
      title: { text: 'My Chart' },
      xAxis: { data: ["衬衫", "羊毛衫", "裤子", "高跟鞋", "袜子"] },
      yAxis: {},
      series: [{ type: 'bar', data: [5, 20, 36, 10, 10] }],
    }
    // 使用刚指定的配置项和数据显示图表。
    myChart.setOption(option)
  }
}
</script>

效果图:

代码:

App.vue

<template>
  <div class="app">
    <BaseForm ref="baseForm"></BaseForm>
    <button @click="handleGet">获取数据</button>
    <button @click="handleReset">重置数据</button>
  </div>
</template>
<script>
import BaseForm from './components/BaseForm.vue'
export default {
  data () {
    return {
    }
  },
  methods: {
    handleGet () {
      console.log(this.$refs.baseForm.getValues())
    },
    handleReset () {
      this.$refs.baseForm.resetValues()
    }
  },
  components: {
    BaseForm
  }
}
</script>

BaseForm.vue

<template>
  <form action="">
    账号:<input type="text" v-model="account" />
    密码:<input type="password" v-model="password" />
  </form>
</template>
<script>
export default {
  data () {
    return {
      account: '',
      password: ''
    }
  },
  methods: {
    // 方法1:收集表单数据,返回对象
    getValues () {
      return {
        account: this.account,
        password: this.password
      }
    },
    // 方法2:重置表单
    resetValues () {
      this.account = ''
      this.password = ''
    }
  }
}
</script>

六、Vue异步更新、$nextTick

需求:编辑标题,编辑框自动聚焦

1.点击编辑,显示编辑框

2.让编辑框立刻获取焦点

this.isShowEdit = true // 显示输入框
this.$refs.inp.focus() // 获取焦点

问题:“显示之后”,立刻获取焦点是不能成功的!

原因:vue是异步更新DOM(提升性能)

$nextTick:DOM更细后,才会触发执行此方法里的函数体

语法:this.$nextTick(函数体)

this.$nextTick(()=>{
this.$refs.inp.focus()
})

代码:

App.vue

<template>
  <div class="app">
    <div v-if="isShowEdit">
      <input ref="inp" v-model="editValue" type="text">
      <button>确认</button>
    </div>
    <!-- 默认状态 -->
    <div v-else>
      <span>{{ title }}</span>
      <button @click="handleEdit">编辑</button>
    </div>
  </div>
</template>
<script>
export default {
  data () {
    return {
      title: '大标题',
      editValue: '',
      isShowEdit: false
    }
  },
  methods: {
    handleEdit () {
      // 1.显示输入框 (异步dom更新,获取不到数据)
      this.isShowEdit = true
      // 2.让 输入框 获取焦点($nextTick等dom更新完,立刻执行准备的函数体)
      this.$nextTick(() => {
        this.$refs.inp.focus()
      })
    }
  }
}
</script>

总结:

1.Vue是异步更新DOM的

2.想要在DOM更新完成之后做某件事,可以使用$nextTick

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/359873.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【脑电信号处理与特征提取】P5-彭薇薇:脑电信号的预处理及数据分析要点

彭薇薇&#xff1a;脑电信号的预处理及数据分析要点 脑电 脑电是神经活动的测量方法&#xff0c;在不同位置测量有不同的方法。比如大脑皮层表面测量的是ECoG&#xff0c;在头皮测量的是EEG。除了EEG是无损的&#xff0c;其他都是有损的。 脑电信号采集系统 下面是完整的…

seata Adjusted frame length exceeds 8388608: 539959368,nacos+mysql+seata部署

问题&#xff1a;docker 部署 seata 后出现异常 seata Adjusted frame length exceeds 8388608: 539959368 CSDN上找了一圈都解决不了。github又半天访问不上。后来终于访问上了&#xff0c;发现这是一个很离谱的问题。。。 原因&#xff1a;访问错了端口 seata默认分两个端口…

字符串中的单词反转【leetcode】

本题选自leetcode图解算法数据结构一书 你在与一位习惯从右往左阅读的朋友发消息&#xff0c;他发出的文字顺序都与正常相反但单词内容正确&#xff0c;为了和他顺利交流你决定写一个转换程序&#xff0c;把他所发的消息 message 转换为正常语序。 注意&#xff1a;输入字符串…

充电桩项目实战:搞定多数据源!

你好&#xff0c;我是田哥 最近&#xff0c;我在对充电桩项目进行微服务升级中&#xff0c;既然是项目升级&#xff0c;难免会遇到各种各样的问题。比如&#xff1a;分布式事务问题、多数据源问题、分布式锁问题等。 项目技术栈&#xff1a; SpringSpring BootSpring Cloud Ali…

Redis常见数据类型[上]

目录 前言&#xff1a; 基本全局命令 KEYS EXISTS DEL EXPIRE TTL TYPE 数据结构和内部编码 内部编码&#xff1a; 单线程架构 引出单线程模型&#xff1a; 为什么单线程还这么快&#xff1f; String字符串 字符串数据类型&#xff1a; 常见命令&#xff1a; S…

第十四篇【传奇开心果系列】BeeWare的Toga开发移动应用示例:Toga实现页面切换

传奇开心果系列博文 系列博文目录BeeWare的Toga开发移动应用示例系列博文目录前言一、Toga页面跳转和切换方式方法介绍二、使用TabView来实现页面切换三、使用页面堆栈管理器(Page Stack Manager)来实现页面切换四、使用网格布局(Grid Layout)和可见性控制来实现页面之间的…

防御保护--NAT策略

目录 NAT策略 NAT类型 server-map表 P2P --- peer to peer 网络类型 ​编辑 目标NAT--服务器映射 双向NAT ​编辑 多出口NAT NAT策略 静态NAT --- 一对一 动态NAT --- 多对多 NAPT --- 一对多的NAPT --- easy ip --- 多对多NAPT 服务器映射 源NAT--基于源IP地址进行转…

算法:分界线

一、算法描述 电视剧《分界线》里面有一个片段&#xff0c;男主为了向警察透露案件细节&#xff0c;且不暴露自己&#xff0c;于是将报刊上的字 剪切下来&#xff0c;剪拼成匿名信。 现在有一名举报人&#xff0c;希望借鉴这种手段&#xff0c;使用英文报刊完成举报操作。 但为…

如何从视频中提取高清图片?可以这样截取

如何从视频中提取高清图片&#xff1f;从视频中提取高清图片可以方便我们制作各种用途所需的素材&#xff0c;如海报、社交媒体配图等。此外&#xff0c;高清图片的细节和色彩也更丰富&#xff0c;可以更好地满足我们的视觉需求。从视频中提取高清图片是一项需要技巧的任务&…

leetcode 27.移除元素(python版)

需求 给你一个数组 nums 和一个值 val&#xff0c;你需要 原地 移除所有数值等于 val 的元素&#xff0c;并返回移除后数组的新长度。 不要使用额外的数组空间&#xff0c;你必须仅使用 O(1) 额外空间并 原地 修改输入数组。 元素的顺序可以改变。你不需要考虑数组中超出新长度…

代码随想录 Leetcode617.合并二叉树

题目&#xff1a; 代码(首刷看解析 2024年1月31日&#xff09;&#xff1a; class Solution { public:TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2) {if (!root1) return root2;if (!root2) return root1;root1->val root2->val;root1->left mergeTree…

计算机网络_1.2因特网概述

1.2因特网概述 一、网络、互联网与因特网的区别与联系1、网络2、互联网3、因特网4、 互联网与因特网辨析 二、因特网介绍1、因特网发展的三个阶段2、因特网简介&#xff08;1&#xff09;因特网服务提供者&#xff08;ISP&#xff09;&#xff08;2&#xff09;因特网已经发展成…

数字孪生智慧能源电力Web3D可视化云平台合集

前言 能源电力的经济发展是中国式现代化的强大动力&#xff0c;是经济社会发展的必要生产要素&#xff0c;电力成本变化直接关系到工业生产、交通运输、农业生产、居民生活等各个方面&#xff0c;合理、经济的能源成本能够促进社会用能服务水平提升、支撑区域产业发展&#xf…

监测Tomcat项目宕机重启脚本(Linux)

1.准备好写好的脚本 #!/bin/sh # 获取tomcat的PID TOMCAT_PID$(ps -ef | grep tomcat | grep -v tomcatMonitor |grep -v grep | awk {print $2}) # tomcat的启动文件位置 START_TOMCAT/mnt/tomcat/bin/startup.sh # 需要监测的一个GET请求地址 MONITOR_URLhttp://localhost:…

Spring Cloud中@RefreshScope实现动态刷新的原理

在现代微服务架构中&#xff0c;Spring Cloud已经成为了一种流行的选择&#xff0c;它提供了许多用于构建和部署微服务的工具和库。其中&#xff0c;动态刷新配置是Spring Cloud中一个非常有用的特性&#xff0c;它允许我们在不重启服务的情况下更新配置。这个特性是通过Refres…

Java入门高频考查基础知识8(腾讯18问1.5万字参考答案)

刷题专栏&#xff1a;http://t.csdnimg.cn/gvB6r Java 是一种广泛使用的面向对象编程语言&#xff0c;在软件开发领域有着重要的地位。Java 提供了丰富的库和强大的特性&#xff0c;适用于多种应用场景&#xff0c;包括企业应用、移动应用、嵌入式系统等。 以下是几个面试技巧&…

c#鼠标绘制

有用的没用的&#xff0c;用的上的用不上的&#xff0c;能写的不能写的&#xff0c;反正想起来就写了&#xff0c;比如这篇&#xff0c;好像一般也没什么用&#xff0c;emmm&#xff0c;或许&#xff0c;做录制软件的时候可以用一下。 顾名思义&#xff0c;本篇主要就是来实现将…

Linux上搭建mqtt开发环境及服务器部署(MosquittoEMQX)

&#x1f449;&#x1f449;&#x1f449;关于Mosquitto代码编写及EMQX的使用&#xff0c;由此入 一、安装编译Mosquitto 使用Mosquitto编写程序连接MQTT服务器&#xff0c;并收发数据1-安装所需依赖 用于在Linux系统上进行SSL/TLS加密通信的开发。它提供了一组用于加密和解密…

dvwa靶场xss储存型

xss储存型 xxs储存型lowmessage框插入恶意代码name栏插入恶意代码 medium绕过方法 high xxs储存型 攻击者事先将恶意代码上传或储存到漏洞服务器中&#xff0c;只要受害者浏览包含此恶意代码的页面就会执行恶意代码。产生层面:后端漏洞特征:持久性的、前端执行、储存在后端数据…

vue前端页面时间显示问题解决方法

解决方法&#xff0c; <template slot-scope"scope"><span>{{ parseTime(scope.row.boxClosingOnlineTime, {y}-{m}-{d} {h}:{i}:{s}) }}</span> </template> 刷新页面&#xff1a; 此外&#xff0c;使用JsonFormat(pattern "yyyy-M…