黑马React18: 基础Part II

黑马React: 基础2

Date: November 16, 2023
Sum: 受控表单绑定、获取DOM、组件通信、useEffect、Hook、优化B站评论




受控表单绑定

受控表单绑定

概念:使用React组件的状态(useState)控制表单的状态

Untitled

  1. 准备一个React状态值
const [value, setValue] = useState('')
  1. 通过value属性绑定状态,通过onChange属性绑定状态同步的函数
<input
	type="text"
	value={value}
	onChange={(e) => setValue(e.target.value)}
/>

Case:

Code:

// 受控绑定表单

import { useState } from "react"

// 1. 声明一个react状态 - useState

// 2. 核心绑定流程
  // 1. 通过value属性绑定 react 状态
  // 2. 绑定 onChange 事件 通过事件参数e拿到输入框最新的值 反向修改到react状态

function App() {
  const [value, setValue] = useState('')
  return (
    <div className="App">
      <input type="text" 
        value={value}
        onChange={(e) => setValue(e.target.value)}
      />
    </div>
  )
}

export default App

Res:

Untitled




React中获取DOM

在 React 组件中获取/操作 DOM,需要使用 useRef React Hook钩子函数,分为两步:

  1. 使用useRef创建 ref 对象,并与 JSX 绑定
const inputRef = useRef(null)
<input type="text" ref={inputRef} />
  1. 在DOM可用时,通过 inputRef.current 拿到 DOM 对象
console.log(inputRef.current)

Case:

Code:

import React, { useRef } from "react"
// React中获取DOM

// 1. useRef生成ref对象, 绑定到dom标签身上
// 2. dom可用时, ref.current获取dom对象
  // 渲染完毕之后dom生成之后可用

function App() {
  const inputRef = useRef(null)
  const showDom = () => {
    console.log(inputRef.current)
  }
  return (
    <div className="App">
      <input type="text" ref={inputRef}/>
      <button onClick={ () => showDom() }>获取DOM</button>
    </div>
  )
}

export default App

Res:

Untitled




案例:B站评论—发表评论

B站评论案例 —— 核心功能实现

Untitled

  1. 获取评论内容
  2. 点击发布按钮发布评论

Code:

  1. 获取评论内容
const [content, setContent] = useState('')

...

{/* 评论框 */}
<textarea
  className="reply-box-textarea"
  placeholder="发一条友善的评论"
  ref={inputRef}
  value={content}
  onChange={(e) => setContent(e.target.value)}
/>
  1. 点击发布按钮发布评论
const handlPublish = () => {
  setCommentList([
    ...commentList,
    {
      rpid: uuidV4(), // 随机id
      user: {
        uid: '30009257',
        avatar,
        uname: '黑马前端',
      },
      content: content,
      ctime: dayjs(new Date()).format('MM-DD hh:mm'), // 格式化 月-日 时:分
      like: 66,
    }
  ])
  // 1. 清空输入框的内容
  setContent('')
  // 2. 重新聚焦  dom(useRef) - focus
  inputRef.current.focus()
}

...

<div className="reply-box-send">
  <div className="send-text" onClick={handlPublish}>发布</div>
</div>


B站评论案例 — id处理和时间处理

Untitled

  1. rpid要求一个唯一的随机数id - uuid
  2. ctime要求以当前时间为标准,生成固定格式 - dayjs

Code:

import { v4 as uuidV4 } from 'uuid'
import dayjs from 'dayjs'

...

{
  rpid: uuidV4(), // 随机id
  user: {
    uid: '30009257',
    avatar,
    uname: '黑马前端',
  },
  content: content,
  ctime: dayjs(new Date()).format('MM-DD hh:mm'), // 格式化 月-日 时:分
  like: 66,
}

理解:

1-uuid会生成一个随机数

在component中查看:

Untitled

2-日期格式化

dayjs.format() // 具体参考以下文档

Ref:

