vue2 中如何使用 render 函数编写组件

news2024/11/26 22:21:33

vue2 中如何使用 render 函数编写组件

    • render 基础语法
    • createElement
      • 返回值:VNode
      • 参数
        • 处理样式和类
        • 组件 props
        • HTML 特性和 DOM 属性
        • 处理事件
        • 插槽
        • 指令
        • v-model 指令
        • 其他属性
    • 使用 render 封装一个输入框
    • 其他问题
    • 参考

vue 提供了声明式编写 UI 的方式,即 vue 提供了对 DOM 进行描述的方式。

有两种描述 DOM 的方式:模板和 render 函数。模板在编译阶段会被转成 render 函数,这一过程叫编译模板。

模板可读性好,但是有时候模板并不灵活,大型的模板可读性也不好。

render 函数可读性不高,但是灵活,使用 render 函数封装组件,使用得当,可提高组件的扩展性和易用性。jsx 可解决 render 函数读写性不高的问题。

在 vue 的项目入口文件中,下面的代码新建一个 vue 应用的根组件,并默认命名为 Root,并将其挂载在 HTML 模板 #app div 上,它的模板在哪?

new Vue({
  render: h => h(App),
}).$mount('#app')

这是一个没有模板的组件。

KaTeX parse error: Expected 'EOF', got '#' at position 8: mount('#̲app'),选择器对应的 do…mount(elector)`挂载元素,替换 selector 后,dom 的属性丢失。 两者表现不同,有点奇怪,但是不需要太关注这个区别。

今天再来复习 render 函数,重点关注这些容易踩坑的地方:

  1. 学习 render 函数的使用,重点:样式、事件、插槽、指令、props、v-model、函数组件的处理。

  2. 学习使用 jsx 封装组件。

  3. 在 render 函数中使用表单组件,因为表单组件涉及到 v-model 容易踩坑。

为何要了解 render ?

在 render 函数中,可用 jsx 代替模板语法,可充分发挥 js 的能力,使得组件扩展性更好、封装更加优雅。

官网说得比较明白了,但是例子过于简单,只能体现优雅,没有体现扩展性,稍后封装一个能体现扩展性的组件。

render 基础语法

render 函数签名:

render(createElement: CreateElement, hack: RenderContext<Props>): VNode;
  1. 返回值 – VNode (虚拟节点) — 一个用于描述 vue 组件结构的 JS 对象

vnode对象

说明
①. 返回值往往是一个单节点,划线的 context 是 vue 全局对象,有 $children 属性,是一个 VNode 数组,元素是一个 VNode,这样的层层嵌套,正好对应的组件的嵌套。 $el 是组件挂载点,_uid 是组件 id。调试时可能会用到。

②. 也可以返回 VNode 数组。比如返回 this.$scopedSlots.default() 这是一个作用域插槽,可能是数组。

  1. 参数

第一个参数 createElement,是一个函数,DOM 中有 createElement 用于创建 DOM 节点。vue 中的 createElement 是用于创建 VNode 的。

h 是 createElement 的别名,代表 Hyperscript (生成 HTML 的脚本),Hyperscript itself stands for “script that generates HTML structures”。

写成h,更加方便输入,更加语义化。

第二个参数 hack 是渲染上下文,组件的propslistenersslots 都在这个参数里。

hack 参数

说明
第二个参数在函数组件中才有,非函数组件为 undefined。因为函数组件中不存在组件实例 this,要提供这个参数获取 props 等内容。
第二个参数通常写成context,更加语义化。

render 写成这样:

render(h,context){
 return <span>render函数</span>
}

render 使用 es6 声明方法的方式且返回 jsx ,vue 会自动注入 const h = this.$createElement,仅限于 render 函数,其他函数要使用,就要手动通过参数传入。

render(){
 return <span>render函数</span>
}

这是 es5 的方式:

render:function(){ // 显示传递 h:  function(h) 才行
  return <span>render函数</span>
}

render 不能返回文本,想要显示文本内容,必须套一个标签, react 的 render 可以返回文本。

返回 jsx,vue 内部会调用 createElement编译成 VNode。

如何返回纯文本?

返回文本的 hack 写法
return this._v('someText'),不推荐这么写,会导致他人难以理解。

createElement

返回值:VNode

VNode 是一个描述组件的普通 js 对象。

参数

createElement(
  // html 标签 、自定义标签,比如 el-input
  // template // NOTE 用于传递插槽
  // 一个组件选项对象
  // resolve 了上述任何一种的一个 async 函数 // TODO 如何使用
  'div', // NOTE 必需的
  // 模板使用到的数据对象
  {},
  // string 或者 子VNode
  []
)

第一个参数不能省略,所以不能返回纯文本。 和 react 的 render 不同。

注意
第一个参数可以是 template,往往和第二个参数的slot属性一起使用,指定插槽名称,传递插槽时可以用到。
resolve 的用法我没有搜索到例子,欢迎大佬告诉我。

重点关注第二个参数

处理样式和类
{
  // :class = "{foo:true,bar:false}"
  class:{
    foo: true,
    bar: false
  },
  // :style="{color:'red','font-size':'14px'}"
  style:{
    color:'red',
    fontSize:'14px'
  }
}
组件 props
{
  props: {
    myCustomProp: '组件属性值'
  }
}
HTML 特性和 DOM 属性
{
  // HTML 特性
  // NOTE 在组件内部使用 $attrs 获取 attrs
  // NOTE 会和 class 属性合并吗?
  // NOTE 和 class 属性的优先级,谁高?
  // 这里的 class 不会添加到 标签上
  attrs: {
    id: 'divId',
    class: 'className'
  },
  // DOM 属性
  domProps:{
    textContent: 'div 文本',// 优先级高于 v-text
    innerHTML: 'BAR'  // 优先级高于 v-html
  }
}

注意
①. attrs 特性中的 class 不会被添加到标签上。
②. 注意区分 HTML 特性和 DOM 属性的区别。

处理事件
{
  // v-bind:event
  on: {
    customEventName: value => {
      // 监听组件的自定义事件 即 emit 触发事件
    }
  },
  // 监听组件上的原生事件,只能用在组件上
  nativeOn: {
    click: target => {
      // 监听原生事件 即非 emit 触发的事件
    }
  }
}

注意
nativeOn 只能用于自定义组件。

插槽
{
  scopedSlots: {
    // 默认插槽
    default: props => h('span',props.text),
    otherSlot: props => h('div',props.customProp)
  },
  slot: 'slotName'// 一般和第一个参数 template 一起使用
}

使用模板定义一个按钮:

<template>
  <div>
    <slot name="left"></slot>
    <button>
      <slot v-bind:person="person">
        <span>按钮</span>
      </slot>
    </button>
    <slot name="right" v-bind:age="person.age"></slot>
  </div>
</template>

<script>
  export default {
    name: 'MyButton',
    data() {
      return {
        person: {
          name: 'jack',
          age: 23,
        },
      }
    },
  }
</script>

在模板种使用该组件:

<MyButton>
  <template #right="{age}">
    <span>按钮右边 {{ age }} 岁</span>
  </template>
  <template v-slot="{ person }">这是按钮,{{ person }}</template>
  <template #left>
    <span>按钮左边</span>
  </template>
</MyButton>

在 render 中使用该组件

import MyButton from './MyButton.vue'
export default {
  name: 'UseButton',
  render(h) {
    //NOTE h 第一个参数为 template 第二个参数里的 slot 属性指定插槽名称
    const slotLeft = h('template', { slot: 'left' }, '按钮左边')
    const slotRight = h('template', { slot: 'right' }, '按钮右边')
    const slotDefault = h('template', { slot: 'default' }, '默认插槽')
    const children = [slotLeft, slotDefault, slotRight]
    return h(MyButton, {}, children)
  },
}

在 render 中获取作用域插槽抛出的数据

import MyButton from './MyButton.vue'
export default {
  name: 'UseButton',
  render(h) {
    const slotLeft = h('template', { slot: 'left' }, '按钮左边')
    const children = [slotLeft]
    return h(
      MyButton,
      {
        scopedSlots: {
          default: props => {
            console.log(props)
            const { person } = props
            const text = `作用域插槽,${JSON.stringify(person)}`
            // 返回 h 创建的 VNode
            return h('span', {}, text)
          },
          right: props => {
            console.log(props)
            const { age } = props
            // 返回 jsx
            return <span>按钮右边 {age}</span>
          },
        },
      },
      children
    )
  },
}

总结

①. 普通命名插槽,使用h('template',{slot:'slotName'},children) 编写,然后放渲染组件的第三个参数里。

②. 作用域插槽在第二个参数的 scopedSlots 对象里,该对象的每个属性名是组件的插槽名,值是一个函数,参数为插槽绑定的数据。

使用 render 函数重写编写 MyButton

export default {
  name: 'MyButton',
  data() {
    return {
      person: {
        name: 'jack',
        age: 23,
      },
    }
  },
  render(h) {
    // NOTE default 关键字 不重命名 无法解构
    const { left, right, default: _defaultSlot } = this.$scopedSlots

    // NOTE 传递一个对象,在模板中使用解构取出属性
    const defaultSlot = _defaultSlot({ person: this.person })
    const leftSlot = left()
    const rightSlot = right(this.person)
    const button = h('button', {}, [defaultSlot])
    return h('div', {}, [leftSlot, button, rightSlot])
  },
}

返回 jsx

export default {
  name: 'MyButton',
  data() {
    return {
      person: {
        name: 'jack',
        age: 23,
      },
    }
  },
  render(h) {
    const { left, right, default: _defaultSlot } = this.$scopedSlots
    // NOTE 检查插槽是否存在
    const defaultSlot = (_defaultSlot && _defaultSlot({ person: this.person })) || <span>按钮</span>
    const leftSlot = (left && left()) || ''
    const rightSlot = right(this.person)
    const button = h('button', {}, [defaultSlot])
    //  返回 jsx 使得 dom 结构更加清晰
    return (
      <div>
        {leftSlot}
        {defaultSlot}
        {rightSlot}
      </div>
    )
  },
}

函数式组件:

export default {
  name: 'MyButton',
  functional: true,
  props: {
    person: {
      type: Object,
      default: () => ({ name: 'jack', age: 23 }),
    },
  },
  // NO DATA in functional component
  // data() {
  //   return {
  //     person: {
  //       name: 'jack',
  //       age: 23,
  //     },
  //   }
  // },
  render(h, { props, scopedSlots }) {
    const { left, right, default: _defaultSlot } = scopedSlots
    const defaultSlot = (_defaultSlot && _defaultSlot({ person: props.person })) || <span>按钮</span>
    const leftSlot = (left && left()) || ''
    const rightSlot = right(props.person)
    const button = h('button', {}, [defaultSlot])
    return (
      <div>
        {leftSlot}
        {button}
        {rightSlot}
      </div>
    )
  },
}

总结
①. 普通插槽、命名插槽、作用域插槽都通过 this.$scopedSlots 获取,它们都是返回 VNode 的函数。
②. 插槽绑定的数据通过插槽函数传递,基本数据使用 {} 包裹,方便在模板中解构。
③. 返回 jsx 能让 div 结构更加清晰。
④. 注意检查是否存在插槽,以启用后备内容。

指令
{
  directives: [{ name: 'directive-name', value: '2', expression: '1+1', arg: 'foo', modifiers: { foo: true } }]
}

在模板中定义指令

<template>
  <!-- title 是名字, 指令的 value 由表达式计算出来 -->
  <!-- v-title:argument.modifier1.modifier2="expression" -->
  <div>
    在模板中编写指令
    <p v-title>这是简单指令</p>
    <!-- 只能带一个参数 -->
    <p v-title:argu>这是带参数的指令</p>
    <!-- 动态参数 -->
    <p v-title:[dynamicArgu()]>这是带动态参数的指令</p>
    <p v-title:argu.foo.bar>这是带参数和修饰符的指令</p>
    <p v-title:job.foo="data">这是带参数、修饰符和普通表达式的指令</p>
    <p v-title:job.foo="expresFun">这是带参数、修饰符和函数表达式的指令</p>
  </div>
</template>

<script>
  export default {
    name: 'Title',
    directives: {
      title: {
        inserted(el, bindings, vnode) {
          const { context: that } = vnode
          const { value = false } = bindings
          if (typeof value === 'function') {
            that.setTile(el, value(that.data))
          } else {
            that.setTile(el, value)
          }
        },
        componentUpdated(el, bindings, vnode) {
          const { context: that } = vnode
          const { value = false } = bindings
          if (typeof value === 'function') {
            that.setTile(el, value(that.data))
          } else {
            that.setTile(el, value)
          }
        },
      },
    },
    data() {
      return {
        data: { age: 23, job: 'web dev' },
      }
    },
    methods: {
      setTile(el, titleValue) {
        const textContent = el.textContent
        const title = textContent.trim() || '暂无数据'
        el.title = typeof titleValue === 'string' ? titleValue : title
      },
      dynamicArgu() {
        return Math.random() > 0.5 ? 'argu1' : 'argu0'
      },
      expresFun(data) {
        return data.age + '岁'
      },
    },
  }
</script>

指令对象 bindings

指令对象

总结
不建议在 render 函数中编写指令,难以理解,指令需要在模板使用才能发挥其设计的目的。render 中可直接控制 DOM。

v-model 指令

使用 render 定义组件,如何提供 v-model

说明:
prop:–value + 使用 on 监听组件的事件,在处理函数中触发 input 自定义事件。

在 render 函数中使用 v-model 指令的处理有三种方案:

① . 在数据对象中使用 model 属性:

{
  model: {
    value: this.value,// value 是 data 里的属性
    callback: value => {
      // 可以再赋值之前做其他逻辑
      // 验证数据
      // 触发事件
      this.value = value
    }
  }
}

②. 传递 value + 监听 input 事件

{
  props: {
    // value 是 data 中的属性
    value: this.value
  },
  on: {
    input: value => {
      // 可做其他事情
      // 触发事件
      this.value = value
    }
  }
}

③. 在 jsx 中使用 vModel 属性

// input 是 data 中的属性
<MyInput vModel={this.input} />

三种方案的优缺点:

model 属性更加好,当表单项还有其他事件时,还可以在 on 中监听它们,比如 element 的下拉,有changeclear 等事件。

props value + input, 很符合 v-model 的语法糖。

jsx+ vModel 属性,简洁,常用。

其他属性
{
  key: 'v for 中的 key',
  ref:'模板变量',
  refInFor: true, // 循环中的 ref 是一个数组
}

使用 render 封装一个输入框

MyInput.jsx

import './my-input.css'
export default {
  name: 'MyInput',
  props: {
    // 需要实现 v-model 指令
    value: {
      type: [String, Number],
      default: '',
    },
  },
  render(h) {
    return h('input', {
      class: {
        'my-input': true,
      },
      style: {
        backgroundColor: '#ccc',
      },
      attrs: {
        id: 'my-input',
        class: 'a-my-input',
        'data-key': 'key',
      },
      domProps: {
        value: this.value,
      },
      // 监听 input 的 input 事件
      on: {
        input: ({ target }) => {
          this.$emit('input', target.value)
        },
      },
    })
  },
}

说明
还可以使用 computed: domProp 的 value 接收一个计算属性,为该计算属性提供 setter 和 getter ,在 input 事件处理函数中设置计算属性的值,在 setter 中触发 自定义的 input 事件。这种方法不如上面的明白,代码量也多了。

在模板中使用该组件

<MyInput v-model="myInput" />

在 render 函数中使用

export default {
  name: 'UseInput',
  data() {
    return {
      input: '',
    }
  },
  render(h) {
    return h('div', {}, [
      h(MyInput, {
        model: {
          value: this.input,
          callback: value => {
            // 可在此做其他事件
            this.input = value
          },
        },
      }),
      h('h3', {}, this.input),
    ])
  },
}

希望 UseInput,支持 v-model,即在二次封装 MyInput。

方案 1:添加 value props 在 model 中触发 input,删除 data 中的 input。

import MyInput from './my-input.jsx'
export default {
  name: 'UseInput',
  props: {
    value: { type: [String, Number], default: '' },
  },
  render(h) {
    return h('div', {}, [
      h(MyInput, {
        model: {
          value: this.value,
          callback: value => {
            // 可在此做其他事件
            this.$emit('input', value)
          },
        },
      }),
      h('h3', {}, this.value),
    ])
  },
}

方案 2: 添加 value props,将其通过 props 传入 UseInput,监听 UseInput 的input事件,在此触发input事件。

import MyInput from './my-input.jsx'
export default {
  name: 'UseInput',
  props: {
    value: { type: [String, Number], default: '' },
  },
  render(h) {
    return h('div', {}, [
      h(MyInput, {
        props: {
          value: this.value,
        },
        on: {
          input: value => {
            this.$emit('input', value)
          },
        },
      }),
      h('h3', {}, this.value),
    ])
  },
}

说明: 对于具有多种事件的表单项,比如 element 的下拉框,第一种方案更加好,on 属性留位置给从外传入的处理函数。

方案 3: jsx + vModel + prop value

import MyInput from './my-input.jsx'
export default {
  name: 'UseInput',
  props: {
    value: { type: [String, Number], default: '' },
  },
  data() {
    return {
      input: this.value,
    }
  },
  render(h) {
    return (
      <div>
        <MyInput vModel={this.input} />
        {/* <h2>{this.input}</h2> */}
      </div>
    )
  },
}

** 注意**:这种方案不能实现双向绑定

其他问题

  1. 如何限制继承的属性,inheritAttrs 设置为 false,无法显示。

在模板定义的组件中,inheritAttrs 属性设置为 false, 除styleclass 以为的属性不会添加到根组件,实现手动控制。

render 定义的组件中,也是一样的。

参考

What does the ‘h’ stand for in Vue’s render method?

A Practical Use Case for Vue Render Functions: Building a Design System Typography Grid

How to use v-model ( for custom input component) in render function?

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java+Spring boot+MYSQL 技术开发的UWB室内外高精度一体化融合定位系统源码 UWB技术定位系统应用场景

JavaSpring bootMYSQL 技术开发的UWB室内外高精度一体化融合定位系统源码 UWB技术定位系统应用场景 系统聚焦基于UWB(超宽带)技术的底层定位网络和定位算法&#xff0c;通过对定位分站、定位标签、定位引擎的硏发&#xff0c;实现高精度定位网络&#xff0c;获取高精度定位结果…

翻译《The Old New Thing》- Why isn’t there a SendThreadMessage function?

Why isnt there a SendThreadMessage function? - The Old New Thing (microsoft.com)https://devblogs.microsoft.com/oldnewthing/20081223-00/?p19743 Raymond Chen 2008年12月23日 为什么没有 SendThreadMessage 函数&#xff1f; 简要 文章讨论了 Windows 中不存在 Sen…

用QT6、QML、FFMPEG写一个有快进功能的影音播放程序

程序如图&#xff1a; 开发环境在ubuntu下&#xff0c;如果改windows下&#xff0c;也就改一下cmakelists.txt。windows下如何配置ffmpeg以前的文章有写&#xff0c;不再重复。 源程序如下&#xff1a; GitHub - wangz1155/ffmpegAudioThread: 用qt6&#xff0c;qml&#xff…

深度图的方法实现加雾,Synscapes数据集以及D455相机拍摄为例

前言 在次之前&#xff0c;我们已经做了图像加雾的一些研究&#xff0c;这里我们将从深度图的方法实现加雾展开细讲 图像加雾算法的研究与应用_图像加雾 算法-CSDN博客 接下来将要介绍如何使用深度图像生成雾效图像的方法。利用Synscapes数据集&#xff0c;通过读取EXR格式的…

Linux☞进程控制

在终端执行命令时&#xff0c;Linux会建立进程&#xff0c;程序执行完&#xff0c;进程会被终止&#xff1b;Linux是一个多任务的OS,允许多个进程并发运行&#xff1b; Linxu中启动进程的两种途径&#xff1a; ①手动启动(前台进程(命令gedit)...后台进程(命令‘&’)) ②…

重构大学数学基础_week04_从点积理解傅里叶变换

这周我们来看一下傅里叶变换。傅里叶变换是一种在数学和许多科学领域中广泛应用的分析方法&#xff0c;它允许我们将信号或函数从其原始域&#xff08;通常是时间域或空间域&#xff09;转换到频域表示。在频域中&#xff0c;信号被表示为其组成频率的幅度和相位&#xff0c;这…

STM32F103C8T6基于HAL库完成uC/OS-III多任务程序

一、在STM32CubeMX中建立工程 配置RCC 配置SYS 配置PC13为GPIO_Output 配置USART1 生成代码 二、获取uC/OS-III源码 官网下载地址&#xff1a;Micrium Software and Documentation - Silicon Labs 网盘下载&#xff1a;百度网盘 请输入提取码 提取码&#xff1a;lzjl 三、复…

反射型xss靶场练习

反射型xss危害小&#xff0c;这里使用的xss靶场是常用的xss靶场&#xff1a;xss-labs。 当我们完成弹窗后就通过该关卡&#xff0c;说该关卡存在xss的一个漏洞并且可以解析js代码。 第一关&#xff1a; 这里没有过滤我们输入的代码&#xff1a;直接将js代码放在js代码中&a…

SpringBoot图书管理系统【附:资料➕文档】

前言&#xff1a;我是源码分享交流Coding&#xff0c;专注JavaVue领域&#xff0c;专业提供程序设计开发、源码分享、 技术指导讲解、各类项目免费分享&#xff0c;定制和毕业设计服务&#xff01; 免费获取方式--->>文章末尾处&#xff01; 项目介绍048&#xff1a; 图…

springboot中路径默认配置与重定向/转发所存在的域对象

今天在写项目的时候&#xff0c;突然发现引用js的时候路径不匹配&#xff0c;让我再次对路径问题产生了疑问&#xff0c;通过查阅springboot官网可以发现&#xff0c;在springboot中查找静态资源的时候&#xff0c;会默认在static、public、resources下查找&#xff0c;官网中也…

C++面向对象程序设计 - 字符串流

文件流是以外存文件为输入输出对象的数据流&#xff0c;字符串流不是以外存文件为输入输出的对象&#xff0c;而以内存中用户定义的字符数组&#xff08;字符串&#xff09;为输入输出的对象&#xff0c;即将数据输出到内存中的字符数组&#xff0c;或者从字符数组&#xff08;…

【NI国产替代】PCIe 高速采集卡, 8 位双通道数字化仪器,采集卡最高采样率高达 5 GS/s 模拟带宽高达 500 MHz

• 8 位双通道数字化仪器 • 最高采样率高达 5 GS/s • 模拟带宽高达 500 MHz • 采用 PCIe 3.0 x 8 接口 • 基于 Xilinx Kintex UltraScale, XCKU040 • 提供硬件、FPGA、软件定制服务 高速采集卡是一款 8 位双通道数字化仪器&#xff0c;采集卡最高采样率高达 5 GS/s 模…

【python报错】list indices must be integers or slices, not tuple

【Python报错】list indices must be integers or slices, not tuple 在Python中&#xff0c;列表&#xff08;list&#xff09;是一种常用的数据结构&#xff0c;用于存储一系列的元素。当你尝试使用不支持的索引类型访问列表元素时&#xff0c;会遇到list indices must be in…

【教学类-36-07】20240608动物面具(通义万相)-A4大小7图15手工纸1图

背景需求&#xff1a; 风变的AI对话大师一年到期了&#xff0c;也没有看到续费的按钮。不能使用它写代码了。 MJ早就用完了&#xff0c;最后480次&#xff0c;我担心信息课题会用到它生图&#xff0c;所以不敢用。 最近探索其他类似MJ的免费出图工具——找到了每天给50张免费图…

DIO控制卡,IRIG-B码卡,PCI-E总线接口卡,百兆数据采集卡

DIO控制卡 ● 4路继电器输出&#xff08;5A250VAC&#xff09; ● 4路开关量输入&#xff08;24VDC&#xff09; ● 1路IDE接口 ● 端口浪涌保护 IRIG-B码卡 ● 1路IRIG-B对时接口&#xff08;RS485/光纤&#xff09; ● 1路IEEE1588 V2对时接口&#xff08;RJ45/光纤&#…

linux本地搭建dns

不需要图形化界面 使用的是dnsmasq&#xff0c;配置简单 1.安装 deb系列linux apt-get install dnsmasqrhat系列linux yum install dnsmasq2.编辑配置文件 vi /etc/dnsmasq.conf设置主dns服务器&#xff0c;比如现有公用的的114.114.114.114 8.8.8.8这类的 server8.8.8.8…

C语言详解(动态内存管理)2

Hi~&#xff01;这里是奋斗的小羊&#xff0c;很荣幸您能阅读我的文章&#xff0c;诚请评论指点&#xff0c;欢迎欢迎 ~~ &#x1f4a5;&#x1f4a5;个人主页&#xff1a;奋斗的小羊 &#x1f4a5;&#x1f4a5;所属专栏&#xff1a;C语言 &#x1f680;本系列文章为个人学习…

零空间(Null Space)控制例子

零空间(Null Space)控制是一种用于多任务控制系统的技术,特别适用于机器人和多自由度系统。其基本原理是将控制任务分解为不同的优先级,其中高优先级任务在主空间(Task Space)中执行,而低优先级任务在零空间(Null Space)中执行。这样可以保证在完成主要任务的同时,次…

VScode的插件使用

1、正则插件-1 2、AI助手工具-1-fittentech 3、画图工具-1 4、GitHub的查看工具 5、shell测试工具

vuInhub靶场实战系列--Kioptrix Level #1

免责声明 本文档仅供学习和研究使用,请勿使用文中的技术源码用于非法用途,任何人造成的任何负面影响,与本人无关。 目录 免责声明前言一、环境配置1.1 靶机信息1.2 靶场配置 二、信息收集2.1 主机发现2.2 端口扫描2.2.1 masscan2.2.2 nmap 2.3 指纹识别2.4 目录扫描2.4.1 dirb…