前端通信那些事儿

前端程序员进阶到大神必备的7本前端书籍 前端易学易懂,属于一个人傻钱多速度来的行业,随着移动互联网的日益兴起,it行业对于前端的需求也在不断的提高,那么从前端小白修炼成为前端大神的这个过程之中,一些必备的枕边书也是必不可少的。 一、《CSS那些事儿》 内容介绍:《CSS那些事儿》是2009年电子工业出版社出版的图书,作者是林小志。该书通过对CSS技巧实例进行讲解,浅入深地分析了CSS相关知识。 通过页面中的文字、图片、表格、表单等... 阅读详情

在这里插入图片描述

在近两年996模式下的近乎疯狂的迭代需求打磨平台的锻炼下,积累了一些前端通信方面的一些实践经验,在这里做一个汇总。一来对自己做一个总结,二来也是给小伙伴们提供一些吸收。

由于作者使用的是vue.js,所有主要对vue.js的组件通信做总结。而且是.vue单文件组件的形式。用react.js的小伙伴不要失望,文章中有很多通用的通信知识点:比如DOM通过自定义事件通信,基于nodejs的EventEmitter通信,多Window通信 / Tab间通信等等。

这里只讨论前端内部的通信,不涉及前后端通信。前后端之间的http通信,mqtt通信,跨域,文件上传等等等等,讲不完的。以后会单独开一篇文章做梳理。

DOM通信

  • DOM通过自定义事件通信

vue组件间通信

  • 父子组件通信
    • props v-bind(缩写为:) 父->子
    • props, watch 父->子
    • $emit v-on(缩写为@) 子->父
    • v-bind:foo.sync 父<–>子
    • p a r e n t , parent, parent,refs 实例式伪通信
  • 跨组件通信
    • 共用事件对象式通信 event bus
    • 全局状态树式通信 vuex
    • 路由式通信 vue-router
    • 依赖注入式通信 provide, inject
  • 基于nodejs的EventEmitter通信

多Window通信 / Tab间通信

  • window.open与window.opener (基于当前window生成子window,实现父->子window的通信)
  • localStorage/sessionStorage与window.onstorage (监听onstorage的event对象key的变化,实现tab间通信)
  • BroadCast Channel (创建一个单独通信通道,tab在这个通道内进行通信)

Web worker通信

  • Main thread与Web worker间通信
  • 多tab共享Shared worker,tab与worker间的通信

DOM通信

DOM通过自定义事件通信

触发事件 <-->增加了自定义事件DOM

DOM通过自定义事件通信的意思是:可以为DOM增加一些自定义的事件,然后在某些情况下去触发这些事件,然后事件做出响应。

说简单一些就是:增加了自定义事件的DOM,是一个鲜活的听话的人,发送对应的命令给它,它就会去做事。

创建自定义事件(Creating custom events)
var event = new Event('build');

// Listen for the event.
elem.addEventListener('build', function (e) { /* ... */ }, false);

// Dispatch the event.
elem.dispatchEvent(event);
增加自定义数据(Adding custom data - CustomEvent())

CustomEvent()可以通过detail属性为事件增加数据。

var event = new CustomEvent('build', { detail: "foo" });
elem.addEventListener('build', function (e) { console.log(e.detail) });

关于应用 DOM通过自定义事件通信 的实战,可以参考我的这篇博客:如何为DOM创建自定义事件?。

vue组件间通信

组件间通信实在是一个老生常谈的话题,因为真的是每天都会遇到。

  • 父子组件通信
    • props v-bind(缩写为:) 父->子
    • props, watch 父->子
    • $emit v-on(缩写为@) 子->父
    • v-bind:foo.sync 父<–>子
    • p a r e n t , parent, parent,refs 实例式伪通信
  • 跨组件通信
    • 共用事件对象式通信 event bus
    • 全局状态树式通信 vuex
    • 路由式通信 vue-router
    • 依赖注入式通信 provide, inject
  • 基于nodejs的EventEmitter通信

父子组件通信

props v-bind(缩写为:) 父->子

父组件的数据单向传递到子组件。

// 父组件 Parent.vue
<template>
  <Child :foo="hello child"></Child>
</template>

<script>
import Child from './child';
export default {
  name: 'parent',
  components: { Child },
};
</script>
// 子组件 Child.vue
<template>
  <div>{{foo}}</div>
</template>