随机数uuid: https://github.com/uuidjs/uuid

日期dayjs: https://dayjs.gitee.io/zh-CN/



B站评论案例 — 清空内容并重新聚焦

Untitled

  1. 清空内容 - 把控制input框的value状态设置为空串
  2. 重新聚焦 - 拿到input的dom元素,调用focus方法

Code:

const handlPublish = () => {
  setCommentList([
    ...commentList,
    {
      rpid: uuidV4(), // 随机id
      user: {
        uid: '30009257',
        avatar,
        uname: '黑马前端',
      },
      content: content,
      ctime: dayjs(new Date()).format('MM-DD hh:mm'), // 格式化 月-日 时:分
      like: 66,
    }
  ])
  // 1. 清空输入框的内容
  setContent('')
  // 2. 重新聚焦  dom(useRef) - focus
  inputRef.current.focus()
}

...

{/* 评论框 */}
<textarea
  className="reply-box-textarea"
  placeholder="发一条友善的评论"
  ref={inputRef} // 给评论框绑定个ref标签, 方便获取
  value={content}
  onChange={(e) => setContent(e.target.value)}
/>



组件通信

理解组件通信

概念:组件通信就是组件之间的数据传递,根据组件嵌套关系的不同,有不同的通信方法

Untitled



父传子-基础实现

Untitled

实现步骤:

  1. 父组件传递数据 - 在子组件标签上绑定属性
  2. 子组件接收数据 - 子组件通过props参数接收数据

Case:

Code:

// 父传子
// 1. 父组件传递数据 子组件标签身上绑定属性
// 2. 子组件接受数据 props的参数

function Son(props) {
  console.log(props);
  return <div>this is Son, {props.name}</div>
}

function App() {
  const name = 'this is app name'
  return (
    <div className="App">
      <Son name={name} />
    </div>
  )
}

export default App

Res:

Untitled



父传子-props说明

  1. props可传递任意的数据

数字、字符串、布尔值、数组、对象、函数、JSX

Untitled

  1. props是只读对象

子组件只能读取props中的数据,不能直接进行修改, 父组件的数据只能由父组件修改



父传子 - 特殊的prop children

场景:当我们把内容嵌套在子组件标签中时,父组件会自动在名为children的prop属性中接收该内容

Case:

Code:

// 父传子
// 1. 父组件传递数据 子组件标签身上绑定属性
// 2. 子组件接受数据 props的参数

function Son(props) {
  console.log(props);
  return <div>this is Son, {props.children}</div>
}

function App() {
  return (
    <div>
      <Son>
        <span>this is span</span>
      </Son>
    </div>
  )
}

export default App

Res:

Untitled



父子组件通信-子传父

Untitled

核心思路:在子组件中调用父组件中的函数并传递参数

Untitled

Case:

Code:

// 子传父
// 核心: 在子组件中调用父组件中的函数并传递实参

import { useState } from "react";

function Son({onGetMsg}) {
  // Son组件中的数据
  const sonMsg = 'this is son msg'
  return (
    <div>
      <button onClick={() => onGetMsg(sonMsg)}>sendMsg</button>
    </div>
  )
}

function App() {
  const [msg, setMsg] = useState('')
  const getMsg = (msg) => {
    console.log(msg);
    setMsg(msg)
  }
  return (
    <div>
      Father: { msg }
      <Son onGetMsg={getMsg}/>
    </div>
  )
}

export default App

Res:

Untitled



使用状态提升实现兄弟组件通信

实现流程:

Untitled

实现思路:借助“状态提升”机制,通过父组件进行兄弟组件之间的数据传递

  1. A组件先通过子传父的方式把数据传给父组件App
  2. App拿到数据后通过父传子的方式再传递给B组件

Case:

// 兄弟组件传递

// 1. 通过子传父 A => App ✅
// 2. 通过父传子 App => B 

import { useState } from "react";

