React(五) 受控组件和非受控组件; 获取表单元素的值。高阶组件(重点),Portals; Fragment组件;严格模式StrictMode

news2024/10/20 7:47:25

文章目录

  • 一、受控组件
    • 1. 什么是受控组件
    • 2. 收集input框内容
    • 3. 收集checkBox的值
    • 4. 下拉框select
    • 总结
  • 二、非受控组件
  • 三、高阶组件
    • 1. 高阶组件的概念 (回顾高阶函数)
    • 2. 高阶组件应用:注入props
      • (1) 高阶组件给---函数式组件注入props
      • (2) 高阶组件给---类组件注入props
      • (3) 高阶组件注入props+自己需要注入props
    • 3. 高阶组件应用:context的增强
    • 4. 高阶组件应用:登录鉴权
    • 5. 高阶组件应用:生命周期劫持
    • 总结
  • 四、 Portals
  • 五、 Fragment组件
  • 六、 严格模式StrictMode

一、受控组件

1. 什么是受控组件

当表单元素绑定value属性时,就是受控组件,此时按键盘也无法再向输入框里输入信息

若要输入信息,必须绑定onChange事件,获取输入的值,修改state,然后通过value属性将修改后的值显示到输入框里。(很像vue中的v-model)
在这里插入图片描述

2. 收集input框内容

(1) form标签上绑定onSubmit事件,当提交时,触发该事件。
(2) label标签里,htmlFor属性值为所绑定的表单属性的id
(3) 两个不同类型输入框的处理事件合并到一个函数中。e.target.name的值是input标签里的name属性。e.target.value是输入框里的值。(键值读取变量用[]包裹)。

// 提交事件
handleSubmitClick (e) {
  // 1.阻止默认的行为
  e.preventDefault()
  // 2.获取到所有的表单数据, 对数据进行组件
  console.log("获取所有的输入内容:", this.state.username, this.state.password)
  // 3.以网络请求的方式, 将数据传递给服务器(ajax/fetch/axios)
}

// 处理input框输入
handleInputChange (e) {
  this.setState({
    [e.target.name]: e.target.value
  })
}

 // 渲染
 render () {
   const { username, password } = this.state
   return (
     <div>
       <form onSubmit={e => this.handleSubmitClick(e)}>
         <label htmlFor="username">
           用户:
           <input type="text" id="username" name='username'
             value={username}
             onChange={e => this.handleInputChange(e)} />
         </label><br />
         <label htmlFor="password">
           密码:
           <input type="password" name="password" id="password"
             value={password}
             onChange={e => this.handleInputChange(e)} />
         </label><br />
         <button type='submit'>注册</button>
       </form>
     </div>
   )
 }

3. 收集checkBox的值

单选框
(1) 通过checked属性设置该框是否被选中。实现数据改变页面
(2) 读取e.target.checked来获取用户的输入,判断用户点击后,checkbox是true还是false

 handleAgreeChange (e) {
    // 根据用户输入修改状态值
   this.setState({
     isAgree: e.target.checked
   })
 }
{/* 单选框 this.state.isAgree默认值是false */}
 const { isAgree } = this.state
<label htmlFor="agree">
  <input
    id='agree'
    type="checkbox"
    checked={isAgree}
    onChange={e => this.handleAgreeChange(e)}
  />
  同意协议
</label><br />

多选框
多选框就是循环遍历数据。与单选框处理逻辑类似,注意修改hobbies时,需要浅拷贝。

  hobbies: [
    { value: "sing", text: "唱", isChecked: false },
    { value: "dance", text: "跳", isChecked: false },
    { value: "rap", text: "rap", isChecked: true }
  ],
   {/* 多选框 */}
   {hobbies.map((item, index) => {
     return (
       <label htmlFor={item.value} key={item.value}>
         <input
           type="checkbox"
           id={item.value}
           checked={item.isChecked}
           onChange={(e) => this.handleHobbiesChange(e, index)} />
         {item.text}
       </label>
     )
   })}
  // 注意需要浅拷贝
