React-组件使用与组件通信

生命周期补充(不常用):

案例:


import React, { Component } from 'react'

export default class App extends Component {
  state = {
    num : 100,
    list: []
  }
  //获取到的是更新前的props 和 state 
  getSnapshotBeforeUpdate(prevProps,prevState){  //必须搭配componentDidUpdate 生命周期使用
    console.log(prevState);
    // 返回值 快照
    const heigth = document.getElementById('content').clientHeight

    console.log([document.getElementById('content')]);
    return heigth
  }
  // prev 之前的旧的数据  snapshot就是 getSnapshotBeforeUpdate 的return返回值
  componentDidUpdate(prevProps, prevState, snapshot){
    console.log('更新前的列表高度:',snapshot);
  }
  render() {
    return (
      <div>App
        <button onClick={() => this.setState({num:this.state.num +1})}> {this.state.num}</button>
        <div id='content'>
          {this.state.list.map((item,index) => (
            <div key={index}>{item}</div>
          ))}
        </div>
        <button onClick={this.add}> 添加</button>
      </div>
    )
  }
  add = () => {
    const time = new Date().getTime()
    this.setState({list: [...this.state.list,time]})
  }
}

一、组件

1.特别说明

有以下示例代码:

import React, { Component } from "react";
// 编辑功能的案例
class App extends Component {
   state = {
       msg: "hello world",
  };
   render() {
       return (
           <div>
               <input type="text" value={this.state.msg} />
           </div>
      );
  }
}

export default App;

通过运行后我们可以在浏览器的consle控制台找到React给予我们的提示:

Warning: You provided a value prop to a form field without an onChange handler. This will render a read-only field. If the field should be mutable use defaultValue. Otherwise, set either onChange or readOnly.

通过上述的警告提示,我们可以得知,在React中并不存在类似于Vue的双向数据绑定操作。此处需要注意以下几点:

  • Vue中的v-model是语法糖

  • 在React里使用的是单向数据流(vue中是双向绑定)

由于在React里数据流是单向的,所以我们就必须得考虑一个问题:怎么获取用户在表单中输入的数据呢?解决办法:

  • 给表单项添加onChange事件,通过事件处理实现双向绑定效果【受控组件】

  • 给表单项的value/checked,设置成defaultValue/defaultChecked,结合ref对象实现双向效果【非受控组件】

React推荐我们使用受控组件。

2.受控组件

state与表单项中的value值绑定在一起,由state的值来控制(onChange事件)表单元素的值,称为受控组件。

绑定步骤:

  • 在state中添加一个状态,作为表单元素的value值

  • 给表单元素绑定change事件,将表单元素的值设置为state的值

案例:


import React, { Component } from 'react'

// 受控组件
// 通过 state 控制组件的状态
// 1.生命一个state 
// 2.将 state绑定到表单的value值, 根据 onChange 事件修改state里面的参数
// 3.最终获取表单数据 直接使用state里的状态参数即可
export default class App extends Component {
  state = {
    name: '',
    password: '',
  }
  render() {
    const {name, password} = this.state
    return (
      <div>
        <input type="text" placeholder='用户名' value={name} onChange={(e)=> this.setState({name: e.target.value})}/>
        <input type="password" placeholder='密码' value= { password} onChange={(e)=> this.setState({password: e.target.value})}/>
        <button onClick={this.submit}>提交</button>
      </div>
    )
  }
  submit = () => {
    console.log(this.state);
  }
}
3.非受控组件

没有和state数据源进行关联的表单项,而是借助ref,使用元素DOM方式获取表单元素值

使用步骤

  • 调用React.createRef()方法创建ref对象

  • 将创建好的ref对象添加到文本框中

  • 通过ref对象获取到文本框的值

提示:一般表单项少的时候可以考虑使用非受控组件。

案例:


import React, { Component, createRef } from "react";

// 非受控组件
// ref 属性绑定  绑定子组件获取到的就是组件实例   绑定的是标签获取到的就是DOM元素
// 1. 导入createRef 方法
// 2. 生成一个ref属性
// 3. 将属性绑定给标签
// 4. this.ref属性.current 获取到绑定的组件实例或者DOM对象

