通过继承React.Component创建React组件-5

news2024/11/6 0:30:21

在React中,V16版本之前有三种方式创建组件(createClass() 被删除了),之后只有两种方式创建组件。这两种方式的组件创建方式效果基本相同,但还是有一些区别,这两种方法在体如下:
在这里插入图片描述

本节先了解下用extnds React.Component 的方式创建React组件。

通过继承React.Component创建React组件

以下是一个简单的模板实现:

<script type="text/babel">
   //组件名称要用大写字母开头,因为React在渲染时会区分大小写。
   class Suggest extends React.Component { //自定义组件
   
   		static defaultProps ={//定义组件参数默认值
            color: 'blue',
            text: 'Confirm',
        }; //state是一个属性,所以要写分号结尾
        
       constructor(props) { //定义构造函数,不需要写function关键字
           super(props); //必须要先调用父类的构造函数,否则无法使用this关键字
           this.state = { //定义state,一个属性,React组件的MVVM渲染就是造它来完成的
               //name: "korgs"
           }; 
       }  //方法结尾没有逗号

       render() { //UI渲染方法
           return (
               <> {/*定义JSX最外层元素*/}
               	 <div> 我是显示内容 </div>
               </>
           );
       }
   }

   const container = document.getElementById('app');
   const root = ReactDOM.createRoot(container);
   root.render(<Suggest text="我是参数值"/>); //组件调用
</script>

核心属性

props

props是properties的缩写。props是React用来让组件之间互相联系的一种机制,通俗地说就是方法的参数,组件的props一定来自于默认属性或通过父组件传递而来,在组件中通过this.props来获取。

 render() { //UI渲染
     return (
         <>
             <div>{this.props.text}</div>
         </>
     );
 }

 //调用示例,这个值会覆盖掉组件中static defaultProps定义默认的值
 root.render(<Suggest text="我是参数值"/>); 

props在React是单向数据流,值也是不可变的。当试图改变props的原始值时,React会报出类型错误的警告,一般可以通过复制的方法来操作:

var attribs = Object.assign({}, this.props); // 浅复制
const obj = {...this.state.obj, foo:'bar'};  //浅复制另一种写法(推荐)

propTypes

非必要实现,它会列出所有可传递给组件的参数列表,同时也提供了参数验证功能,但注意,它只会在控制台发出警告,并不会阻断程序运行,在V16之后已从React核心库中删除了,所以需要单独安装:
npm i --save-dev prop-types

import PropsTypes from "prop-types"

class Suggest extends React.Component { //组件
    static defaultProps ={
        color: 'blue',
        text: 'Confirm',
    };
}

Suggest.props = { //参数列表
    color: PropsTypes.string.isRequired,
}

export default Suggest

以下是一些常见的用法:

Suggest.propTypes = {
  type: PropTypes.oneOf(['year', 'suggest', 'rating', 'text', 'input']),
  id: PropTypes.string,
  options: PropTypes.array,
  defaultValue: PropTypes.any,
  children: React.PropTypes.oneOfType([
        React.PropTypes.arrayOf(React.PropTypes.node),
        React.PropTypes.node,]
  ),
};

ref

如果需要访问底层DOM节点来执行一些命令式操作时,可以使用ref属性,这个属性值一般要求全局唯一,有两个术语需要先分清:

  • 组件:指React组件;
  • DOM节点:指组件渲染后的html的Dom节点,通过组件可以拿到DOM节点;
class Focus extends React.Component {

  constructor(props) {
    super(props)
    this.handleClick = this.handleClick.bind(this)
  }

  handleClick() {
    this.element.focus()
  }

  render() {
    return (
      <div>
        {/*这里的ref是一个回调函数,组件加载时就会运行*/}
        <input type="text" ref={element => (this.element = element)} />
          <button onClick={this.handleClick}>Focus</button>
      </div>
    )
  }
}

需要特别注意this.element = element中的element指向的组件,而非DOM节点元素,比如上面例子中 this.element = <input type="text" />,这样如果是个复杂组件,还可以访问组件内部的方法。

核心方法

render()

React在组件更新并非每次整个区域全部重新渲染,React会在内部维护一个称为Virual DOM的虚拟树,每次有DOM更新时就会维护此虚拟树结构,然后在需要UI重绘区域采用DOM DIFF算法计算出最小改变,然后选择最佳性能方法,比如append还是insert等方法重绘。