handleHobbiesChange (e, index) {
  console.log(e.target.checked, index);
  const hobbies = [...this.state.hobbies]
  hobbies[index].isChecked = e.target.checked
  this.setState({ hobbies })
}

4. 下拉框select

单选下拉框
(1)通过value属性来设置默认值,fruit: "apple",
(2) e.target.value来读取用户选了什么水果;

   {/* 下拉框 */}
   {/*  value={fruit} 设置默认值 */}
   <select value={fruit} onChange={e => this.handleFruitChange(e)}>
     <option value="orange">橘子</option>
     <option value="apple">苹果</option>
     <option value="banana">香蕉</option>
   </select>
   
// 水果下拉框
handleFruitChange (e) {
 this.setState({ fruit: e.target.value })
}

多选下拉框
(1)添加multiple属性,设置多选,此时绑定的value值为 fruits: ['apple', 'banana']
(2)e.target.selectedOptions获取用户选择,具体看事件处理函数

 {/* 多选框 */}
 <select value={fruits} onChange={e => this.handleFruitsChange(e)} multiple>
   <option value="orange">橘子</option>
   <option value="apple">苹果</option>
   <option value="banana">香蕉</option>
 </select>
// 水果下拉多选框
handleFruitsChange (e) {
 const options = Array.from(e.target.selectedOptions)
 // options里每一项的value值是用户选择的值
 const values = options.map(item => item.value)
 this.setState({ fruits: values })

 // 额外补充: Array.from(可迭代对象)
 // Array.from(arguments)
 const values2 = Array.from(e.target.selectedOptions, item => item.value)
 console.log(values2)
}

在这里插入图片描述

总结

ElementValue propertyChange callbackNew value in the callback
<input type="text" />value="string"onCahngee.target.value
<input type="checkbox" />checked={boolean}onCahngee.target.checked
<input type="radio" />checked={boolean}onCahngee.target.checked
<textarea/>value="string"onCahngee.target.value
<select/>value="option value"onCahngee.target.value

二、非受控组件

(1) 绑定默认值不能用value,会变成受控组件。应该用defaultValue
(2) 给元素添加监听事件,只能用原生的方式; 首先需要绑定ref,然后添加监听事件addEventListener
(3) 通过this.introRef.current.value来获取输入框里的值。
(4) checkboxradio支持defaultCheckedselecttextarea支持defaultValue

export class App extends PureComponent {
  constructor() {
    super()
    this.state = {
      intro: '123456'
    }
    this.introRef = createRef()
  }
  componentDidMount () {
    this.introRef.current.addEventListener(...)
  }
  // 提交事件
  handleSubmitClick (e) {
    // 1.阻止默认的行为
    e.preventDefault()
    // 2.获取到所有的表单数据, 对数据进行组件
    console.log(this.introRef.current.value);
    // 3.以网络请求的方式, 将数据传递给服务器(ajax/fetch/axios)
  }

  // 渲染
  render () {
    const { intro } = this.state
    return (
      <div>
        <form onSubmit={e => this.handleSubmitClick(e)}>
          {/* 非受控组件 */}
          <input type="text" defaultValue={intro} ref={this.introRef} />
          <button type='submit'>注册</button>
        </form>
      </div >
    )
  }
}

三、高阶组件

1. 高阶组件的概念 (回顾高阶函数)

(1) 高阶函数
满足这两个条件之一的就是高阶函数:
接受一个或多个函数作为输入;
输出一个函数;
比如JS中的map,filter,reduce

funcition foo(){
	function bar(){
	}
	return bar
}
// foo函数返回一个函数,所以这个也是高阶函数
const fn = foo()

(2) 高阶组件(Higher-Order Components) 简称HOC
高阶组件本质是一个函数(并不是组件),这个函数的参数是组件,函数的返回值是一个新组件。