function A({ onGetAName }) {
  const name = 'this is A name'
  return (
    <div>
      this is A component: 
      <button onClick={() => onGetAName(name)}>send</button>
    </div>
  )  
}

function B(props) {
  return (
    <div>
      this is B component: {props.name}
    </div>
  )
}

function App() {
  const [name, setName] = useState('')
  const getAName = (name) => {
    setName(name)
  }
  return (
    <div>
      <h1>Father: </h1>
      <A onGetAName={getAName} />
      <B name={name} />
    </div>
  )
}

export default App

Res:

Untitled



使用Context机制跨层级组件通信

图示:

Untitled

实现步骤

  1. 使用createContext方法创建一个上下文对象Ctx
  2. 在顶层组件(App)中通过 Ctx.Provider 组件提供数据
  3. 在底层组件(B)中通过 useContext 钩子函数获取消费数据

Untitled

Case:
Code:

// Context跨层通信
// App => A => B

// 1. createContext方法创建一个上下文对象

// 2. 在顶层组件 通过Provider组件提供数据
// 3. 在底层组件 通过useContext钩子函数使用数据

import { createContext, useContext } from "react";

const MsgContext = createContext()

function A() {
  return (
    <div>
      this is A component
      < B />
    </div>
  )
}

function B() {
  const msg = useContext(MsgContext)
  return (
    <div>
      this is B component - { msg }
    </div>
  )
}

function App() {
  const msg = 'this is app msg'
  return (
    <div>
      <MsgContext.Provider value={msg}>
        this is App
        <A />
      </MsgContext.Provider>
    </div>
  )
}

export default App

Res:

Untitled




useEffect 的使用

useEffect 的概念理解

useEffect是一个React Hook函数,用于在React组件中创建不是由事件引起而是由渲染本身引起的操作(副作用),比如发送AJAX请求,更改DOM等等

Untitled

说明:上面的组件中没有发生任何的用户事件,组件渲染完毕之后就需要和服务器要数据,整个过程属于 “只由渲染引起的操作”



useEffect 的基础使用

需求:在组件渲染完毕之后,立刻从服务端获取频道列表数据并显示到页面中

语法

useEffect(() => {}, [])

参数1是一个函数,可以把它叫做副作用函数,在函数内部可以放置要执行的操作

参数2是一个数组(可选参),在数组里放置依赖项,不同依赖项会影响第一个参数函数的执行,当是一个空数组的时候,副作用函数只会在组件渲染完毕之后执行一次

接口地址:http://geek.itheima.net/v1_0/channels

Case:
Code:

import { useEffect, useState } from "react"

const URL = 'http://geek.itheima.net/v1_0/channels'

function App() {
  // 创建一个状态数据
  const [list, setList] = useState([])
  useEffect(() => {
    // 额外的操作 获取频道列表
    async function getList() {
      const res = await fetch(URL)
      const jsonRes = await res.json()
      // console.log(list);
      setList(jsonRes.data.channels)
    }
    getList()
  }, [])
  
  return (
    <div className="App">
      {/* this is app - { list[0].name } */}
      <ul>
        { list.map(item => {
          return <li key={ item.id }>{ item.name }</li>
        })}
      </ul>
    </div>
  )
}

export default App

Res:

Untitled



useEffect 依赖项参数说明

useEffect副作用函数的执行时机存在多种情况,根据传入依赖项的不同,会有不同的执行表现

依赖项副作用函数执行时机
没有依赖项目数组初始渲染+组件更新时执行
空数组依赖只在初始渲染时执行一次
添加特定依赖项组件初始渲染 + 特性依赖项变化时执行

Case: 1. 没有依赖项

func: 点击按钮, 数字会逐渐加1

Code:

import { useEffect, useState } from "react"