render() { //UI渲染
    return (
        <>
            <div> 我是显示内容 </div>
        </>
    );
}

render() 在实现上一般只返回组件,即使只是一段文本,也建议要用JSX的形式进行包装。

添加样式

内部样式

在组件内编写样式代码,React的style不能用字面量,需要封装成一个对象。然后需要用驼峰式代替原来的-连接符。

render() { //UI渲染
    const styleClass = {
        color:`red',
        background:`url({imgUrl})`,
        height:10 //默认是px
    };

    return (
        <>
            <div style={styleClass}>css</div>
        </>
    );
}

外部样式

正常使用时可以定义一个.css外部样式文件,然后在.js中引入。就可以正常使用了。

import './index.css'

使用classnames插件实现动态样式

npm i --save-dev classnames,这个插件主要用于当需要动态给组件添加样式,减少if语句数量用的,比如,下面代码就实现了按键颜色的切换。

import React from 'react'
import classnames from 'classnames';
import "./all.css"

class ClassNameDemo extends React.Component {

    constructor(props) {
        super(props);

        this.state ={
            isPressed: false,
        };

        this.handleClick = this.handleClick.bind(this);
    }

    handleClick() {
        this.setState({isPressed: true})
    }

    render() {
        //使用方式
        const btnClass = classnames({
            'btn':true,
            'btn-pressed': this.state.isPressed,
        })

        return (
            <div>
                <input type="text"/>
                <button className={btnClass} onClick={this.handleClick}>Focus</button>
            </div>
        )
    }

}

export default ClassNameDemo

all.css文件容

.btn{

}
.btn-pressed{
    color: #f3f;
}

事件交互

React把所有事件绑定到结构的最外层,使用一个统一的事件监听器来处理(事件委派机制)。

React基于Virtual DOM实现了一个SyntheticEvent(合成事件层),所有自定义的事件都会接收到一个兼容的SyntheticEvent对象实例,它与原生的Event完全兼容,同样也可以使用stopPropagation()preventDefault()来中断。

如果需要使用原生Event,可以调用SyntheticEvent.nativeEvent属性。

绑定事件

  • 构造器内绑定:这种不能传递参数,好处是性能好,只bind一次即可**(推荐)**
 class Suggest extends React.Component {
     static defaultProps ={  };

     constructor(props) {
         super(props);
          //绑定this到事件中,以实现在自定义事件中的this指向组件,而非事件
         this.handleClick = this.handleClick.bind(this);
     }

     handleClick(e){
         /*一般在此处会调用this.setState({})方法重绘UI界面
         有时为了防止冒泡,会调用 e.preventDefault() 方法*/
         console.log(e.target); //target = <button>Click me!!!</button>
     }

     render() { //UI渲染
         return (
             <>
                 <button onClick={this.handleClick}>Click me!!!</button>
             </>
         );
     }
 }
  • 自动绑定:这种可以传递参数,但每次渲染都要重新绑定一次
<script type="text/babel">
    class App extends React.Component {
        constructor(props) {
            super(props);
            
            this.state = {
                inputVal: 'male',
            };
        }

        handleInputChange(args, e) {
            console.log(e);
            console.log(args);
        }

        render() {
            const { inputVal} = this.state;
            return (
                <div>
                    <input type="radio" value="male" checked={inputVal === 'male'} onClick= {this.handleInputChange.bind(this,"dd")}/>
                </div>
            );
        }
    }

    const container = document.getElementById('app');
    const root = ReactDOM.createRoot(container);
    root.render(<App text="我是参数值"/>);
</script>

原生事件

一些特殊的事件React并没有实现,所以在必要时还会需要使用js的原生的事件机制,通过ref定义通过refs取得组件DOM,然后在组件加载后绑定原生的侦听事件,代码如下:

  class Suggest extends React.Component { 
      static defaultProps ={  };

      constructor(props) {
          super(props); 
          this.handListener = this.handListener.bind(this);
      }

      componentDidMount(){
          //refs在新版本中已经不建议再用了,而且本身也不建议再使用了
          this.refs.buttonDom.addEventListener('click', this.handListener);
      }

      handListener(e){
          console.log(e.target);
      }

      render() { //UI渲染
          return (
              <>
                  <button ref="buttonDom">Click buttonDom!!!</button>
              </>
          );
      }
  }

事件处理技巧

主要是为了防止绑定的事件太多,在一个地方绑定,然后用swith来分发,示例如下:

class Button extends React.Component {
  constructor(props) {
    super(props)
    this.handleEvent = this.handleEvent.bind(this) //绑定一个事件
  }

  handleEvent(event) {
    switch (event.type) { //根据事件类型分发事件
      case 'click':
        console.log('clicked')
        break

      case 'dblclick':
        console.log('double clicked')
        break

      default:
        console.log('unhandled', event.type)
    }
  }

  render() {
    return (
      <button 
           onClick={this.handleEvent} 
           onDoubleClick={this.handleEvent}>
          Click me!
      </button>
    )
  }
}

远程获取数据

从远程URL获取数据,下例展示了一个从远程获取组件state初始化数据的过程。

 componentDidMount() {
     const _this = this; //指向组件 this,否则在fetch函数中无法引用组件
     fetch('https://api.github.com/users/grearon/gists', {
         method: 'POST',
         mode: 'no-cors',
         headers: {
             'Content-Type': 'application/x-www-form-urlencoded'
         },
         // body: JSON.stringify(response)
     }).then(function(response) {
         _this.setState({response}); //重置state
     }).catch( error => console.log(error));
 }

导出和导入

可以直接写成下面这样的代码,因为我们的宗旨是构建小而美的组件,所以下列的代码完全合理:

//Gallery.js
export default function Gallery(){ }
export function Profile(){ }
语法导出语句导入语句
默认export default function Button() {}import Button from ‘./Button.js’;
具名export function Button() {}import { Button } from ‘./Button.js’;
  • 最后的.js可以省略
  • 同一文件中,有且仅有一个默认导出,但可以有多个具名导出!

组件调用

添加子元素

除了像下面代码这样调用组件:

   const container = document.getElementById('app');
   const root = ReactDOM.createRoot(container);
   root.render(<Suggest text="我是参数值"/>); //组件调用

还可以在调用时传入子组件,比如组件这样来定义:

return (
    <>
        <div style={styleClass}>{this.props.children}</div>
    </>
);

调用

const container = document.getElementById('app');
const root = ReactDOM.createRoot(container);
root.render(
    <Suggest text="我是参数值">
        <div>ddd</div>
    </Suggest>
);

注意看上例中{this.props.children}这个声明,它表示组件调用时可传递任意数量的子节点到组件中,上例中与<div>ddd</div>对应。

组件间通信

主要就是用到了props和state功能,希望两个组件的状态始终同步更改。要实现这一点,可以将相关 state 从这两个组件上移除,并把 state 放到它们的公共父级,再通过 props 将 state 传递给这两个组件。

父向子

父向子通过this.props属性,注意看下面的代码实现

<script type="text/babel">
   //子组件,定义了一个名为name的属性
   class Child extends React.Component{
       static defaultProps = {
           name:"button"
       }
       render(){
           console.log(this.props);
           return (
               <button>{this.props.name}</button>
           );
       }
   }

   //父组件
   class App extends React.Component{
       constructor(props){
           super(props);
       }
       render(){
           return (
              <>
                {/* 采用props传值给子组件,这时子组件其实会有两个属性值 */}
                <Child {...this.props}/> 
              </>
           );
       }
   }

   const container = document.getElementById('app');
   const root = ReactDOM.createRoot(container);
   root.render(<App name="我是参数值" color="red"/>);
</script>

子向父

子组件控制父组件主要是通过回调函数实现,在父组件中定义回调方法,在子组件中注册事件,然后父组件把回调方法以参数的方式传递给子组件。

<script type="text/babel">
    class Child extends React.Component{
        static defaultProps = {
            name:"button",
        }
        render(){
            return (
                <button onClick={this.props.btnClick}>{this.props.name}</button>
            );
        }
    }

    //父组件
    class App extends React.Component{
        constructor(props){
            super(props);
            
            //定义一个数据,供子组件来修改
            this.state={
                count:0
            }
            this.handleClick = this.handleClick.bind(this);
        }
        //定义回调函数
        handleClick(e) {
            this.setState({count: this.state.count+1})
            console.log(e.target + this.state.count); //~~out: <button>我是参数值</button>0
        }

        render() {
            return (
                <>  {/*回调函数以参数的形式传给子组件*/}
                    <Child btnClick={this.handleClick} {...this.props}/>
                </>
            );
        }
    }

    const container = document.getElementById('app');
    const root = ReactDOM.createRoot(container);
    root.render(<App name="我是参数值" color="red"/>);
</script>

同级间

一般会采用公有父组件的方式,说白了就是向上组装,由父组件统一控制state数据,以实现数据共享的目的,或是再向上包装或封装成一个单独的类对象。

<script type="text/babel">
    //子组件,定义了一个名为name的属性
    class Child extends React.Component{
        static defaultProps = {
            name:"button",
        }
        render(){
            return (
                <button onClick={this.props.btnClick}>{this.props.name}</button>
            );
        }
    }
    //子组件Display
    const Display = ({counter}) => {
        return <h1>{counter}</h1>
    }

    //父组件
    class App extends React.Component{
        constructor(props){
            super(props);

            //定义一个数据,供子组件来修改
            this.state={
                count:0
            }
            this.handleClick = this.handleClick.bind(this);
        }

        handleClick(e) {
            this.setState({count: this.state.count+1})
            console.log(e.target + this.state.count);
        }

        render() {
            return (
                <>
                    <Child btnClick={this.handleClick} {...this.props}/>
                    <Display counter={this.state.count}/>{/*共享state数据*/}
                </>
            );
        }
    }

    const container = document.getElementById('app');
    const root = ReactDOM.createRoot(container);
    root.render(<App name="我是参数值" color="red"/>);
</script>

-------- 以上组件的基本用法全介绍完了,下面是一个常用的实例---------

例子:处理表单数据

表单封装

<script type="text/babel">
    class UserForm extends React.Component {
        constructor(props) {
            super(props);
            this.state = {
                userName:"",
                userAge:0,
            };

            this.handleSubmit = this.handleSubmit.bind(this);
            this.handleContentChange = this.handleContentChange.bind(this);
        }

        handleSubmit(event){
            console.log("提交操作");
            console.log(this.state);
        }
        /*注意这种绑定方法的实现*/
        handleContentChange(event){
            //用这种方法可减少change函数的个数
            this.setState({
                [event.target.name]: event.target.value,
            })
        }

        render() {
            const {color, text} = this.props;
            return (
                <>
                    <form onSubmit={this.handleSubmit}>
                        {/*注意这种绑定方法*/}
                        <label>用户名:</label><input name="userName" type="text"  value={this.state.name} onChange={this.handleContentChange}/>
                        <button  className={`btn btn-${color}`} >提交</button>
                    </form>
                </>
            );
        }
    }

    const container = document.getElementById('app');
    const root = ReactDOM.createRoot(container);
    root.render(<UserForm />);
</script>

使用schema插件自动创建表单

下面的例子只是列出了如何格式化表单,至于jsonschema的详细用法可查看其官网,https://react-jsonschema-form.readthedocs.io/en/v1.8.1/。
安装 npm install --save react-jsonschema-form

class JSONSchemaForm extends React.Component {
    constructor() {
        super();
        this.handleSubmit = this.handleSubmit.bind(this);
    }

    handleSubmit = (values) => {
        console.log(values);
    }

    render() {
        //构建form表单
        const schemaForm = {
            type:"object",
            properties: {
                firstName: {type:"string", default:"Dan"},
                lastName: {type:"string", default:"Abramov"},
            }
        }

        return (
            <Form schema={schemaForm} onSubmit={this.handleSubmit}>
            	<button type="submit">Sub2mit</button>
            </Form>
        )
    }
}

例子:组件优化

剥离操作和展现

就是把UI定义成一个方法、变量、参数或是单独组件,举例如下:

const ui = [
    <>
        <div> 我是显示内容 </div>
        <div className="Suggest" ref="div01">{this.props.text}</div>
        <div style={styleClass}>css</div>
    </>
]

return (
    ui
);

展开属性…的用法

...用法其实就是一种语法糖,比如:

render() { //UI渲染
    const attr = {
        href:"www.baidu.com",
        alt:"_blank"
    }
    return (
        <>  
            {/* 这种写法其实就是herf={attr.href} alt={attr.alt}*/}
            <a {...attr}>click</a>
        </>
    );
}

删除属性

 // 浅复制
var attribs = Object.assign({}, this.props);
//这段代码等价于: delete attribs.size; 
var {size, ...attribs} = this.props;

Immutable不可变数据集

这个库定义了多个类型工具类,如List, Stack, Map等,其主要是为了函数编程使用
cnpm insatll --save-dev immutable

import {List} from 'immutable';
//因为immutable中的对象和原生js比较相像,所以尽量用命名区分开,以免混淆
let $$list = List([1, 2]);
$$list.push(3, 4);

let $$map = Immutable.Map({a:1, b:2, c:3})

Pure-render处理shouldComponentUpdate

这一节内容可以和Immutable不可变数据集一同应用,因为state变化会自动render(),所以在操作state前最好使用Immutable把一些数据变成不可变的,由人为来判断是否需要改变数据。

也就是在某此时刻最好把state看成是一个不可变对象。
cnpm i --save-dev react-addons-pure-render-mixin

import PureRenderMixin from 'react-addons-pure-render-mixin'

class App extends  React.Component{
    constructor(props) {
        super(props);
        //一个浅复制的应现,代替原来的should实现
        this.shouldComponentUpdate = PureRenderMixin.shouldComponentUpdate.bind(this);
    }

    render(){
        return <div>aaa</div>
    }
}

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

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

相关文章

vue+elemntui 加减表单框功能样式

<el-form ref"form" :model"form" :rules"rules" label-width"80px"><el-form-item label"配置时间" prop"currentAllocationDate"><div v-for"(item,key) in timeList"><el-date…

ROCm上来自Transformers的双向编码器表示(BERT)

14.8. 来自Transformers的双向编码器表示&#xff08;BERT&#xff09; — 动手学深度学习 2.0.0 documentation (d2l.ai) 代码 import torch from torch import nn from d2l import torch as d2l#save def get_tokens_and_segments(tokens_a, tokens_bNone):""&qu…

Cortex-M3的SysTick 定时器

目录 概述 1 SysTick 定时器 1.1 SysTick 定时器功能介绍 1.2 SysTick 定时器功能实现 1.3 SysTick在系统中的作用 2 SysTick应用的实例 2.1 建立异常服务例程 2.2 使能异常 2.3 闹钟功能 2.4 重定位向量表 2.5 消灭二次触发 3 SysTick在FreeRTOS中的应用 3.1 STM…

(完全解决)Python字典dict如何由键key索引转化为点.dot索引

文章目录 背景解决方案基础版升级版 背景 For example, instead of writing mydict[‘val’], I’d like to write mydict.val. 解决方案 基础版 I’ve always kept this around in a util file. You can use it as a mixin on your own classes too. class dotdict(dict)…

如何进行异地多地兼容组网设置?

跨地区工作、远程办公和异地合作已成为常态。由于网络限制和安全性要求&#xff0c;远程连接仍然是一个具有挑战性的问题。为了解决这一难题&#xff0c;各行各业都在寻找一种能在异地多地兼容的组网设置方案。本文将着重介绍基于【天联】的组网解决方案&#xff0c;探讨其操作…

SpringBoot——整合Thymeleaf模板

目录 模板引擎 新建一个SpringBoot项目 pom.xml application.properties Book BookController bookList.html ​编辑 项目总结 模板引擎 模板引擎是为了用户界面与业务数据分离而产生的&#xff0c;可以生成特定格式的页面在Java中&#xff0c;主要的模板引擎有JSP&…

如何评价刘强东说“业绩不好的人不是我兄弟”

在近日的一次京东管理层会议上&#xff0c;创始人刘强东以不容置疑的口吻表明了对公司文化的坚定态度&#xff1a;“凡是长期业绩不好&#xff0c;从来不拼搏的人&#xff0c;不是我的兄弟。”这句话不仅是对那些工作表现不佳的员工的直接警告&#xff0c;也透露出京东在追求业…

C++语法|多重继承详解(一)|理解虚基类和虚继承

系列汇总讲解&#xff0c;请移步&#xff1a; C语法&#xff5c;虚函数与多态详细讲解系列&#xff08;包含多重继承内容&#xff09; 虚基类是多重继承知识上的铺垫。 首先我们需要明确抽象类和虚基类的区别&#xff1a; 抽象类&#xff1a;有纯虚函数的类 虚基类是什么呢&a…

阿里云的域名购买和备案(一)

前言 本篇文章主要讲阿里云的域名购买和备案。 大家好&#xff0c;我是小荣&#xff0c;我又开始做自己的产品迷途dev了。这里详细记录一下域名购买的流程和备案流程。视频教学 购买流程 1.阿里云官网搜索域名注册 2.搜索你想注册的域名 3.将想要注册的域名加入域名清单 4.点…

[Linux]网络原理与配置

一.NAT模式网路配置 虚拟系统的IP地址处于随机网段&#xff0c;同时在母机上会额外有一个与虚拟IP地址网段相同的IP地址&#xff0c;可以实现母机与虚拟机的通信。虚拟系统的IP地址可以通过主机实际的IP地址作为代理IP&#xff0c;与外部系统进行通信。 优点&#xff1a;不造…

2024.05.25学习记录

1、面经复习&#xff1a; JS异步进阶、vue-react-diff、vue-router模式、requestldleCallback、React Fiber 2、代码随想录刷题、动态规划 3、组件库使用storybook

【C++】牛客——JZ38 字符串的排列

✨题目链接&#xff1a; JZ38 字符串的排列 ✨题目描述 输入一个长度为 n 字符串&#xff0c;打印出该字符串中字符的所有排列&#xff0c;你可以以任意顺序返回这个字符串数组。 例如输入字符串ABC,则输出由字符A,B,C所能排列出来的所有字符串ABC,ACB,BAC,BCA,CBA和CAB。 数…

结合时间复杂度浅谈二分法的好处(将持续更新,绝对值你一个收藏)

前言 笔者虽然刷的算法题不多,但是笔者也敢说,二分法真的是一种很优越的算法,使用上限极高的那种,正因如此,笔者才想浅谈一下二分法. 封面是我很喜欢的一个游戏角色,不知道有没有老gal玩家知道! 什么是二分法? 枚举查找即顺序查找&#xff0c;实现原理是逐个比较数组 a[0:…

【C++】详解二叉搜索树

目录 树概述 二叉搜索树概述 概念 特性 元素操作 插入 删除 模拟实现 框架 查找 插入 删除 树概述 树——在计算机中是一种很常见的数据结构。 树是一种很强大的数据结构&#xff0c;数据库&#xff0c;linux操作系统管理和windows操作系统管理所有文件的结构就是…

【基础详解】快速入门入门 SQLite数据可

简介 SQLite 是一个开源的嵌入式关系数据库&#xff0c;实现了自给自足的、无服务器的、配置无需的、事务性的 SQL 数据库引擎。它是一个零配置的数据库&#xff0c;这意味着与其他数据库系统不同&#xff0c;比如 MySQL、PostgreSQL 等&#xff0c;SQLite 不需要在系统中设置…

golang中的字节序 binary BigEndian 大端 , LittleEndian 小端 理解与write写入注意事项

在golang的binary包中有2个字节系的变量定义BigEndian和LittleEndian 这个东西是go里面很有特点的玩意&#xff0c;我们在java, php等语言中是基本看不到&#xff0c;因为大部分的语言默认使用的是BigEndian 大端模式&#xff0c; 而go语言里面是你自己可选的。 这个字节系大小…

Java的类和对象

Java的类和对象 前言一、面向过程和面向对象初步认识C语言Java 二、类和类的实例化基本语法示例注意事项 类的实例化 三、类的成员字段/属性/成员变量注意事项默认值规则字段就地初始化 方法static 关键字修饰属性代码内存解析 修饰方法注意事项静态方法和实例无关, 而是和类相…

@Async详解,为什么生产环境不推荐直接使用@Async?

一、Async 注解介绍&#xff1a; Async 注解用于声明一个方法是异步的。当在方法上加上这个注解时&#xff0c;Spring 将会在一个新的线程中执行该方法&#xff0c;而不会阻塞原始线程。这对于需要进行一些异步操作的场景非常有用&#xff0c;比如在后台执行一些耗时的任务而不…

ssms用户登陆失败,服务器处于单用户模式。目前只有一位管理员能够连接。解决方案

文章目录 问题解决方案单用户模式什么是单用户模式&#xff1f;为什么使用单用户模式&#xff1f;实现步骤 问题 连接smss的时候发现无法连接&#xff0c;显示 服务器处于单用户模式。目前只有一位管理员能够连接 解决方案 打开SQL Server配置管理器 右键属性 在启动参数的最…

Python 之 日志巡检脚本

脚本说明 使用Paramiko库进行SSH连接的自动化脚本&#xff0c;用于检查、配置和排除设备故障。说明如下&#xff1a; 导入所需的库&#xff1a;paramiko、json、logging和concurrent.futures。定义配置文件路径&#xff08;devices.json&#xff09;和日志文件路径&#xff0…