// 1. 定义一个原组件
class OriginHW extends PureComponent {
  render () {
    return (
      <div>HelloWorld</div>
    )
  }
}
// 2. 定义一个高阶组件,接收原组件,并对原组件进行一些操作
function hoc (Cpn) {
  class newHW extends PureComponent {
    render () {
      return <Cpn name="why" />
    }
  }
  return newHW
}

// 3. 调用高阶组件,这里的参数直接传原组件的名称;接收到的一个新组件
const HelloHOC = hoc(OriginHW)

class App extends PureComponent {
  render () {
    return (
      <div>
        {/* 使用新组件 */}
        <HelloHOC />
      </div>
    )
  }
}

界面打印:HelloWorld;

可以看出,高阶组件对原来的组件进行了一层拦截,拦截之后就可以对组件进行一些操作,再返回组件。

高阶组件不是React API的一部分,是一种设计模式
高级组件再一些React第三方库中十分常见:
 * 比如:redux中的connect
 * 比如:react-router中的withRouter

2. 高阶组件应用:注入props

  首先定义一个高阶组件,用于给需要特殊数据的组件,注入props数据。比如某些组件需要userInfo这个数据。

src/hoc/enhancedUserInfo.js

// 定义高阶组件,给需要特殊数据的组件,注入props
function enhancedUserInfo (OriginComponent) {
  class NewComponent extends PureComponent {
    // 构造函数
    constructor() {
      super()
      this.state = {
        userInfo: {
          userName: 'tom',
          age: '18'
        }
      }
    }
    render () {
      return (
        // 通过props的方式将数据传给组件
        <OriginComponent {...this.state.userInfo} />
      )
    }
  }
  // 其实本质上return的是注入了props数据的<OriginComponent/>组件
  return NewComponent
}
export default enhancedUserInfo

(1) 高阶组件给—函数式组件注入props

App.jsx

import React, { PureComponent } from 'react'
import enhancedUserInfo from './hoc/enhancedUserInfo'
import About from './pages/About'

// 增强函数式组件,props接收数据,
// funtion后面可以不写函数名,这里是为了区分增强前后,Friend与NewFriend
const NewFriend = enhancedUserInfo(function Friend (props) {
  return <h2>Hello--{props.userName}---{props.age}---{props.fruit}</h2>
})

// App应用函数式组件
class App extends PureComponent {
  render () {
	  ...
	  <NewFriend />
  }
}

(2) 高阶组件给—类组件注入props

src/pages/About.jsx:创建类组件About

import enhancedUserInfo from '../hoc/enhancedUserInfo'
class About extends PureComponent {
  render () {
    return (
      <div>
        {/* 没有构造函数也可以读取this.props */}
        <h2>About---{this.props.userName}---{this.props.age}</h2>
      </div>
    )
  }
}
// 在导出的时候,利用高阶组件增强改类组件,让该组件收到props数据
export default enhancedUserInfo(About)

App.jsx

// App应用函数式组件
class App extends PureComponent {
  render () {
	  ...
	  <About/>
  }
}

(3) 高阶组件注入props+自己需要注入props

在使用子组件之前,通过高阶组件可以注入一些props数据;如果在App中使用子组件时,也往里传递了数据,该怎么接收。

class App extends PureComponent {
  render () {
    return (
      <div>
        {/* fruit实际是传给了高阶组件里的NewComponent */}
        <NewFriend fruit={['apple', 'banana']} />
        <About fruit={['橘子', '火龙果']} />
      </div>
    )
  }
}

这里传递的fruit,实际上是传到了enhancedUserInfo里的NewComponent类中,然后再通过props的方式传给OriginComponent.
在这里插入图片描述
原组件中仍然是通过props来接收这些数据
在这里插入图片描述

3. 高阶组件应用:context的增强

照旧先创建theme-context

src/context/theme-context.js

import { createContext } from 'react'
const ThemeContext = createContext()
export default ThemeContext

App中应用子组件Product,并用Context包裹子组件,传递数据