function App() {
  // 1. 没有依赖项 初始 + 组件 更新
  const [count, setCount] = useState(0)
  useEffect(() => {
    console.log('副作用函数执行了');
  })
  const handleAdd = () => {
    setCount(count + 1)
  }
  return (
    <div className="App">
      this is app
      <button onClick={ () => handleAdd() }> {count} </button>
    </div>
  )
}

export default App

Res:

Untitled

Case2: 空数组依赖

Code:

import { useEffect, useState } from "react"

function App() {
  // 1. 没有依赖项 初始 + 组件 更新
  const [count, setCount] = useState(0)
  useEffect(() => {
    console.log('副作用函数执行了');
  })
  const handleAdd = () => {
    setCount(count + 1)
  }
  return (
    <div className="App">
      this is app
      <button onClick={ () => handleAdd() }> {count} </button>
    </div>
  )
}

export default App

Res:

Untitled

Case3: 添加特定依赖项

Code:

import { useEffect, useState } from "react"

function App() {
  // 3. 添加特定依赖项
  // 依赖于 count , 只要count变化, 就执行副作用函数
  const [count, setCount] = useState(0)
  useEffect(() => {
    console.log('副作用函数执行了');
  }, [count])
  const handleAdd = () => {
    setCount(count + 1)
  }
  return (
    <div className="App">
      this is app
      <button onClick={ () => handleAdd() }> {count} </button>
    </div>
  )
}

export default App

Res:

Untitled



useEffect — 清除副作用

在useEffect中编写的由渲染本身引起的对接组件外部的操作,社区也经常把它叫做副作用操作,比如在useEffect中开启了一个定时器,我们想在组件卸载时把这个定时器再清理掉,这个过程就是清理副作用

useEffect(() => {
	// 实现副作用操作逻辑
	return () => {
		// 清除副作用逻辑
		...
	}
}, [])

说明:清除副作用的函数最常见的执行时机是在组件卸载时自动执行

需求:在Son组件渲染时开启一个定制器,卸载时清除这个定时器

Case:

func: 点击卸载, 定时器会停止

Code:

import { useEffect, useState } from "react";

function Son() {
  useEffect(() => {
    const timer = setInterval(() => {
      console.log('定时器执行中...pilipala');
    }, 1000)

    return () => {
      clearInterval(timer)
    }
  }, [])
  return <div>this is son</div>
}

function App() {
  // 通过条件渲染模拟组件卸载
  const [show, setShow] = useState(true)
  return (
    <div>
      { show && <Son />}
      <button onClick={() => setShow(false)}>卸载Son组件</button>
    </div>
  )
}

export default App

Res:

Untitled




自定义Hook实现

自定义Hook函数

概念:自定义Hook是以 use 打头的函数,通过自定义Hook函数可以用来实现逻辑的封装和复用

Untitled

Case:

func: 切换 显示/隐藏 组件

Code:

// 封装自定义 Hook

// 问题: 布尔切换的逻辑 当前组件耦合在一块时, 不方便复用
// 解决思路: 自定义Hook

import { useState } from "react"

function useToggle() {
  // 可复用逻辑代码
  const [value, setValue] = useState(true)

  const handleToggle = () => {
    setValue(false)
  }
 
  // 哪些状态和回调函数需要在其他组件中使用 return
  return {
    value, 
    handleToggle
  }
}

// 封装自定义hook通用思路
// 1. 声明一个以use打头的函数
// 2. 在函数体内封装可复用的逻辑 (只要是可复用的逻辑)
// 3. 把组件中用到的状态或者回调returan出去(以对象或者数组)
// 4. 在哪个组件中要用到这个逻辑, 就调用这个自定义hook, 结构出来状态和回调进行使用

function App() {
  const { value, handleToggle } = useToggle()

  return (
    <div className="App">
      { value && <div>this is div</div>}
      <button onClick={() => handleToggle()}>toggle</button>
    </div>
  )
}

export default App

Res:

Untitled




React Hooks使用规则