export default class App extends Component {
  nameRef = createRef();
  passwarodRef = createRef();
  render() {
    return (
      <div>
        <input type="text" placeholder="用户名" ref={this.nameRef} />
        <input type="password" placeholder="密码" ref={this.passwarodRef} />
        <button onClick={this.submit}>提交</button>
      </div>
    );
  }
  submit = () => {
    console.log(this.nameRef);
    console.log(this.passwarodRef);
    // 基础语法
    console.log({ name: this.nameRef.current.value, password : this.passwarodRef.current.value });
    //  替代语法
    const uname = this.nameRef.current.value
    const uPassword = this.passwarodRef.current.value
    console.log({uname,uPassword});
  };
}
表单登录案例:
1.fetch登录:

/***
 *   非受控组件
 *   ref属性绑定  绑定子组件获取到的就是组件实例 绑定的是标签获取到的就是DOM对象
 *   1、导入createRef方法
 *   2、生成一个ref属性
 *   3、将属性绑定给标签
 *   4、this.ref属性.current 获取到绑定的组件实例或者DOM对象
 *
 */
import React, { Component, createRef } from 'react'
export default class App extends Component {
  unameRef = createRef()
  upassRef = createRef()
  render() {
    return (
      <div>
        <input type="text" placeholder="用户名" ref={this.unameRef} />
        <input type="password" placeholder="密码" ref={this.upassRef} />
        <button onClick={this.submit}>提交</button>
      </div>
    )
  }
  submit = () => {
    // console.log(this.unameRef)
    // console.log(this.upassRef)
    const uname = this.unameRef.current.value
    const upass = this.upassRef.current.value
    const url = 'http://127.0.0.1:5000/api/v1/login'
    fetch(url, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ username: uname, password: upass })
    })
      .then((res) => res.json())
      .then((res) => {
        console.log(res)
        if (res.code === 0) {
          alert('登录成功')
        } else {
          alert('登录失败')
        }
      })
  }
}
2.rcc组件登录流程

import React, { Component, createRef } from 'react'
import { Form, Input, Button, Toast } from 'antd-mobile'
import axios from 'axios'
export default class App extends Component {
  onFinish = (values) => {
    console.log(values)
    const url = 'http://127.0.0.1:5000/api/v1/login'
    axios.post(url, values).then((res) => {
      console.log(res)
      if (res.data.code === 0) {
        Toast.show({
          icon: 'success',
          content: '登录成功'
        })
      } else {
        Toast.show({
          icon: 'fail',
          content: '登录失败',
          duration:1500,
          afterClose: () => {
            //  window.location.reload()
            // 通过ref属性绑定组件实例 获取到组件的实例 并使用其组件实例方法清空表单字段内容
            this.formRef.current.setFieldsValue({ username: '', password: '' })
          }
        })
      }
    })
  }
  formRef = createRef()
  render() {
    return (
      <div>
        <Form
          ref={this.formRef}
          onFinish={this.onFinish}
          layout="horizontal"
          mode="card"
          footer={
            <Button block type="submit" color="primary" size="large">
              提交
            </Button>
          }
        >
          <Form.Item name="username" label="用户名">
            <Input placeholder="例如:admin" />
          </Form.Item>
          <Form.Item name="password" label="密码">
            <Input placeholder="例如:admin123" type="password" />
          </Form.Item>
        </Form>
      </div>
    )
  }
}

二、组件通信

1.父传子

该传值的实现可以分为两种,思想大致如下:

  • 父通过ref标记子组件,通过ref获取子组件实例对象,父将自己的状态或数据以实参形式传递给子组件中预设的方法,在子组件中的预设方法以形参形式接收父组件传递来的数据,并保存到子组件自身的状态

  • 在父组件中定义一个获取父组件自身状态或数据的方法,将该方法以props属性的形式传递给子组件,子组件收到后执行该方法即可获取到父组件的状态或数据

案例:

父组件


import React, { Component ,createRef} from 'react'
import Child from './components/Child'

/**
 * 父传子
 * 1.props
 * 2.children 这个类似于props
 * 3.父组件定义一个方法 传递给子组件 子组件调用  父组件方法通过返回值传递到子组件(通过props直接调用方法)
 * 4.子组件定义一个方法  父组件调用  传递参数给子组件  实现父传子
 */