class App extends PureComponent {
  render () {
    return (
      <div>
        {/* 使用新组件 */}
        <ThemeContext.Provider value={{ color: 'red', size: 20 }}>
          <Product />
        </ThemeContext.Provider>
      </div >
    )
  }
}

子组件接收context数据的方式有两种,指定context类型的只能接收一种context数据。所以一般通过consumer来接收多个context数据。之前的做法是在组件内部使用consumer:
在这里插入图片描述
这样的会让组件可读性不高,且不好维护。

利用高阶组件的做法:在高阶组件中使用consumer,然后将context数据注入原组件中。
(1) 定义高阶组件withTheme;
src/hoc/with-theme.js:

import ThemeContext from "../context/theme-context"
function withTheme (OriginComponent) {
  return (props) => {
    return (
      <ThemeContext.Consumer>
        {
          value => {
            // 通过props将context数据传给子组件
            return <OriginComponent {...value} />
          }
        }
      </ThemeContext.Consumer>
    )
  }
}
export default withTheme

(2) 高阶组件在子组件向外暴露的时候拦截一下,注入数据:

import withTheme from '../hoc/with-theme'
export class Product extends PureComponent {
  render () {
    return (
      // props接收数据。
      <div>Product---color:{this.props.color}---size:{this.props.size}</div>
    )
  }
}
export default withTheme(Product)

4. 高阶组件应用:登录鉴权

(1) 定义一个高阶组件。判断当前是否有token,有就说明登录了(登录就渲染界面),没有就没登录(没登录就返回提示信息)

src/hoc/login-auth .js

function loginAuth (OriginComponent) {
  // 返回一个函数式组件
  return (props) => {
    const token = localStorage.getItem('token')
    if (token) {      // 登录则渲染该组件
      return <OriginComponent />
    } else {      // 没登录则给出提示信息
      return <h2>请先登录</h2>
    }
  }
}
export default loginAuth

(2) 哪个子组件需要登录鉴权,就用高阶组件拦截一下
子组件Cart:

import loginAuth from '../hoc/login-auth'
export class Cart extends PureComponent {
  render () {
    return (
      <div>Cart</div>
    )
  }
}
export default loginAuth(Cart)

(3) App中使用子组件
App中设置一个state数据:isLogin,用来渲染数据的变化。

class App extends PureComponent {
   ...
  login () {
    localStorage.setItem('token', 'tom')
    // 设置isLogin变量的目的是,确定登录,修改数据,能够重新调用render函数
    this.setState({ isLogin: true })
    
    // 如果没有isLogin,可以调用强制刷新的API,但是也不建议使用这个API
    // this.forceUpdate()
  }
  render () {
    return (
      <div>
        <Cart />
        <button onClick={e => this.login()}>点击登录</button>
      </div >
    )
  }
}

高阶函数里什么时候适合创建类组件,什么适合适合创建函数组件。

5. 高阶组件应用:生命周期劫持

通过生命周期来计算每个组件的挂载时间。

  export class Detail extends PureComponent {
     UNSAFE_componentWillMount () {
       this.beginTime = new Date().getTime()
     }

     componentDidMount () {
       this.endTime = new Date().getTime()
       const interval = this.endTime - this.beginTime
       console.log(`当前页面花费了${ interval }ms渲染完成!`)
     }
    render () {...}
  }

抽取到高阶组件中:

// 可以对需要计算渲染时间的组件进行拦截
function logRenderTime (OriginComponent) {
  // 函数式组件没有生命周期,所以返回一个类组件;
  // 由于是直接返回这个类,所以类名可以省略 class NewComponent extends...
  return class extends PureComponent {
    UNSAFE_componentWillMount () {
      this.beginTime = new Date().getTime()
    }

    componentDidMount () {
      this.endTime = new Date().getTime()
      const interval = this.endTime - this.beginTime
      console.log(`当前${ OriginComponent.name }页面花费了${ interval }ms渲染完成!`)
    }
    render () {
      return <OriginComponent {...this.props} />
    }
  }
}
export default logRenderTime