使用规则:

  1. 只能在组件中或者其他自定义Hook函数中调用

  2. 只能在组件的顶层调用,不能嵌套在 if、for、其他函数中

    理解: 就是Hooks不能有条件地执行, 只能直接在顶部采用const { value, handleToggle } = useToggle() 这种方式, 直接调用

Untitled




案例:优化B站评论案例

优化需求

Untitled

  1. 使用请求接口的方式获取评论列表并渲染
  2. 使用自定义Hook函数封装数据请求的逻辑
  3. 把评论中的每一项抽象成一个独立的组件实现渲染


优化需求-通过接口获取评论列表

  1. 使用 json-server 工具模拟接口服务, 通过 axios 发送接口请求

    json-server是一个快速以.json文件作为数据源模拟接口服务的工具
    axios是一个广泛使用的前端请求库

# -D 指安装到开发时依赖
npm i json-server -D
  1. 使用 useEffect 调用接口获取数据
useEffect(() => {
	// 发送网络请求
	...
}, [])

拓展:

json-server

使用步骤:

1-安装(参考视频)

2-配置 package.json

"scripts": {
  "start": "react-scripts start",
  "build": "react-scripts build",
  "test": "react-scripts test",
  "eject": "react-scripts eject",
  "serve": "json-server db.json --port 3004" // 添加 json-server 的端口
},

参考:

json-server: https://github.com/typicode/json-server



优化需求-自定义Hook函数封装数据请求

一般思路:

  1. 编写一个 use 打头的函数
  2. 函数内部编写封装的逻辑
  3. return出去组件中用到的状态和方法
  4. 组件中调用函数解构赋值使用
function useGetList () {
  // 获取接口数据渲染
  const [commentList, setCommentList] = useState([])

  useEffect(() => {
    // 请求数据
    async function getList () {
      // axios请求数据
      const res = await axios.get(' http://localhost:3004/list')
      setCommentList(res.data)
    }
    getList()
  }, [])

  return {
    commentList,
    setCommentList
  }
}

...

const [commetList, setCommetList] = useGetList()


优化需求-封装评论项Item组件

Untitled

抽象原则:App作为“智能组件”负责数据的获取,Item作为“UI组件”负责数据的渲染

// 封装Item组件
function Item ({ item, onDel }) {
  return (
    <div className="reply-item">
      {/* 头像 */}
      <div className="root-reply-avatar">
        <div className="bili-avatar">
          <img
            className="bili-avatar-img"
            alt=""
            src={item.user.avatar}
          />
        </div>
      </div>

      <div className="content-wrap">
        {/* 用户名 */}
        <div className="user-info">
          <div className="user-name">{item.user.uname}</div>
        </div>
        {/* 评论内容 */}
        <div className="root-reply">
          <span className="reply-content">{item.content}</span>
          <div className="reply-info">
            {/* 评论时间 */}
            <span className="reply-time">{item.ctime}</span>
            {/* 评论数量 */}
            <span className="reply-time">点赞数:{item.like}</span>
            {/* 条件:user.id === item.user.id */}
            {user.uid === item.user.uid &&
              <span className="delete-btn" onClick={() => onDel(item.rpid)}>
                删除
              </span>}
          </div>
        </div>
      </div>
    </div>
  )
}

{/* 评论列表 */}
<div className="reply-list">
  {/* 评论项 */}
  {commetList.map(item => <Item key={item.rpid} item={item} onDel={() => handleDel(item.rpid)}/>)}
</div>

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

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

相关文章

YOLOV5 C++部署的人员检测项目【学习笔记(十一)】

本文为修改后的转载&#xff0c;没有转载链接&#xff0c;所以文章类型暂为原创 文章目录 一、安装Pytorch 及 YOLO v51.1 安装GPU版 pytorch1.2 安装YOLO v5所需依赖 二、YOLO v5训练自定义数据2.1 标注数据2.1.1 安装labelImg2.1.2 标注 2.2 准备数据集2.2.1 组织目录结构2.…