export default class App extends Component {
  state= {
    msg: '父组件的值20'
  }
  childRef = createRef()
  sendData = () => {
    return this.state.msg
  }
  componentDidMount(){
    this.childRef.current.getData({num:250})
  }
  render() {
    return (
      <div>
        父组件
        <Child ref= {this.childRef} msg={this.state.msg} sendData= {this.sendData}> {this.state.msg}</Child>
      </div>
    )
  }
}

子组件


import React, { Component } from 'react'

export default class Child extends Component {
    getData = (data) => {
        console.log(data);
    }
  render() {
    // console.log(this.props);
    // console.log(this.props.sendData());
    return (
      <div>Child</div>
    )
  }
}
2.子传父

该传值的实现可以分为两种,思想大致如下:

  • (父主动获取子的数据)父通过ref标记子组件,随后通过子组件实例对象获取子组件的数据

  • 在父组件中预埋一个修改父组件自身的方法,将该方法以props的形式传递给子组件,子组件收到方法时去调用,并且将自己需要给父的数据以实参的形式给这个方法

案例:

父组件


import React, { Component, createRef } from 'react'
import Child1 from './components/Child1'

/**
 * 子传父
 * 1.ref
 * 2.父组件定义方法 子组件调用 通过参数传递的方式 实现子传父
 * 3.子组件定义方法  父组件调用  通过返回值 传递参数  实现父传子
 */
export default class App extends Component {
  getData = (data) => {
    console.log(data);
  }
  componentDidMount(){
    // console.log(this.Child1Ref.current.state);
    
    console.log(this.Child1Ref.current.sendData());
  }
  
  Child1Ref= createRef()
  render() {
    return (
      <div>
        <Child1 ref={this.Child1Ref} getData={this.getData}></Child1>
      </div>
    )
  }
}

子组件


import React, { Component } from "react";

export default class Child1 extends Component {
  state = {
    msg: "我是子组件",
  };
  componentDidMount() {
    this.props.getData(this.state);
  }
  sendData = () => {
    return this.state;
  };
  render() {
    return <div>Child1</div>;
  }
}
3.跨组件传值

在react没有类似vue中的事件总线来解决这个问题。在实际的项目中,当需要组件间跨级访问信息时,如果还使用组件层层传递props,此时代码显得不那么优雅,甚至有些冗余。在react中,我们还可以使用context来实现跨级父子组件间的通信


import React, { Component, createContext } from "react"

const {
Provider,
Consumer
} = createContext()

提示:在React的context中,数据被看成了商品,发布数据的组件会用provider身份,接收数据的组件使用consumer身份。

 

  • 创建Context对象

当React渲染一个订阅了这个Context对象的组件,这个组件会从组件树中离自身最近的那个匹配的Provider中读取到当前的context值。


// 定义全局context
// 由于这个操作后期可能被复用,建议独立文件去创建。此处以`src/Context/index.js`为例
import { createContext } from "react"

export default createContext()
  • 发布消息 

在App.jsx组件中发布消息,这样所有的组件都可以消费它的消息。


import React, { Component } from "react";
import Cmp1 from "./Components/Cmp1";
import Cmp2 from "./Components/Cmp2";
// 导入context对象
import ContextObj from "./Context/index";
let { Provider } = context;


class App extends Component {
   state = {
       count: 12345,
  };

   render() {
       return (
           <div>
               <Provider value={this.state.count}>
                   <Cmp6></Cmp6>
                   <Cmp7></Cmp7>
               </Provider>
           </div>
      );
  }
}

export default App;
  • 组件消费

在子组件中通过Api完成消费动作,从而实现消息通信。消费的方式有2种:

方式1:通过组件消费


import React, { Component } from "react";

import ContextObj from "../Context/index";
let { Consumer } = ContextObj;

class Cmp1 extends Component {
   render() {
       return (
           <div>
               <Consumer>
                  {(value) => {
                       return <div>获取到的值是:{value}</div>;
                  }}
               </Consumer>
           </div>
      );
  }
}

export default Cmp1;

方式2:通过绑定静成属性来消费

import React, { Component } from "react";
import ContextObj from "../Context/index";

class Cmp2 extends Component {
   static contextType = ContextObj;
   render() {
       return <div>{this.context}</div>;
  }
}