OriginComponent.name可以拿到组件的名字;

应用在某个组件上:

import logRenderTime from '../hoc/log_render_time'
export class Detail extends PureComponent {
 ...
}
export default logRenderTime(Detail)

总结

高阶组件主要是方便代码的复用。
高阶组件中什么时候返回类组件,什么时候返回函数式组件,取决于是否

四、 Portals

 某些情况下,我们希望渲染的内容独立于父组件,挂载到其他位置。甚至独立于当前挂载的DOM元素中。

<!--比如当前除了root根节点,还有第二个节点。通过Portals,我们可以将内容挂载到root2中-->
  <div id="root"></div>
  	  <!-- 新节点 -->
  <div id="root2"></div>

App.jsx
createPortal(child,container)child是任何可渲染的React元素,container是DOM元素,也就是需要挂载的地方。

// 1. 引入createPortal函数
import { createPortal } from 'react-dom'
export class App extends PureComponent {
  render () {
    return (
      <div>
        <h1>AppH1</h1>
        {
          createPortal(<h2>App H2</h2>, document.querySelector('#root2')
          )
        }
      </div>
    )
  }
}
export default App

在这里插入图片描述

五、 Fragment组件

因为要求只能有一个根节点,所以每次写结构都要包裹一个div
当我们不想多一个div结构时,可以采用Fragment

import React, { Fragment, PureComponent } from 'react'
export class App extends PureComponent {
  render () {
    return (
      // <div>
      //   <h1>没吃早饭</h1>
      //   <h2>没吃午饭</h2>
      //   <h3>没吃晚饭</h3>
      // </div>
      
      <Fragment>
        <h1>没吃早饭</h1>
        <h2>没吃午饭</h2>
        <h3>没吃晚饭</h3>
      </Fragment>
    )
  }
}

在这里插入图片描述
Fragment标签可以用是用<></>代替(语法糖)。需要注意,当需要在Fragment标签绑定key属性时,不能采用语法糖的形式。

     <>
       <h1>没吃早饭</h1>
       <h2>没吃午饭</h2>
       <h3>没吃晚饭</h3>
     </>

六、 严格模式StrictMode

StrictMode于Fragment一样,不会渲染到结构上面。主要用来显示程序中潜在的问题。严格模式的检查尽在开发模式下运行。

import React, { PureComponent, StrictMode } from 'react'
export class App extends PureComponent {
  render () {
    return (
      <div>
       {/* 对Home及其后代元素开启严格模式 */}
        <StrictMode>
          <Home />
        </StrictMode>
        <Profile />
      </div>
    )
  }
}

严格模式检查什么?

(1) 识别不安全的生命周期,检查是否使用过时的ref API

// Home.jsx
  UNSAFE_componentWillMount () {
    console.log("Home UNSAFE_componentWillMount")
  }
  render () {
  return (
    <div>
      <h2 ref="title">Home Title</h2>
      {/* <h2>Home</h2> */}
    </div>
  )
}

严格模式下,会报错,提醒程序员,避免一些隐藏的bug。
在这里插入图片描述
如果Profile组件使用这两个过时的API及生命周期函数,仍可正常使用,不会报错误。

(2) 检查副作用
  严格模式检查下的组件的生命周期函数会被调用两次,以检查此处的逻辑代码当被多次调用是,是否会产生bug。在生产环境中是不会被调用两次的。
在这里插入图片描述
(3)检查是否使用其他废弃或过时(findDOMNode)的方法 ,给出警告

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

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

相关文章

开源的存储引擎--cantian

cantian 上次稼先社会活动之后&#xff0c;在北京签售的时候见到了三位参天的核心人物。我有感于他们的热情、务实和坦诚&#xff0c;我觉得还应该在深入的做一些事情。至少可以安装体验一下&#xff0c;做做推广。毕竟现在务实的产品不多了&#xff0c;很多都是浮躁的宣传。为…

从一个事故中理解 Redis(几乎)所有知识点