dvwa-command injection 代码审计(超详细逐行审计)

dvwa-command injection 代码审计 low <?phpif( isset( $_POST[ Submit ] ) ) {// Get input$target $_REQUEST[ ip ];// Determine OS and execute the ping command.if( stristr( php_uname( s ), Windows NT ) ) {// Windows$cmd shell_exec( ping . $target );}…

姓氏情侣家庭亲子谐音顽梗头像分销流量主微信抖音小程序开发

姓氏情侣家庭亲子谐音顽梗头像分销流量主微信抖音小程序开发 姓氏情侣头像&#xff1a;提供各种姓氏的情侣头像模板&#xff0c;用户可根据自己的姓氏选择合适的头像进行定制。 家庭头像&#xff1a;为家庭成员提供多种形式的头像模板&#xff0c;让用户可以选择合适的家庭头像…

使用Arrays.asList与不使用的区别

在写算法的时候&#xff0c;遇到了有的题解使用的是Arrays.asList&#xff0c;也有的是直接新建一个List集合将元素加进去的。 看了一下算法的时间&#xff0c;两者居然相差了9秒。 算法原地址&#xff1a; 力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长…

虾皮选品免费工具:如何用知虾进行虾皮市场分析选品

在如今的电商时代&#xff0c;了解市场需求和选择热销产品是成功经营的关键。虾皮作为东南亚地区最大的电商平台之一&#xff0c;提供了一系列的选品工具&#xff0c;帮助卖家在市场竞争中脱颖而出。本文将介绍如何使用虾皮的免费工具——知虾进行虾皮市场分析选品&#xff0c;…

Google Chrome 任意文件读取 (CVE-2023-4357)漏洞

漏洞描述 该漏洞的存在是由于 Google Chrome 中用户提供的 XML 输入验证不足。远程攻击者可以创建特制网页&#xff0c;诱骗受害者访问该网页并获取用户系统上的敏感信息。远程攻击者可利用该漏洞通过构建的 HTML 页面绕过文件访问限制&#xff0c;导致chrome任意文件读取。Li…

捷诚管理信息系统 SQL注入漏洞复现

0x01 产品简介 捷诚管理信息系统是一款功能全面&#xff0c;可以支持自营、联营到外柜租赁的管理&#xff0c;其自身带工作流管理工具&#xff0c;能够帮助企业有效的开展内部审批工作。 0x02 漏洞概述 捷诚管理信息系统CWSFinanceCommon.asmx接口存在SQL注入漏洞。未经身份认…

<C++> 模板-下

目录 前言 一、非类型模板参数 二、类模板的特化 1. 概念 2. 函数模板特化 3. 类模板特化 4. 全特化 5. 偏特化 5.1 特化部分参数 5.2 对某些类型的进一步限制 三、模板的分离编译 1. 概念 2. 分离编译 3. 解决方法 1. 显式实例化 2. 在一个文件内写声明和定义 四、模板总结 …

基于nodejs学校宿舍管理系统-计算机毕设 附源码45118

nodejs学校宿舍管理系统 摘要 信息化社会内需要与之针对性的信息获取途径&#xff0c;但是途径的扩展基本上为人们所努力的方向&#xff0c;由于站在的角度存在偏差&#xff0c;人们经常能够获得不同类型信息&#xff0c;这也是技术最为难以攻克的课题。针对学校宿舍管理系统等…

Java_异常详解

前言 异常是什么,异常如何抛出,如何抛出自定义异常,异常处理主要的五个关键字&#xff1a;throw,try,catch,finally,throws ,异常的处理流程 异常是什么 在Java中&#xff0c;将程序执行过程中发生的不正常行为称为异常。比如之前写代码时经常遇到的&#xff1a; 1. 算数异…

PySide6 Tutorials (一)表格小部件魔改

前言 Pyside6官方教程给了一个使用表格显示颜色的教程&#xff0c;原教程地址如下&#xff1a;源地址&#xff0c; 结合前面button信号的学习&#xff0c;就魔改添加了如下功能&#xff1a;增加一列按钮&#xff0c;可以修改该行的颜色值&#xff0c;通过点击按钮生成指定的颜…

口袋参谋:找关键词的三种方法!

​如何找热搜关键词&#xff1f;99%的商家都不知道。那么今天可以根据我说的三种方法去做。 第一种方法&#xff1a;利用竞争对手 通过分析竞争对手&#xff0c;正在使用和采取何种优化方法&#xff0c;来帮助你理解市场上正在流行什么样的关键字&#xff0c;这些热词可以直接从…

uniapp中swiper 轮播带左右箭头,点击切换轮播效果demo(整理)

可以点击箭头左右切换-进行轮播 <template><view class"swiper-container"><swiper class"swiper" :current"currentIndex" :autoplay"true" interval"9000" circular indicator-dotschange"handleSw…

golang指针学习

package mainimport "fmt"func main() {name:"飞雪无情"nameP:&name//取地址fmt.Println("name变量的内存地址为:",&name)fmt.Println("name变量的值为:",name)fmt.Println("name变量的内存地址为:",nameP)fmt.Prin…

中大型企业网搭建(毕设类型)

毕业设计类别 某大学网络规划与部署 目录 某大学网络规划与部署 第一章项目概述 1.1 项目背景 1.2 网络需求分析 第二章网络总体设计方案 2.1 网络整体架构 2.2 网络设计思路 第三章 网络技术应用 3.1 DHCP 3.2 MSTP 3.3 VRRP 3.4 OSPF 3.5 VLAN 3.6 NAT 3.7 WLAN 3…

完美解决:yum -y install nginx 报出 没有可用软件包 nginx。错误:无须任何处理

目录 一、问题&#xff1a; 二、原因&#xff1a; 三、解决方法&#xff1a; 一、问题&#xff1a; [rootlocalhost ~]# yum -y install nginx 已加载插件&#xff1a;fastestmirror Loading mirror speeds from cached hostfile * base: mirrors.bfsu.edu.cn * extras: m…

纽扣电池/含纽扣电池产品上架亚马逊各国法规标准要求16 CFR 第 1700.15/20 ANSI C18.3M(瑞西法案认证)

亚马逊纽扣电池认证标准有哪些&#xff1f; 一、美国站&#xff08;亚马逊纽扣电池/含纽扣电池商品&#xff09;安全测试标准要求&#xff1a; 16 CFR 第 1700.15 、16 CFR 第 1700.20 ANSI C18.3M、警示标签声明要求&#xff08;第 117-171 号公众法&#xff09; 二、澳大…

SQL的连接join

一、连接说明 union、intersect等集合运算&#xff0c;它的特征是以 “行” 为单位进行操作&#xff0c;通俗点说&#xff0c;就是进行这些集合运算&#xff0c;会导致记录行数的增减&#xff0c;使用union会增加记录行数&#xff0c;使用 intersect 或 expect 会减少行记录&a…

java中,通过替换word模板中的关键字后输出一个新文档

一、要用到的jar包 我已上传了相关的jar包&#xff0c;需要的可以通过以下链接直接下载&#xff1a; https://download.csdn.net/download/qq_27387133/88558034 具体jar包截图&#xff1a; 二、实现的代码 注意&#xff1a;文件要用docx格式!!! word变量替换的方法&#…

模板初阶学习

✨前言✨ &#x1f4d8; 博客主页&#xff1a;to Keep博客主页 &#x1f646;欢迎关注&#xff0c;&#x1f44d;点赞&#xff0c;&#x1f4dd;留言评论 ⏳首发时间&#xff1a;2023年11月21日 &#x1f4e8; 博主码云地址&#xff1a;博主码云地址 &#x1f4d5;参考书籍&…