export default Cmp2;

案例:

import React, { Component, createContext } from "react";
/**
 * context  跨层级传参
 * 1.导入createContext
 * 2.生成一个context
 * 3.使用 provider 进行数据的发布
 * 4.使用 Consumer 接收传递的参数  或者 static 方式 接收传递的参数()
 */

const context = createContext();
const Provider = context.Provider; // 写法二
// const Consumer = context.Consumer;
// 爷爷组件
export default class App extends Component {
  state = {
    money: 100,
  };
  render() {
    return (
      <div>
        {/* 写法一 */}
        {/* <context.Provider> 
          <Father money={this.state.money}></Father>
        </context.Provider> */}
        {/* 写法二 */}
        <Provider value={this.state.money}>
          <Father></Father>
        </Provider>
      </div>
    );
  }
}

// 爸爸组件
class Father extends Component {
  render() {
    return (
      <div>
        <Child></Child>
      </div>
    );
  }
}

// 儿子或孙子
class Child extends Component {
  static contextType = context;
  render() {
    return (
      <div>
        {/* 写法一 */}
        {/* <Consumer>{(value) => <div>Child 爷爷给了{value}元</div>}</Consumer> */} 
        {/* 写法二 */}
        爷爷给了{this.context}元
      </div>
    );
  }
}

使用 Context 之前的考虑

Context 主要应用场景在于很多不同层级的组件需要访问同样一些的数据。请谨慎使用,因为这会使得组件的复用性变差。

如果你只是想避免层层传递一些属性,组件组合(component composition)有时候是一个比 context 更好的解决方案。

比如,考虑这样一个 Page 组件,它层层向下传递 user 和 avatarSize 属性,从而让深度嵌套的 Link 和 Avatar 组件可以读取到这些属性:

<Page user={user} avatarSize={avatarSize} />
// ... 渲染出 ...
<PageLayout user={user} avatarSize={avatarSize} />
// ... 渲染出 ...
<NavigationBar user={user} avatarSize={avatarSize} />
// ... 渲染出 ...
<Link href={user.permalink}>
  <Avatar user={user} size={avatarSize} />
</Link>

如果在最后只有 Avatar 组件真的需要 user 和 avatarSize,那么层层传递这两个 props 就显得非常冗余。而且一旦 Avatar 组件需要更多从来自顶层组件的 props,你还得在中间层级一个一个加上去,这将会变得非常麻烦。

一种 无需 context 的解决方案是将 Avatar 组件自身传递下去,因为中间组件无需知道 user 或者 avatarSize 等 props:

function Page(props) {
  const user = props.user;
  const userLink = (
    <Link href={user.permalink}>
      <Avatar user={user} size={props.avatarSize} />
    </Link>
  );
  return <PageLayout userLink={userLink} />;
}

// 现在,我们有这样的组件:
<Page user={user} avatarSize={avatarSize} />
// ... 渲染出 ...
<PageLayout userLink={...} />
// ... 渲染出 ...
<NavigationBar userLink={...} />
// ... 渲染出 ...
{props.userLink}

这种变化下,只有最顶部的 Page 组件需要知道 Link 和 Avatar 组件是如何使用 user 和 avatarSize 的。

这种对组件的控制反转减少了在你的应用中要传递的 props 数量,这在很多场景下会使得你的代码更加干净,使你对根组件有更多的把控。但是,这并不适用于每一个场景:这种将逻辑提升到组件树的更高层次来处理,会使得这些高层组件变得更复杂,并且会强行将低层组件适应这样的形式,这可能不会是你想要的。

而且你的组件并不限制于接收单个子组件。你可能会传递多个子组件,甚至会为这些子组件(children)封装多个单独的“接口(slots)”,正如这里的文档所列举的

function Page(props) {
  const user = props.user;
  const content = <Feed user={user} />;
  const topBar = (
    <NavigationBar>
      <Link href={user.permalink}>
        <Avatar user={user} size={props.avatarSize} />
      </Link>
    </NavigationBar>
  );
  return (
    <PageLayout
      topBar={topBar}
      content={content}
    />
  );
}

这种模式足够覆盖很多场景了,在这些场景下你需要将子组件和直接关联的父组件解耦。如果子组件需要在渲染前和父组件进行一些交流,你可以进一步使用 render props。