作者&#xff1a;看破 一、简单回顾 事故回溯总结一句话&#xff1a; &#xff08;1&#xff09;因为大 KEY 调用量&#xff0c;随着白天自然流量趋势增长而增长&#xff0c;最终在业务高峰最高点期占满带宽使用 100%。 &#xfeff; &#xfeff; &#xff08;2&#xff…

如何安装MySql

一.卸载MySql 1.1安装版 进入“控制面板”&#xff0c;将有关“mysql”的一切都删除&#xff0c;再到“C:\ProgramData”中&#xff0c;将“mysql”文件夹删除。 1.2压缩版 先在cmd中停止mysql服务 net stop mysql8 再删除解压“mysql”文件夹即可 二.安装MySql 2.2安装版…

RabbitMQ进阶_可靠性

文章目录 一、 发送者的可靠性1.1、 生产者重试机制1.2、 生产者确认机制1.2.1、确认机制理论1.2.2、确认机制实现1.2.2.1、定义ReturnCallback1.2.2.2、定义ConfirmCallback 二、 MQ的可靠性2.1、 数据持久化2.1.1、 交换机持久化2.1.2、 队列持久化2.1.3、 消息持久化 2.2、 …

端点物联网学习资源合集

端点物联网 学习资源合集 导航 1. 物联网实战--入门篇 文章链接 简介&#xff1a;物联网是一个包罗万象的行业和方向&#xff0c;知识碎片严重&#xff0c;本系列文章通过 边学边用 的思想&#xff0c;逐步建立学习者的信心和兴趣&#xff0c;从而进行更深入透彻的学习和探索…

IDEA如何用maven打包(界面和命令两种方式)

前言 我们在使用IDEA开发时&#xff0c;如果是springboot项目的话&#xff0c;一般是用maven来管理我们的依赖的。然后&#xff0c;当我们开发完成之后&#xff0c;就需要打包部署了。 那么&#xff0c;我们应该如何打包呢&#xff1f; 如何打包&#xff08;jar包&#xff09…

scrapy案例——链家租房数据的爬取

案例需求&#xff1a; 1.使用scrapy爬虫技术爬取链家租房网站&#xff08;成都租房信息_成都出租房源|房屋出租价格【成都贝壳租房】 &#xff09;的数据&#xff08;包括标题、价格和链接&#xff09; 2.利用XPath进行数据解析 3.保存为本地json文件 分析&#xff1a; 请…

(AtCoder Beginner Contest 375)B - Traveling Takahashi Problem

&#xff08;AtCoder Beginner Contest 375&#xff09;B - Traveling Takahashi Problem 题目大意 按顺序给定n个点 ( x i , y i ) (x_i,y_i) (xi​,yi​) 求按顺序走过这n个点并回到原点的总距离 任意两点之间的距离是欧几里得距离 思路 按照题意模拟即可&#xff0c;时间…

GPTLink 源码快速搭建 ChatGPT 商用站点

GPTLink 源码快速搭建 ChatGPT 商用站点&#xff0c;基于PHP(Hyperf) Vue开发的&#xff0c;可以通过docker轻松部署&#xff0c;并且有一个支持PC和移动端的完美UI控制台。该项目提供了许多强大的功能&#xff0c;包括自定义付费套餐、一键导出对话、任务拉客和用户管理等等。…

NeRF三维重建—神经辐射场Neural Radiance Field(二)体渲染相关

NeRF三维重建—神经辐射场Neural Radiance Field&#xff08;二&#xff09;体渲染相关 粒子采集部分 粒子采集的部分我们可以理解为&#xff0c;在已知粒子的情况下&#xff0c;对图片进行渲染的一个正向的过程。 空间坐标(x,y,z&#xff09;发射的光线通过相机模型成为图片上…

分布式篇(分布式事务)(持续更新迭代)