<script>
export default {
  name: 'child',
  props: {
    foo: {
      type: String,
      default: '',
    },
  },
};
</script>
props, watch 父->子

子组件监听的父组件属性如果不仅仅做类似{{foo}}这样的模板渲染,可以使用watch做监听。

父组件中的传入子组件props的变量发生变化时,可以通过watch监听对应的prop属性,做出对应的操作。
这也算是一种父子组件通信的方式。

// 父组件
<Child :foo="parent.foo" @child-msg-emit="childMsgOn"></Child>
// 子组件
watch: {
    foo(val) {
      console.log("foo更新为:", val);
    }
},
$emit v-on(缩写为@) 子->父

子组件通过$emit向父组件传递数据。
父组件通过v-on接收数据。
二者需要约定好相同的事件名。

// 父组件 Parent.vue
<template>
  <Child :foo="hello child" @child-msg-emit="childMsgOn"></Child>
</template>

<script>
import Child from './child';
export default {
  name: 'parent',
  components: { Child },
  methods: {
    childMsgOn(msg) {
      console.log(msg); //'hello parent'
    },
  },
};
</script>
// Child.vue
<template>
  <div>{{foo}}</div>
</template>

<script>
export default {
  name: 'child',
  props: {
    foo: {
      type: String,
      default: '',
    },
  },
  mounted() {
    this.$emit('child-msg-emit', 'hello parent');
  },
};
</script>
v-bind:foo.sync 父<–>子

除了用$emit和v-on,父组件传入子组件的prop可以双向绑定吗?可以用.sync。

可能有小伙伴对这个.sync修饰符不熟悉,但它其实非常有用。
sync是一个语法糖,简化v-bind和v-on为v-bind.sync和this.$emit(‘update:xxx’)。为我们提供了一种子组件快捷更新父组件数据的方式。

首先将传递给foo的值放在一个变量中。

...
  <Child :foo="parent.foo" @child-msg-emit="childMsgOn"></Child>
  data() {
     return {
         parent: { foo: "hello child" }
     }
  },
  methods: {
    childMsgOn(msg) {
      console.log(msg); //'hello parent'
      this.parent.foo = msg;
    },
  }
...
<Child
  v-bind:foo="parent.foo"
  v-on:child-msg-emit="childMsgOn"
></Child>

在vue中,父组件向子组件传递的props是无法被子组件直接通过this.props.foo = newFoo去修改的。
除非我们在组件this.$emit("child-msg-emit", newFoo),然后在父组件使用v-on做事件监听child-msg-emit事件。若是想要可读性更好,可以在$emit的name上改为update:foo,然后v-on:update:foo。

有没有一种更加简洁的写法呢???
那就是我们这里的.sync操作符。
可以简写为:

<Child v-bind:foo.sync="parent.foo"></Child>

子组件触发:this.$emit("update:foo", newFoo);

然后在子组件通过this.$emit("update:foo", newFoo);去触发,注意这里的事件名必须是update:xxx的格式,因为在vue的源码中,使用.sync修饰符的属性,会自定生成一个v-on:update:xxx的监听。

<Child v-bind:foo="parent.foo" v-on:update:foo="childMsgOn"></Child>

如果想从源码层面理解v-bind:foo.sync,可以参考我的这篇文章:如何理解vue中的v-bind?。

p a r e n t , parent, parent,refs 实例式伪通信

父->子 props, watch
子->父 $emit, v-on
父<–>子 v-bind:xxx.sync

除上述3种方法外,我们还可以直接通过获得父子组件的实例去调用它们的方法,是一种伪通信。

子组件通过 p a r e n t 可 以 拿 到 父 组 件 的 v u e 实 例 , 从 而 调 用 属 性 和 方 法 。 父 组 件 可 以 通 过 parent可以拿到父组件的vue实例,从而调用属性和方法。 父组件可以通过 parent可以拿到父组件的vue实例,从而调用属性和方法。父组件可以通过refs拿到子组件的vue实例,从而调用属性和方法。

// parent.vue
<Child ref="child" :foo="parent.foo" @child-msg-emit="childMsgOn"></Child>
  methods: {
    parentMethod() {
      console.log("I am a parent method");
    },
    $refCall() {
        this.$refs.child.childMethod(); // I am a child method
    }
  }
// child.vue
  methods: {
    childMethod() {
      console.log("I am a child method");
    },
    $parentCall() {
        this.$parent.parentMethod(); // I am a parent method
    }
  }