但是,有的时候在组件树中很多不同层级的组件需要访问同样的一批数据。Context 能让你将这些数据向组件树下所有的组件进行“广播”,所有的组件都能访问到这些数据,也能访问到后续的数据更新。使用 context 的通用的场景包括管理当前的 locale,theme,或者一些缓存数据,这比替代方案要简单的多。

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

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

相关文章

红队打靶练习:DERPNSTINK: 1

目录 信息收集 1、arp 2、netdiscover 3、nmap 4、nikto 5、whatweb 目录探测 1、gobuster 2、dirsearch WEB get flag1 robots.txt /php/phpmyadmin /temporary /weblog wordpress wpscan扫描 漏洞发现 提权 系统信息收集 mysql登录 john get flag2 s…

Orchestrator源码解读2-故障失败发现

目录 目录 前言 核心流程函数调用路径 GetReplicationAnalysis 故障类型和对应的处理函数 拓扑结构警告类型 与MHA相比 前言 Orchestrator另外一个重要的功能是监控集群&#xff0c;发现故障。根据从复制拓扑本身获得的信息&#xff0c;它可以识别各种故障场景。Orchest…

Vue2.v-指令

v-if 在双引号中写判断条件。 <div v-if"score>90">A</div> <div v-else-if"score>80">B</div> <div v-else>C</div>v-on: :冒号后面跟着事件。 为了简化&#xff0c;可以直接用代替v-on:。 事件名“内联语…

【前端素材】同城服务分类手机APP页面的设计实现

一、需求分析 一个同城服务分类手机页面是一个用于提供同城服务分类信息的移动设备页面。它通常具有以下功能&#xff1a; 地理定位&#xff1a;同城服务分类手机页面可以利用用户的地理定位功能&#xff0c;获取用户当前所在的城市或地区信息&#xff0c;以便提供与用户所在地…

一、Mybatis 简介

本章概要 简介持久层框架对比快速入门&#xff08;基于Mybatis3方式&#xff09; 1.1 简介 https://mybatis.org/mybatis-3/zh/index.html MyBatis最初是Apache的一个开源项目iBatis, 2010年6月这个项目由Apache Software Foundation迁移到了Google Code。随着开发团队转投G…

12、DolphinScheduler

1、DolphinScheduler简介 1.1、 DolphinScheduler概述 Apache DolphinScheduler是一个分布式、易扩展的可视化DAG工作流任务调度平台。致力于解决数据处理流程中错综复杂的依赖关系&#xff0c;使调度系统在数据处理流程中开箱即用。 1.2、 DolphinScheduler核心架构 Dolph…

UV贴图和展开初学者指南

在线工具推荐&#xff1a; 3D数字孪生场景编辑器 - GLTF/GLB材质纹理编辑器 - 3D模型在线转换 - Three.js AI自动纹理开发包 - YOLO 虚幻合成数据生成器 - 三维模型预览图生成器 - 3D模型语义搜索引擎 介绍 这正是本文的主题——UV贴图——登上舞台的时候。大多数 3D 建…

基于YOLOv8 + BotSORT实现球员和足球检测与跟踪 (步骤 + 源码)

导 读 本文主要介绍基于YOLOv8和BotSORT实现球员和足球检测与跟踪 &#xff0c;并给出步骤和代码。 背景介绍 本文旨在了解 YOLO 架构并在自定义数据集上对其进行训练&#xff0c;然后微调模型以获得更好的结果&#xff0c;并运行推理以了解最有效的方法。 什么是YOLO&#x…

练习-指针笔试题

目录 前言一、一维整型数组1.1 题目一1.2 题目二 二、二维整型数组2.1 题目一2.2 题目二2.3 题目三 三、结构体3.1 题目一&#xff08;32位机器运行&#xff09; 四、字符数组4.1 题目一4.2 题目二 总结 前言 本篇文章记录关于C语言指针笔试题的介绍。 一、一维整型数组 1.1 …

探索人工智能:深度学习、人工智能安全和人工智能

深度学习是人工智能的一种重要技术&#xff0c;它模拟了人类大脑神经网络的工作原理&#xff0c;通过建立多层次的神经元网络来实现对数据的分析和处理。这种技术的引入使得人工智能的发展进入到了一个新的阶段。 现如今&#xff0c;深度学习在各个领域都有着广泛的应用。例如…