一、事务 1. 什么是事务 2. 事务目的 3. 事务的流程 4. 事务四大特性 原子性&#xff08;Atomicity&#xff09; 一致性&#xff08;Consistency&#xff09; 持久性&#xff08;Durability&#xff09; 隔离性&#xff08;Isolation&#xff09; 5. MySQL VS Oracle …

云黑系统全解无后门 +搭建教程

这套系统呢是玖逸之前南逸写的一套云黑系统&#xff0c;功能带有卡密生成和添加黑名单等&#xff0c;源码放在我的网盘里已经两年之久&#xff0c;由于玖逸现在已经跑路了所以现在发出来分享给大家&#xff0c;需要的可以自己拿去而开&#xff0c;反正功能也不是很多具体的自己…

免费字体二次贩卖;刮刮乐模拟器;小报童 | 生活周刊 #4

Raycast 的两款在线工具 Raycast 公司出品&#xff0c;必属精品&#xff0c;之前的代码转图片工具&#xff0c;交互和颜值都做得很漂亮 现在又新出了一个 图标制作器&#xff0c;一键制作美观好看的图标 猫啃网 没想到像【汇文明朝体】这样免费的字体都被人拿来当成【打字机字…

C# WinForm 用名字name字符串查找子控件

工作上遇到界面控件太多&#xff0c;需要对一些控件批量处理。虽然可以用代码批量控制&#xff0c;但要么是建立数组集合把所有要处理的控件放进去循环处理&#xff0c;要么是一个一个列出来修改属性。 但我大多数要求改的控件命名上是有规律的&#xff0c;所有只需要循环拼接字…

使用 MongoDB 构建 AI:利用实时客户数据优化产品生命周期

在《使用 MongoDB 构建 AI》系列博文中&#xff0c;我们看到越来越多的企业正在利用 AI 技术优化产品研发和用户支持流程。例如&#xff0c;我们介绍了以下案例&#xff1a; Ventecon 的 AI 助手帮助产品经理生成和优化新产品规范 Cognigy 的对话式 AI 帮助企业使用任意语言&a…

卸载 Git

目录 打开 Geek找到 Git右键卸载 Git卸载完成等待扫描注册表点击完成清除Git在本地的配置文件 打开 Geek 找到 Git 右键卸载 Git 卸载完成 等待扫描注册表 点击完成 已经删除完毕 清除Git在本地的配置文件 进入 C:\Users\用户名 删除框起来的配置文件 &#x1f447; 源码资料…

【移动安全】OWASP MASTG 移动应用程序安全测试指南

OWASP 是 Open Web Application Security Project MASTG 是 Mobile Application Security Testing Guide 移动应用程序安全测试指南 英文网站&#xff1a;https://mas.owasp.org/MASTG/ 中文网站&#xff1a;http://www.owasp.org.cn/OWASP-CHINA/owasp-project/owasp-mobile-…

Docker本地镜像发布到Docker Registry私有仓库

1. 私有仓库 私有库可以部署在本地或私有云环境中&#xff0c;我们可以控制镜像的访问权限。相比公共仓库&#xff0c;私有库提供了更高的安全性和更快的访问速度。此外&#xff0c;私有库还支持自定义&#xff0c;你可以根据自己的需求来配置仓库。 私有仓库解决方案 Harbo…

递归神经网络解释(RNN)

Recurrent Neural Network (RNN) 如今,不同的机器学习技术用于处理不同类型的数据。最难处理和预测的数据类型之一是顺序数据。顺序数据与其他类型的数据不同,因为虽然可以假设典型数据集的所有特征都是与顺序无关的,但不能假设顺序数据集是无关的。为了处理这种类型的数据…

018_基于python+django荣誉证书管理系统2024_jytq9489

目录 系统展示 开发背景 代码实现 项目案例 获取源码 博主介绍&#xff1a;CodeMentor毕业设计领航者、全网关注者30W群落&#xff0c;InfoQ特邀专栏作家、技术博客领航者、InfoQ新星培育计划导师、Web开发领域杰出贡献者&#xff0c;博客领航之星、开发者头条/腾讯云/AW…