跨组件通信

想想一种情况,有这样一个组件树。
红色组件想和黄色组件进行通信。
image

红色组件可以通过逐级向上$emit,然后通过props逐级向下watch,最后更新黄色组件。

显然这是一种很愚蠢的方法,在vue中有多种方式去做更加快速的跨组件通信,比如event bus 跨组件通信,vue-router 区分新增与编辑,vuex 全局状态树和provide, inject 跨组件通信。

共用事件对象式通信 event bus

image

名字听起来高大上,但其实使用起来很简单。
下面演示一个注册为plugin的用法。

// plugins/bus/bus.js
import Vue from 'vue';
const bus = new Vue();
export default bus;
// plugins/bus/index.js
import bus from './bus';
export default {
  install(Vue) {
    Vue.prototype.$bus = (() => bus)();
  },
};
// main.js
import bus from 'src/plugins/bus';
Vue.use(bus);

注册为全局plugin之后,就可以通过this.$bus使用我们的event bus了。

红色组件发送事件:

this.$bus.$emit('yellowUpdate', 'hello yellow.');

黄色组件接收事件:

this.$bus.$on('yellowUpdate',(payload)=>{
    console.log(payload); // hello yellow
});
  • 优点:最快捷的跨组件通信方式,支持双工通信(通信专业的我告诉大家,双工可以理解为双向通信),上手简单。
  • 缺点:事件在组件间穿透,数据传递层级关系不明显,出现bug难以快速定位
全局状态树式通信 vuex

image

vuex是vue生态很重要的一个附加plugin,进行前端的状态管理。
除前端状态管理之外,因为这是一个全局的状态树,状态在所有组件都是共享的,因此vuex其实也是一个跨组件通信的方式。

定义store

import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

const state = {
  userInfo: {
      id: '',
      name: '',
      age: '',
  },
};

const mutations = {
  UPDATE_USER(state, info) {
    state.userInfo = info;
  },
};

export default new Vuex.Store({
  state,
  mutations
});

红色组件:更新状态树的state:mapMutation

 <script>
import { mapMutations } from 'vuex';
export default {
  name: 'set-state',
  methods: {
        ...mapMutations(['UPDATE_USER']),
  },
  created(){
      this.UPDATE_USER({ id: 1, name: 'foo', age: 25 });
  }
}
</script>

黄色组件:获得状态树的state:mapState

<template>
     <ul>
       <li>{{ user.id }}</li>
       <li>{{ user.name }}</li>
       <li>{{ user.age }}</li>
     </ul>
</template>
 <script>
import { mapState } from 'vuex';
export default {
  name: 'get-state',
  computed: {
    ...mapState({
      user: 'userInfo',
    })
  },
}
</script>
路由式通信 vue-router

没想到吧,vue-router不仅仅可以做路由管理,还可以区分组件的编辑和新增状态。
因为对于一个新增或者编辑组件,数据基本上都是一致的,一般都是在同一个组件内增加一个标识去区分新增或者编辑。

这个标识可以是组件自身的一个status属性,也可以是通过props传入的status属性。

也可以不加这种标识,直接通过vue-router去做到。而且用vue-router还可以直接将数据带过去。

父组件通过vue-router的query带数据过去。

this.$router.push({ name: 'componentPost', query: { type: 'edit', data } });

新增/编辑子组件得到数据并做填充。

created() {
    // 判断到是编辑状态
    if(this.$route.query.type==="edit"){
        const data = this.$route.query.data;
        // do some thing with data
    }
}
依赖注入式通信 provide, inject

image

provide,inject其实是一种“解决后代组件想访问共同的父组件,$parent层级过深且难以维护问题“的利器。其中心思想是依赖注入。

学习过react的同学应该知道context这个概念,在vue中,provide/inject与之很类似。

通过vue官方的例子我们做一个解释:

<google-map>
  <google-map-region v-bind:shape="cityBoundaries">
    <google-map-markers v-bind:places="iceCreamShops"></google-map-markers>
  </google-map-region>
</google-map>

google-map-region和google-map-markers如果都想获得祖先元素google-map实例,然后调用它的方法getMap。

// google-map-region这样做
this.$parent.getMap();
// google-map-markers这样做
this.$parent.$parent.getMap();

如果还在google-map-markers 组件下还有子组件呢?this.$parent.$parent.$parent.getMap();