简单的MOV转MP4方法

1.下载腾讯的QQ影音播放器, 此播放器为绿色视频播放器, 除了播放下载好的视频外没有臃肿无用功能 官网 QQ影音 百度网盘链接&#xff1a;https://pan.baidu.com/s/1G0kSC-844FtRfqGnIoMALA 提取码&#xff1a;dh4w 2.用QQ影音打开MOV文件 3.右下角打开影音工具箱 , 选择截取…

开启Android学习之旅-6-实战答题App

不经过实战&#xff0c;看再多理论&#xff0c;都是只放在笔记里&#xff0c;活学活用才是硬道理。同时开发应用需要循序渐进&#xff0c;一口气规划300个功能&#xff0c;400张表&#xff0c;会严重打击自己的自信。这里根据所学的&#xff0c;开发一个答题App。 题库需求分析…

公司新买的BI,和金蝶系统配合太默契了

公司一直都用金蝶系统来实现包括财务管理、供应链管理、人力资源管理等多个方面的资源的合理配置和业务流程的自动化。但到了数据分析这块&#xff0c;金蝶系统就明显力不从心&#xff0c;需要一个专业的数据分析工具来接手。财务经理推荐用奥威BI&#xff0c;说这款BI的一大特…

光纤知识总结

1光纤概念&#xff1a; 光导纤维&#xff08;英语&#xff1a;Optical fiber&#xff09;&#xff0c;简称光纤&#xff0c;是一种由玻璃或塑料制成的纤维&#xff0c;利用光在这些纤维中以全内反射原理传输的光传导工具。 微细的光纤封装在塑料护套中&#xff0c;使得它能够…

OpenAI ChatGPT-4开发笔记2024-01:开发环境

ChatGPT发展一日千里。工具、函数少则数日&#xff0c;多则数月就加入了Deprecated行列不再如预期般工作。元旦闲来无事&#xff0c;用最新的ChatGPT重写一下各种开发场景&#xff0c;全部实测通过。 开发环境&#xff1a; 电脑&#xff1a;两台笔记本&#xff1a;HP和MacBoo…

Pixi.js的魅力

摘要&#xff1a;官网 Web开发的时代&#xff0c;图形和动画已经成为了吸引用户注意力的重要手段之一。而 Pixi.js 作为一款高效、易用的2D渲染引擎&#xff0c;已经成为了许多开发者的首选~~ 项目中&#xff0c;有一些图像的处理操作&#xff08;3D图&#xff0c;2D图都有&…

49寸OLED拼接屏:技术、应用与市场前景

作为“49寸OLED拼接屏”技术总监&#xff0c;我深知这一产品对于显示行业的重要性。随着显示技术的不断进步&#xff0c;OLED拼接屏在高端显示市场占据了一席之地。下面&#xff0c;我将从技术的角度深入剖析这一产品。 一、参数 49寸OLED拼接屏是一款高端大屏显示产品&#x…

在线文本转语音工具的实现

文章目录 文章最下面有工具链接&#xff01;前言edge-tts库1.首先使用pip安装这个库2.写一段示例代码3.多线程 pydub库1.介绍2.示例 将他们整合起来我把他们部署到了我的服务器上&#xff0c;可以在线使用点我使用工具 文章最下面有工具链接&#xff01; 前言 最近有文字转语…

Halcon3D篇-3D预处理,滤波,点云筛选

前言 由于3D相机采集到的数据通常通过Tiff格式的深度图进行显示或者保存。 深度图与模型的互转可以访问另一篇博客&#xff1a;https://blog.csdn.net/m0_51559565/article/details/135362674 关于3D相机的数据采集&#xff0c;可以访问我们另一篇关于LMI3D相机SDK的二次开发…

Redis主从复制哨兵及集群

目录 一.主从复制 主从复制的工作原理如下&#xff1a; 主从复制的作用&#xff1a; 搭建Redis 主从复制 每台服务器配置&#xff1a; ​编辑进行编译安装&#xff1a; 定义systemd服务管理脚本&#xff1a; 开启服务&#xff0c;报错看下内容&#xff1a; 修改 Redis…