这种代码还能看吗???而且后期组件结构有变动的话,根本无法维护。

为了解决这个问题,可以使用provide/inject。

// google-map.vue
<script>
export default {
  name: "child",
  provide() {
      return {
          getMap: this.getMap
      }
  }
};
</script>
// google-map-region.vue,google-map-markers.vue等后代组件这样使用
<script>
export default {
  name: "child",
  inject: ['getMap']
  mouted(){
       this.getMap(); // 这样就可以访问到google-map的getMap方法了。
  }
};
</script>

当注入一个属性时,可以将注入值作为默认值或者数据入口。可以通过from改名字。

// google-map.vue
<script>
export default {
  name: "child",
  provide() {
      return {
          foo: 'hello inject, I am foo',
          bar: 'hello inject, I am bar',
          getMap: this.getMap
      }
  }
};
</script>
// google-map-region.vue,google-map-markers.vue等后代组件这样使用
<script>
export default {
  name: "child",
  inject: {
      primitiveFoo: 'foo',
      specialFoo: {
         from: 'bar',
         default: '默认属性'
      },
       googleMapGetMap: 'getMap',
  },
  mouted() {
      // 这样就可以访问到google-map的foo属性了。
      this.primitiveFoo; // 'hello inject, I am foo'
      this.specialFoo; // 'hello inject, I am bar'
      this.googleMapGetMap(); // 这样就可以访问到google-map的getMap方法了。
  }
};
</script>

具体可以参考:provide / inject和依赖注入

基于nodejs的EventEmitter通信

其实与基于vue实例的event bus很类似。都是很简单的双向通信的,基于订阅发布模型的通信方式。
image

如果是基于webpack,vue/react等等现代化的基于nodejs开启本地服务器和打包发布的项目,可以在项目中使用nodejs的EventEmitter。

按照自己喜欢的名称overwrite原来的方法:

import { EventEmitter } from 'events';

class Emitter extends EventEmitter {
  $emit(eventName, cargo) {
    this.emit(eventName, cargo);
  }
  $on(eventName, callback) {
    this.on(eventName, callback);
  }
  $off(eventName, callback) {
    this.removeListener(eventName, callback);
  }
}

export default new Emitter();

红色组件使用emitter $emit发送事件

import emitter from '../emitter';
emitter.$emit('foo-bar-baz', 'hello yellow');

黄色组件使用emitter $on接收事件

import emitter from '../emitter';
emitter.$on('foo-bar-baz', (msg)=>{
    console.log(msg); // 'hello yellow'
});

最后使用 o f f 销 毁 事 件 。 若 是 在 v u e 中 , 建 议 在 b e f o r e D e s t r o y ( ) 生 命 周 期 中 使 用 , 并 且 需 要 将 off销毁事件。 若是在vue中,建议在beforeDestroy()生命周期中使用,并且需要将 off销毁事件。若是在vue中,建议在beforeDestroy()生命周期中使用,并且需要将on的callback赋值为一个具名回调。

mounted(){
    this.fooBarBazHandler =  (msg)=>{
        console.log(msg); // 'hello yellow'
    }
    emitter.$on('foo-bar-baz', this.fooBarBazHandler);
}
beforeDestroy() {
    emitter.$off('iText-confirm', this.fooBarBazHandler);
},

组合使用watch,vuex,event bus可能起到意想不到的效果,我手上开发的PC端聊天模块,就是基于watch,vuex和event bus实现的,非常强大。

我相信大家在实际开发中可以找到自己的最佳实践。

多Window / Tab / Page 通信

这是一个非常常见的场景,当你打开了一个页面需要与另一个页面做数据传递时,组件间通信那一套是行不通的。
因为每个window/page/tab都是单独的一个vue实例,单独的vuex实例,即使是nodejs的e、EventEmitter,也是一个单独的emitter实例。

这要怎么办呢?其实浏览器为我们提供了多种方式去做这件事。

  • window.open与window.opener (基于当前window生成子window,实现父->子window的通信)
  • localStorage与window.onstorage (监听onstorage的event对象key的变化,实现tab间通信)
  • BroadCast Channel (创建一个单独通信通道,tab在这个通道内进行通信)
  • Shared worker (开启一个共享的工作线程,tab在这个共享线程内进行通信)

window.open与window.opener (基于当前window生成子window,实现父->子window的通信

假设下面这样一个场景:点击图片打开一个新的window,1秒后替换成别的图片。
image

<img :src="src"  @click="openChildWindow()"/>
openChildWindow(){
     // window.open会返回子window对象
     this.childWindow = window.open("https://foo.bar.com/baz.jpg");
     setTimeout(()=>{
        // 通过this.childWindow访问到子对象进行操作
         this.childWindow.location.replace("https://foo.bar.com/baz.png");
     }, 1000)
}

this.childWindow.opener就是当前的window实例,在子window内也可以访问到父window进行操作。

localStorage/sessionStorage与window.onstorage (监听onstorage的event对象key的变化,实现tab间通信

image

这是一种在tab已经打开后,无法明显建立父子关系的场景下常用的方法。

Tab A:在localStorage/sessionStorage中set一个新值

window.localStorage.setItem('localRefresh', +new Date());
window.sessionStorage.setItem('sessionRefresh', +new Date());

Tab B:监听storage的变化

window.onstorage = (e) => {
  if (e.key === 'localRefresh') {
      // do something
  }
  if (e.key === 'sessionRefresh'') {
      // do something
  }
};

这样我们就实现TabA和TabB之间的通信了。

BroadCast Channel (创建一个单独通信通道,tab在这个通道内进行通信)

除了通过上述方式之外,还可以专门建立一个通信通道去交换数据。

image

window创建一个channel并且发送消息给tab和iframe
const bc = new BroadcastChannel('test_channel');
bc.postMessage('This is a test message.');
tab和iframe接收channel数据

只要与父window建立同名BroadcastChannel即可。

const bc = new BroadcastChannel('test_channel');
bc.onmessage = function (event) { 
    console.log(event); // 'This is a test message.'包含在event对象中。
}

Web worker通信

Main thread与Web worker间通信

image

手上项目的热力图计算曾经尝试过将计算逻辑转移到worker子线程计算,但是由于种种原因没有成功,但是积累了这方面的经验。

worker线程

// src/workers/test.worker.js
onmessage = function(evt) {
  // 工作线程收到主线程的消息
  console.log("worker thread :", evt); // {data:{msg:”Hello worker thread.“}}
  // 工作线程向主线程发送消息
  postMessage({
    msg: "Hello main thread."
  });
};

main线程

// src/pages/worker.vue
<template>
  <div>Main thread</div>
</template>

<script>
import TestWorker from "../workers/test.worker.js";

export default {
  name: "worker",
  created() {
    const worker = new TestWorker();
   // 主线程向工作线程发送消息
    worker.postMessage({ msg: "Hello worker thread." });
   // 主线程接收到工作线程的消息
    worker.onmessage = function(event) {
      console.log("main thread", event); // {data:{msg:"Hello main thread."}}
    };
  }
};
</script>

image

更多如何在vue项目中使用Main thread与Web worker间通信的demo可以查看:一次失败的用web worker提升速度的实践

多tab共享Shared worker,tab与worker间的通信

image

Shared worker是一种web worker技术。
mdn的这个demo为我们清晰地展示了如何使用SharedWorker,实现tab对worker的共享。

SharedWorker的执行脚本worker.js

onconnect = function(e) {
  var port = e.ports[0];

  port.onmessage = function(e) {
   var workerResult = 'Result: ' + (e.data[0] * e.data[1]);
    port.postMessage(workerResult);
  }

}

Tab A与Tab B都新建名为worker.js的SharedWorker

var myWorker = new SharedWorker("worker.js");
myWorker.port.start();
向worker发送数据
console.log('Message posted to worker');
myWorker.port.postMessage();
向worker接收数据
myWorker.port.onmessage = function(e) {
    console.log('Message received from worker');
}

地址:http://mdn.github.io/simple-shared-worker/
worker-1
image
worker-2
image

共享了什么,共享了一个乘法worker,worker1和worker2都可以用,在这里是乘法运算。
image

总结

在这边博文中我们学习到了DOM通信,vue组件间通信,多Window通信 / Tab间通信,Web worker通信等等前端通信的知识点。
但是要知道,这些仅仅是实际开发中的可选项集合,具体使用什么样的技术,还是要结合具体的应用场景。
而且在前端日新月异的更新换代中,会有老的技术消失,会有新的技术出现。一定要保持stay hungry的态度。

参考资料:

  • https://cn.vuejs.org/v2/guide/
  • https://vuex.vuejs.org/zh/guide/
  • https://developer.mozilla.org/en-US/docs/Web/API/Broadcast_Channel_API
  • https://github.com/mdn/simple-shared-worker
  • https://github.com/FrankKai/FrankKai.github.io/issues/178
  • https://github.com/FrankKai/FrankKai.github.io/issues/193
  • https://github.com/FrankKai/FrankKai.github.io/issues/181

期待和大家交流,共同进步,欢迎大家加入我创建的与前端开发密切相关的技术讨论小组:

努力成为优秀前端工程师!

前端程序员从菜鸟到大神必学的七本前端书籍 前端易学易懂,属于一个人傻钱多速度来的行业,随着移动互联网的日益兴起,it行业对于前端的需求也在不断的提高,那么从前端小白修炼成为前端大神的这个过程之中,一些必备的枕边书也是必不可少的。 一、《CSS那些事儿》 内容介绍:《CSS那些事儿》是2009年电子工业出版社出版的图书,作者是林小志。该书通过对CSS技巧实例进行讲解,浅入深地分析了CSS相关知识。 通过页面中的文字、图片、表格、表单等... 阅读详情

相关推荐

零基础入门前端工程师必备书籍推荐

零基础自学前端的过程中看书是必不可少的,多看书能帮助你打牢基础、稳固根基,有很多人问我前端工程师需要看一些什么书?尤其是零基础自学前端的新手,今天我就整理了一份书单推荐给大家。 1、《Web前端开发最佳实践》 本书主要讲解了html、css、JavaScript以及移动端开发的最佳实践方案,能够对缺乏良好指导的开发者产生很大的帮助。通过阅读本书我们可以掌握如何编写高可读性、高维护性、高性能的html、css以及JavaScript。 作者简介:党建,资深Web前端开发工程师。精通HTML、CSS、Java

kobe_back的博客 3059

HTML5 前端原生 WebSocket 通信

HTML5 WebSocket WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。 WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。 WebSocket 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。 很多网站为了实现推送技术,所用的技术都是 Aj...

蚩尤后裔-汪茂雄 3483

传输线的特征阻抗

信号源内阻与所接传输线的特性阻抗大小相等且相位相同,或传输线的特性阻抗与所接负载阻抗的大小相等且相位相同,分别称为传输线的输入端或输出端处于阻抗匹配状态,简称为阻抗匹配。否则,便称为阻抗失配。有时也直接叫做匹配或失配。指一个电路输入端的等效阻抗。在输入端上加上一个电压源U,测量输入端的电流I,则输入阻抗Rin就是U/I。可以把输入端想象成一个电阻的两端,这个电阻的阻值,就是输入阻抗。- 对于电压驱动的电路,输入阻抗越大,则对电压源的负载就越轻,因而就越容易驱动,也不会对信号源有影响;

学海无涯的专栏 4464

前端的通信(三种)

前端通信(三种) 1.Node 中 net 模块的前端通信 2.H5提供的 WebSocket 【常用于 移动端】 3.pc端低版本浏览器使用 socket.io 通信 - 服务券:总服务器 - 客户端: 单个用户应用 有多个 Node中net模块的通信 流程 总服务器的创建步骤 1.第一步搭建总服务器 2.引入net内置模块,创建服务器 3.用net的createServer()方法创建一个服务...

nanwanLisa的博客 1381

光耦选型避坑指南:如何根据CTR参数精准计算输入输出电阻(附24V工业场景实例)

本文深入解析光耦选型核心,聚焦电流传输比(CTR)参数及其衰减特性,提供从输出需求反向推导输入输出电阻的精准计算方法。文章以24V工业场景为例,结合光电耦合器数据手册,详细阐述了如何根据CTR最小值进行降额设计,并给出包含反接保护、TVS管等在内的完整保护电路方案,旨在构建高可靠、长寿命的信号隔离电路,避免因选型或设计不当导致的系统故障。

nept的博客 1040

保姆级教程:用Wokwi玩转ESP32 MicroPython仿真(含库文件配置指南)

本教程详细介绍了如何使用Wokwi平台进行ESP32 MicroPython仿真开发,包括库文件配置、传感器数据模拟和REPL调试技巧。通过Wokwi的仿真调试系统,开发者可以在浏览器中快速验证代码逻辑,提高开发效率,特别适合物联网项目的快速迭代。

weixin_29195615的博客 443

vue实现动态树与左侧栏折叠效果

实现左侧栏折叠效果,显示树形菜单

Bugxiu_fu的博客 2284

kubedns-coredns部署pod出现not ready问题

文章目录遇到的问题1、发现问题2、排查问题3、解决方法 coredns的实例health_check不通过的问题,排查和解决方法 遇到的问题 1、发现问题 pod启动但是未ready 查看是readiness失败 使用对应的URL进行curl,发现真的返回503 2、排查问题 查看错误日志,发现一堆这个错误"waiting on : kubernetes" 网上相关的问题解答 这个跟测试场景不一样,这个案例是开了防火墙,可以确认我这个案例的机器没有开防火墙,但它提醒了一点,coredns是需要访问ap

u012533481的博客 2844

前端框架综述(8)前端

前端到底有什么,现在前端各种各样,处于一个百家争鸣的情况,所以现在很多学习前端的人不知道到底应该学习哪一个框架,下面就针对现在前端的整体情况进行宏观描述。

jayden 2502

OpenAI,从推出更强大的Sora 2模型展开探索与未来发展前景+部署方法大全+文末邀请码*12

摘要 OpenAI推出的Sora 2是第二代AI视频生成模型,在多模态内容生成领域实现重大突破。文末足足有12个邀请码,速来速享!!!

aqfcca的博客 2248

在群辉(NAS)中安装虚拟机套件(Virtual Machine Manager)

一、在群辉中下载虚拟机套件Virtual Machine Manager ①启用Open vSwitch(网络-->管理--启用Open vSwitch) ②打开“套件中心” ③查找到Virtual Machine Manager套件点击“安装套件” 二、安装虚拟机套件(Virtual Machine Manager) ①打开虚拟机套件运行设置向导 ②选择存储空间...

提供C#相关开发 、云计算、运维测试、网络安全相关技术分享与服务,有意向可联系。 2万+

【前端知识体系梳理(二)】前端跨页面通信手段

✅作者简介:大家好我是无处不楼台,是一个什么都会一点的大前端小白博主! 📃个人主页:无处不楼台的博客_优快云博客-JavaScript学习,项目开发; 🔥系列专栏:https://blog.csdn.net/qq_53087870/category_11785056.html?spm=1001.2014.3001.5482https://blog.csdn.net/qq_53087870/category_11785056.html?spm=1001.2014.3001.5482 💖.

henu_GM的博客 5350

SillyTavern本地AI聊天平台部署与调优全指南

大型语言模型(LLM)作为当前人工智能领域的核心技术,通过其强大的自然语言理解和生成能力,正在深刻改变人机交互方式。其工作原理基于Transformer架构,通过海量数据训练,学习语言的统计规律与语义关联。这项技术的核心价值在于,它能够作为通用基础,赋能于多样化的下游应用,实现个性化的智能对话与内容创作。在工程实践中,如何高效、灵活且低成本地部署和利用这些模型,成为开发者与爱好者的关键需求。本地化部署方案,特别是结合如Ollama、KoboldCPP等推理引擎,提供了数据隐私保障与可控的硬件成本。Silly

weixin_42520448的博客 431

前端不同服务器之间的通信_有关前端的那些事儿

1.前端做什么 软件开发主要分为三部分:网页设计师,前端工程师,后台工程师 网页设计师主要负责使用Photoshop或者其他工具做成网页固定排版(即UI设计),而前端工程需要将网页设计师做成的网页样例做成静态网页,实现部分功能,最后,由后台工程师将静态网页做成动态网页,最后实现所有功能。2.前端基础学什么 结构:HTML用来描述页面的结构 表现:CSS用于控...

weixin_39619433的博客 248

RICHARDSON-LUCY 去卷积简介

Lucy去卷积1.泊松过程及联合概率分布2.极大似然估计参考文献 1.泊松过程及联合概率分布 首先假设相机接收光子生成图像的过程符合泊松分布。 因此,一次曝光过程中,某像素位置接收到iii个光子的概率p(i)p(i)p(i)为: p(i)=exp⁡(−λ)⋅λii!\qquad\qquad p(i)=\exp(-\lambda)\cdot\cfrac{\lambda^{i}}{i!}p(i)=exp(−λ)⋅i!λi​ 那么针对一张M∗NM*NM∗N的图像,所有像素的联合概率分布可以描述为: P(I)=∏e

驽马十驾,功在不舍;锲而不舍,金石可镂。 8694

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

一文带你了解,前端模块化那些事儿

该文章主要讲述了前端模块化的发展历史和各个阶段的技术方案,包括无模块化(IIFE)、CommonJS、AMD、CMD、ESModule、UMD。其中,无模块化时期的文件拆分是最基础的模块化,但也存在函数命名冲突的问题;IIFE 是现代模块化的基石,利用函数的块级作用域进行隔离,可以控制作用域;CommonJS 文件即模块,模块加载同步,适用于服务器端 node,浏览器端使用 webpack 或 browserfy。

老男孩的博客 1065

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

Hybrid 应用中 H5 与 Native 通信的那点事儿

作者:董华磊,百度高级研发工程师APP 开发技术对比Native App一般是指本地化应用,后续简称 NA;优点:体验好,可以做一些比较好的交互效果,可作为独立软件出售;缺点:更新较差,...

程序员成长指北 2419

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

前端与HTTP那些事儿

各版本的http 发展 在HTTP建立之初,主要是为了传输超文本标记语言(HTML)文档。随着时代的发展,也进行了若干次演进。下图是各个版本发布的时间轴。 目前为止,使用最为广泛的是http1.1,http1.0应该比较少了,最新的是http2。 这篇博文也主要,围绕着1.0、1.1、2.0三个版本进行介绍。 http/1.0 http1.0不会复用tcp链接,每次请求都会打开、断开一条链接。 ...

qianduan6666666的博客 3039

前端架构那些事儿

前端架构那些事儿 在谈前端架构之前,需要先探讨一下不同人群对前端产生的困惑。前端这个职业最近几年才逐渐被认可,之前一直是低端的代名词,所以多数高手很不屑搞这个。之前的很多项目,人们对前端这块的要求也只是能用就行,所以很少会在上面去细致、深入地建立一套完善体系。而多数产品的技术经理也会是后端出身的,往往对前端的认识还停留在Java Struts那个原始的MVC模型上,或者首先想到的就是GWT和JS

落叶翩翩的优快云博客 884

前端开发那些事儿

前端开发是做什么的? 无论是前端工程师还是后端工程师都是做软件开发的. 软件开发主要有两种j架构:C/S和B/S C/S:(Client/Server 客户端/服务器):一般我们使用的软件都是C/S架构,比如QQ\office\360......,C表示客户端,用户通过客户端来使用软件,S表示服务器,负责处理软件的业务逻辑. 其特点:1.使用前必须要安装.2.软件更新时服务器与客户端同时更新...

Hanhanyoona的博客 834

[转]关于前端的那点事儿

Web前端都有些什么职位? 概括来说,Web前端的相关职位名称主要有:“网页制作”、“网页制作工程师”、“前端制作工程师”、“网站重构工程师”、“前端开发工程师”、“资深前端开发工程师”以及“前端架构师”。 Web前端开发需要哪些技能?   前端开发主要是做Web端的结构、行为和表现的,对应W3C的相应标准,结构层面需要我们去了解和掌握HTML和XHTML,表现层面我们需 ...

weixin_34029680的博客 271

图书管理系统html前端_微前端一二事儿

作者 : 写代码的比熊君如果盘点2019年最火的前端技术,那么微前端肯定占有一席之地。 但是大部分人对于微前端这个架构新贵的了解还是处于懵懵懂懂的状态,本文将会详细介绍微前端的前生今世,带大家了解微前端架构是如何一步步从实际需求中演化而来,以及小桔车服基于微前端所提炼的一套中后台体系建设实践。什么是微前端微前端这个概念最初是对应于微服务这个概念提出的,微服务的核心思想就是将一个大的单体应用基于业务...

weixin_39557797的博客 2201

不只是滑块:从某讯验证码的VMP实现,聊聊前端代码保护的那些事儿

本文深入探讨了某讯滑块验证码采用的VMP(虚拟机保护)技术,揭示了前端代码保护的重要性与技术实现。通过分析VMP的工作原理、优势与局限,以及与其他保护技术(如代码混淆、WebAssembly)的对比,为开发者提供了构建多层次前端安全防护体系的实用建议。

weixin_30629653的博客 435
上一篇: 物联网宠儿mqtt.js那些事儿
下一篇: 2020年冬季前端笔试题总结
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

趁你还年轻233

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值