react【三】受控组件/高阶组件/portals/fragment/严格模式/动画

文章目录

  • 1、受控组件
    • 1.1 认识受控组件
    • 1.2 checkout
    • 1.3 selected
    • 1.4 非受控组件
  • 2、高阶组件
    • 2.1 认识高阶组件
    • 2.2 应用1-props增强的基本使用
    • 2.3 对象增强的应用场景-context共享
    • 2.4 应用2-鉴权
    • 2.5 应用3 – 生命周期劫持
    • 2.6、高阶组件的意义
  • 3、Portals
  • 4、fragment
  • 5、StrictMode
  • 6、React过渡动画实现
    • 6.1 CSSTransition
    • 6.2 SwitchTransition
    • 6.3 TransitionGroup

1、受控组件

1.1 认识受控组件

在这里插入图片描述

import React, { PureComponent } from "react";

export class App extends PureComponent {
  constructor() {
    super();

    this.state = {
      userName: "",
    };
  }

  inputChange(e) {
    const value = e.target.value;
    this.setState({ userName: value });
  }

  submitChange(e) {
    // 1.阻止表单的默认事件 表单默认会被刷新
    e.preventDefault();

    // 2.在这里修改表单数据
    console.log(e);

    // 3.发送网络请求
  }

  render() {
    const { userName } = this.state;

    return (
      <div>
        <form onSubmit={(e) => this.submitChange(e)}>
          <label htmlFor="userName">
            用户:
            <input
              id="userName"
              type="text"
              name="userName"
              value={userName}
              onChange={(e) => this.inputChange(e)}
            ></input>
          </label>
          <button type="submit">注册</button>
        </form>
      </div>
    );
  }
}

export default App;

在这里插入图片描述

1.2 checkout

在这里插入图片描述

import React, { PureComponent } from "react";

export class App extends PureComponent {
  constructor() {
    super();

    this.state = {
      userName: "",
      password: "",
      isAgree: false,
      hobbies: [
        { value: "sing", text: "唱", isChecked: false },
        { value: "dance", text: "跳", isChecked: false },
        { value: "rap", text: "rap", isChecked: false },
      ],
    };
  }

  handleAgreeChange(e) {
    this.setState({ isAgree: e.target.checked });
  }

  handleHobbiesChange(e, index) {
    const hobbies = [...this.state.hobbies];
    hobbies[index].isChecked = e.target.checked;

    this.setState({ hobbies });
  }

  submitChange(e) {
    // 1.阻止表单的默认事件 表单默认会被刷新
    e.preventDefault();

    // 2.在这里修改表单数据
    console.log(e);
    const hobbies = this.state.hobbies.filter((item) => item.isChecked);
    console.log(hobbies);

    // 3.发送网络请求
  }

  render() {
    const { isAgree, hobbies } = this.state;

    return (
      <div>
        <form onSubmit={(e) => this.submitChange(e)}>
          {/* 单选 */}
          <label htmlFor="agree">
            <input
              type="checkbox"
              id="agree"
              checked={isAgree}
              onChange={(e) => this.handleAgreeChange(e)}
            />
            单选
          </label>

          {/* 多选 */}
          <div>
            {hobbies.map((item, index) => {
              return (
                <label htmlFor={item.value} key={index}>
                  <input
                    type="checkbox"
                    id={item.value}
                    checked={item.isChecked}
                    onChange={(e) => this.handleHobbiesChange(e, index)}
                  />
                  {item.text}
                </label>
              );
            })}
          </div>

          <button type="submit">注册</button>
        </form>
      </div>
    );
  }
}

export default App;

1.3 selected

在这里插入图片描述

import React, { PureComponent } from "react";

export class App extends PureComponent {
  constructor() {
    super();

    this.state = {
      fruit: "orange",
      fruits: ["orange", "apple"],
    };
  }

  submitChange(e) {
    // 1.阻止表单的默认事件 表单默认会被刷新
    e.preventDefault();

    // 2.在这里修改表单数据
    console.log(e);

    // 3.发送网络请求
  }

  // 单选
  fruitChange(e) {
    console.log(e.target.value);
    this.setState({ fruit: e.target.value });
  }

  //  多选
  fruitsChange(event) {
    // event.target.selectedOptions 获取到的不是数组 HTMLCollection [option]
    // 方法1
    // const options = Array.from(event.target.selectedOptions);
    // const values = options.map((item) => item.value);
    // this.setState({ fruits: values });

    // 额外补充: Array.from(可迭代对象)
    // Array.from(arguments,()=>{})

    // 方法2
    const values = Array.from(
      event.target.selectedOptions,
      (item) => item.value
    );

    this.setState({ fruits: values });
  }

  render() {
    const { fruit, fruits } = this.state;

    return (
      <div>
        <form onSubmit={(e) => this.submitChange(e)}>
          {/* select单选 */}
          <select value={fruit} onChange={(e) => this.fruitChange(e)}>
            <option value="apple">苹果</option>
            <option value="orange">橘子</option>
            <option value="banana">香蕉</option>
          </select>

          {/* select多选 */}
          <select
            value={fruits}
            multiple
            onChange={(e) => this.fruitsChange(e)}
          >
            <option value="apple">苹果</option>
            <option value="orange">橘子</option>
            <option value="banana">香蕉</option>
          </select>

          <button type="submit">注册</button>
        </form>
      </div>
    );
  }
}

export default App;

1.4 非受控组件

在这里插入图片描述

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

export class App extends PureComponent {
  constructor() {
    super();

    this.state = { intro: "kiki" };
    this.introRef = createRef();
  }

  submitChange(e) {
    // 1.阻止表单的默认事件 表单默认会被刷新
    e.preventDefault();

    // 2.在这里修改表单数据
    console.log(e);
    console.log(this.introRef.current.value);

    // 3.发送网络请求
  }

  render() {
    const { intro } = this.state;

    return (
      <div>
        <form onSubmit={(e) => this.submitChange(e)}>
          <input type="text" defaultValue={intro} ref={this.introRef}></input>

          <button type="submit">注册</button>
        </form>
      </div>
    );
  }
}

export default App;

2、高阶组件

2.1 认识高阶组件

在这里插入图片描述在这里插入图片描述

import React, { PureComponent } from "react";

// 普通类组件
class HelloWorld extends PureComponent {
  constructor(props) {
    super(props);
  }
  render() {
    const { name } = this.props;
    return (
      <div>
        <span>普通的类组件-{name}</span>
      </div>
    );
  }
}

// 高阶组件
const Hoc = (Comp) => {
  class NewCpn extends PureComponent {
    render() {
      return (
        <div>
          <h1>我是高阶组件</h1>
          {/* 高阶组件传递参数给子组件 */}
          <Comp name="kiki" />
        </div>
      );
    }
  }
  return NewCpn;
};

// 调用高阶组件
const HelloWorldHOC = Hoc(HelloWorld);

class componentName extends PureComponent {
  render() {
    return (
      <div>
        {/* 对高阶组件的使用 */}
        <HelloWorldHOC />
      </div>
    );
  }
}

export default componentName;

2.2 应用1-props增强的基本使用

在这里插入图片描述

  • enhanced_props.js
import React, { PureComponent } from "react";

const enhancedUserInfo = (OriginComponent) => {
  class NewComponent extends PureComponent {
    constructor(props) {
      super(props);

      this.state = {
        userInfo: {
          name: "kiki",
          age: "18",
        },
      };
    }
    render() {
      // 1.将state.userInfo的内容全部传递给子组件
      // 2.将OriginComponents 原本的props也给注入
      return <OriginComponent {...this.props} {...this.state.userInfo} />;
    }
  }
  return NewComponent;
};

export default enhancedUserInfo;

  • about.jsx
import React, { PureComponent } from 'react'
import enhancedUserInfo from '../hoc/enhanced_props'

export class About extends PureComponent {
  render() {
    return (
      <div>About: {this.props.name}</div>
    )
  }
}

export default enhancedUserInfo(About)

  • App.jsx
import React, { PureComponent } from "react";
import enhancedUserInfo from "./hoc/enhanced_props";
import About from "./pages/About";

const Home = enhancedUserInfo((props) => {
  // 通过enhancedUserInfo 将它本身的state传递给该函数组件
  return (
    <h1>
      {props.name}-{props.age}
    </h1>
  );
});

const HelloWord = enhancedUserInfo((props) => {
  return (
    <h1>
      {/* 调用组件的时候传递的参数也可以拿到 */}
      {props.name}-{props.age}-{props.banner}
    </h1>
  );
});

export class App extends PureComponent {
  render() {
    return (
      <div>
        <Home />
        {/* 给高阶函数传递props */}
        <HelloWord banner="['a','b']" />
        {/* 调用已经注入enhancedUserInfo的组件 */}
        <About />
      </div>
    );
  }
}

export default App;

2.3 对象增强的应用场景-context共享

  • 使用高阶组件来跨组件传参
    在这里插入图片描述

  • theme_context.js (创建context)

import { createContext } from "react";

const themeContext = createContext();

export default themeContext;

  • with_theme.js(props增强
import ThemeContext from "../context/theme_context";

const withTheme = (OriginComp) => {
  return (props) => {
    return (
      // 将共享context传递给子组件 把传递给高阶函数的props也传递给子组件
      <ThemeContext.Consumer>
        {(value) => {
          return <OriginComp {...value} {...props} />;
        }}
      </ThemeContext.Consumer>
    );
  };
};

export default withTheme;

  • procuct组件
import React, { PureComponent } from "react";
import ThemeContext from "../context/theme_context";
import withTheme from "../hoc/with_theme";

// export class Product extends PureComponent {
//   render() {
//     return (
//       <div>
//         Product:
//         <ThemeContext.Consumer>
//           {
//             value => {
//               return <h2>theme:{value.color}-{value.size}</h2>
//             }
//           }
//         </ThemeContext.Consumer>
//       </div>
//     )
//   }
// }

// export default Product

export class Product extends PureComponent {
  render() {
    const { color, size, name } = this.props;

    return (
      <div>
        <h2>
          context注入的参数: {color}-{size}
        </h2>
        <div>传递给product的参数:{name}</div>
      </div>
    );
  }
}

// 将context的参数注入给product
export default withTheme(Product);

  • App.jsx
import React, { PureComponent } from "react";
import ThemeContext from "./context/theme_context";
import Product from "./pages/Product";

export class App extends PureComponent {
  render() {
    return (
      <div>
        <ThemeContext.Provider value={{ color: "red", size: 30 }}>
          <Product name="kiki" />
        </ThemeContext.Provider>
      </div>
    );
  }
}

export default App;

2.4 应用2-鉴权

在这里插入图片描述

  • login_auth
const loginAuth = (OriginComp) => {
  return (props) => {
    const token = localStorage.getItem("token");
    return token ? <OriginComp {...props} /> : "请先登录";
  };
};

export default loginAuth;

  • card.jsx
import React, { PureComponent } from 'react'
import loginAuth from '../hoc/login_auth'

export class Cart extends PureComponent {
  render() {
    return (
      <h2>Cart Page</h2>
    )
  }
}

export default loginAuth(Cart)
  • app.jsx
import React, { PureComponent } from "react";
import Cart from "./pages/Cart";

export class App extends PureComponent {
  handleClick() {
    localStorage.setItem("token", "kiki");

    // 修改本地缓存并不会发生界面刷新 所以需要强制刷新
    // 强制刷新在一般情况下部推荐 so 请使用 state
    this.forceUpdate();
  }
  render() {
    return (
      <div>
        <button onClick={(e) => this.handleClick()}>点击登录</button>
        <Cart />
      </div>
    );
  }
}

export default App;

2.5 应用3 – 生命周期劫持

  • log_render_time
import { PureComponent } from "react";

function logRenderTime(OriginComponent) {
  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

  • detail.jsx
import React, { PureComponent } from 'react'
import logRenderTime from '../hoc/log_render_time'

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() {
    return (
      <div>
        <h2>Detail Page</h2>
        <ul>
          <li>数据列表1</li>
          <li>数据列表2</li>
          <li>数据列表3</li>
          <li>数据列表4</li>
          <li>数据列表5</li>
          <li>数据列表6</li>
          <li>数据列表7</li>
          <li>数据列表8</li>
          <li>数据列表9</li>
          <li>数据列表10</li>
        </ul>
      </div>
    )
  }
}

export default logRenderTime(Detail)
  • App.jsx
import React, { PureComponent } from 'react'
import Detail from './pages/Detail'

export class App extends PureComponent {
  render() {
    return (
      <div>
        <Detail/>
      </div>
    )
  }
}

export default App

2.6、高阶组件的意义

在这里插入图片描述

3、Portals

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4、fragment

在这里插入图片描述

import React, { PureComponent, Fragment } from 'react'

export class App extends PureComponent {
  constructor() {
    super() 

    this.state = {
      sections: [
        { title: "哈哈哈", content: "我是内容, 哈哈哈" },
        { title: "呵呵呵", content: "我是内容, 呵呵呵" },
        { title: "嘿嘿嘿", content: "我是内容, 嘿嘿嘿" },
        { title: "嘻嘻嘻", content: "我是内容, 嘻嘻嘻" },
      ]
    }
  }

  render() {
    const { sections } = this.state

    return (
      <>
        <h2>我是App的标题</h2>
        <p>我是App的内容, 哈哈哈哈</p>
        <hr />

        {
          sections.map(item => {
            return (
              <Fragment key={item.title}>
                <h2>{item.title}</h2>
                <p>{item.content}</p>
              </Fragment>
            )
          })
        }
      </>
    )
  }
}

export default App

5、StrictMode

在这里插入图片描述
在这里插入图片描述

6、React过渡动画实现

在这里插入图片描述
在这里插入图片描述

6.1 CSSTransition

在这里插入图片描述
在这里插入图片描述

  • npm install react-transition-group --save
    在这里插入图片描述
import React, { createRef, PureComponent } from "react";
import { CSSTransition } from "react-transition-group";
import "./style.css";

export class App extends PureComponent {
  constructor(props) {
    super(props);

    this.state = {
      isShow: true,
    };

    // 在严格模式下会报错 所以需要绑定ref
    this.sectionRef = createRef();
  }

  render() {
    const { isShow } = this.state;

    return (
      <div>
        <button onClick={(e) => this.setState({ isShow: !isShow })}>
          切换
        </button>
        {/* { isShow && <h2>哈哈哈</h2> } */}

        {/* timeout是必须要设置的,他是控制类的移出事件 动画时间还是由CSS控制 */}
        {/* unmountOnExit:用来决定是否移除组件 */}
        {/* appear:刚挂载的时候是否有动画 */}

        <CSSTransition
          nodeRef={this.sectionRef}
          in={isShow}
          unmountOnExit={true}
          classNames="why"
          timeout={2000}
          appear
          onEnter={(e) => console.log("开始进入动画")}
          onEntering={(e) => console.log("执行进入动画")}
          onEntered={(e) => console.log("执行进入结束")}
          onExit={(e) => console.log("开始离开动画")}
          onExiting={(e) => console.log("执行离开动画")}
          onExited={(e) => console.log("执行离开结束")}
        >
          <div className="section" ref={this.sectionRef}>
            <h2>哈哈哈</h2>
            <p>我是内容, 哈哈哈</p>
          </div>
        </CSSTransition>
      </div>
    );
  }
}

export default App;

6.2 SwitchTransition

在这里插入图片描述
在这里插入图片描述

  • App.jsx
import React, { PureComponent } from "react";
import { SwitchTransition, CSSTransition } from "react-transition-group";
import "./style.css";

export class App extends PureComponent {
  constructor() {
    super();

    this.state = {
      isLogin: true,
    };
  }

  render() {
    const { isLogin } = this.state;

    return (
      <div>
        <SwitchTransition mode="out-in">
          <CSSTransition
            // 在切换组件的时候用的是key 显示和隐藏
            key={isLogin ? "exit" : "login"}
            classNames="login"
            timeout={1000}
          >
            <button onClick={(e) => this.setState({ isLogin: !isLogin })}>
              {isLogin ? "退出" : "登录"}
            </button>
          </CSSTransition>
        </SwitchTransition>
      </div>
    );
  }
}

export default App;

6.3 TransitionGroup

在这里插入图片描述
在这里插入图片描述

import React, { PureComponent } from "react";
import { TransitionGroup, CSSTransition } from "react-transition-group";
import "./style.css";

export class App extends PureComponent {
  constructor() {
    super();

    this.state = {
      books: [
        { id: 111, name: "你不知道JS", price: 99 },
        { id: 222, name: "JS高级程序设计", price: 88 },
        { id: 333, name: "Vuejs高级设计", price: 77 },
      ],
    };
  }

  addNewBook() {
    const books = [...this.state.books];
    books.push({
      id: new Date().getTime(),
      name: "React高级程序设计",
      price: 99,
    });
    this.setState({ books });
  }

  removeBook(index) {
    const books = [...this.state.books];
    books.splice(index, 1);
    this.setState({ books });
  }

  render() {
    const { books } = this.state;

    return (
      <div>
        <h2>书籍列表:</h2>
        <TransitionGroup component="ul">
          {books.map((item, index) => {
            return (
              // 这里不用index作为key是因为在删除的时候Index是动态变化的会发生错乱
              <CSSTransition key={item.id} classNames="book" timeout={1000}>
                <li>
                  <span>
                    {item.name}-{item.price}
                  </span>
                  <button onClick={(e) => this.removeBook(index)}>删除</button>
                </li>
              </CSSTransition>
            );
          })}
        </TransitionGroup>
        <button onClick={(e) => this.addNewBook()}>添加新书籍</button>
      </div>
    );
  }
}

export default App;

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

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

相关文章

【无标题】Matlab之annotation函数——创建图形注释(箭头、椭圆、矩形)

应用1&#xff1a;创建文本箭头注释 创建一个简单线图并向图窗添加文本箭头。用归一化的图窗坐标指定文本箭头位置&#xff0c;起点为 (0.3,0.6)&#xff0c;终点为 (0.5,0.5)。通过设置 String 属性指定文本说明。 figure plot(1:10) x [0.3 0.5]; y [0.6 0.5]; annotation…

Linux网络基础1

目录 计算机网络背景协议OSI七层模型TCP/IP五层&#xff08;四层&#xff09;模型网络传输基本流程以太网通信原理IP地址理解 计算机网络背景 到目前为止&#xff0c;我们之前所有的编程都是单机的&#xff0c;不是多机互联。以前计算机被发明的时候是为了军事用途&#xff0…

【C语言】常见字符串函数的功能与模拟实现

目录 1.strlen() 模拟实现strlen() 2.strcpy() 模拟实现strcpy() 3.strcat() 模拟实现strcat() 4.strcmp() 模拟实现strcmp() 5.strncpy() 模拟实现strncpy() 6.strncat() 模拟实现strncat() 7.strncmp() 模拟实现strncmp() 8.strstr() 模拟实现strstr() 9.str…

Midjourney绘图欣赏系列(一)

Midjourney介绍 Midjourney 是生成式人工智能的一个很好的例子&#xff0c;它根据文本提示创建图像。它与 Dall-E 和 Stable Diffusion 一起成为最流行的 AI 艺术创作工具之一。与竞争对手不同&#xff0c;Midjourney 是自筹资金且闭源的&#xff0c;因此确切了解其幕后内容尚不…

Vulhub kali 环境安装教程

进入 root 权限 sudo su 更新软件 apt-get update 安装 HTTPS 协议和 CA 证书 apt-get install -y apt-transport-https ca-certificates 安装 docker apt install docker.io 查看 docker 是否安装完成 docker -v 安装 pip apt-get install python3-pip 安装 docker-compose do…

【python之美】减少人工成本之批量去除首行_3

批量去除首行内容 怎么创建多个文本并写入多行数据呢 上特产&#xff1a; import ospath "C:\\Users\\Administrator\\Desktop\\text_1\\" numb int(input("需要创建几个文件&#xff1a;")) a 1 for i in range(numb):f open(path text _ str(a)…

jmeter-问题四:json断言时,预期结果那里如何不写成固定值?

文章目录 json断言时&#xff0c;预期结果那里如何不写成固定值&#xff1f;定义用户参数&#xff0c;然后在json断言的expected value处引用使用csv数据&#xff0c;然后在json断言的expected value处引用 json断言时&#xff0c;预期结果那里如何不写成固定值&#xff1f; 定…

测试开发-2-概念篇

文章目录 衡量软件测试结果的依据—需求1.需求的概念2.从软件测试人员角度看需求3.为什么需求对软件测试人员如此重要4.如何才可以深入理解被测试软件的需求5.测试用例的概念6.软件错误&#xff08;BUG&#xff09;的概念7.开发模型和测试模型8.软件的生命周期9.瀑布模型&#…

Spring 用法学习总结(三)之 AOP

Spring学习 7 bean的生命周期8 AOP面向切面编程8.1 AOP相关术语8.2 AOP使用 7 bean的生命周期 bean的生命周期主要为bean实例化、bean属性赋值、bean初始化、销毁bean&#xff0c;其中在实例化和初始化前后都使用后置处理器方法&#xff0c;而InstantiationAwareBeanPostProce…

Linux之多线程

目录 一、进程与线程 1.1 进程的概念 1.2 线程的概念 1.3 线程的优点 1.4 线程的缺点 1.5 线程异常 1.6 线程用途 二、线程控制 2.1 POSIX线程库 2.2 创建一个新的线程 2.3 线程ID及进程地址空间布局 2.4 线程终止 2.5 线程等待 2.6 线程分离 一、进程与线程 在…

HDFS的超级用户

一. 解释原因 HDFS(Hadoop Distributed File System)和linux文件系统管理一样&#xff0c;也是存在权限控制的。 但是很不一样的是&#xff0c; 在Linux文件系统中&#xff0c;超级用户Superuser是root而在HDFS中&#xff0c;超级用户Superuser是启动了namenode的用户&#x…

4核16g配置咋样?还不错,阿里云4核16G服务器26元1个月

4核16g配置咋样&#xff1f;还不错&#xff0c;阿里云4核16G服务器26元1个月&#xff0c;阿里云4核16G服务器配置优惠价格ECS云服务器经济型e实例26元1个月、149元半年、79元3个月&#xff0c;4核16G通用算力u1服务器、通用型g7、通用型g8i、AMD通用型g8a、性能增强通用型g8ae、…

html从零开始6:关系选择器、css盒子模型、弹性盒子模型【搬代码】

关系选择器 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"widthdevice-width,…

Linux日志管理服务 rsyslogd

文章目录 1. 基本介绍2. 系统常用的日志3. 日志管理服务 rsyslogd 1. 基本介绍 日志文件是重要的系统信息文件&#xff0c;其中记录了许多重要的系统事件&#xff0c;包括用户的登录信息、系统的启动信息、系统的安全信息、邮件相关信息、各种服务相关信息等。日志对于安全来说…

QQ群微信群强制加群/随机小姐姐视频分享打赏裂变PHP源码

很多人再找qq群或者微信分享小姐姐视频打赏的裂变源码&#xff0c;这次就分享出来&#xff01; 下载地址QQ群微信群强制加群.zip官方版下载丨最新版下载丨绿色版下载丨APP下载-123云盘

中国电子学会2023年12月份青少年软件编程Scratch图形化等级考试试卷二级真题(含答案)

2023-12 Scratch二级真题 分数&#xff1a;100 题数&#xff1a;37 测试时长&#xff1a;60min 一、单选题(共25题&#xff0c;共50分) 1.在制作推箱子游戏时&#xff0c;地图是用数字形式储存在电脑里的&#xff0c;下图是一个推箱子地图&#xff0c;地图表示如下&#x…

QGIS教程 加载shape数据 矢量数据(批量)

一. 前言 本篇文章主要介绍QGIS的使用&#xff0c;包括如何加载矢量shape数据、查看数据属性、如何加载txt属性数据、怎么用脚本批量加载矢量数据等内容。 如果想了解QGIS&#xff0c;可以参考博文&#xff1a; QGIS基本介绍 如果想了解shape数据格式详情&#xff0c;可以参考…

bpmn-js 事件总线处理

bpmn-js中使用EventBus作为事件的处理句柄&#xff0c;EventBus的使用和我们常规使用的事件总线没啥大的区别&#xff0c;其源码位于&#xff1a;/diagram-js/lib/core/EventBus.js &#xff08;bpmn-js使用diagram-js实现流程图的web端绘制呈现工具&#xff09;。 EventBus使用…

权限提升:利用Linux错配提权

目录 Linux权限基础 Linux用户权限 Linux文件权限 特殊的Linux文件权限 Linux本机信息收集 Linux错配提权 crontab计划任务提权 SUID提权 Linux权限基础 Linux用户权限 在Linux中&#xff0c;根据权限的不同&#xff0c;大致可以分为三种&#xff1a;超级用户&#x…

steam游戏搬砖项目靠谱吗?有没有风险?

作为一款fps射击游戏&#xff0c;csgo在近几年可谓是火出圈&#xff0c;作为一款全球竞技游戏&#xff0c;深受玩家喜爱追捧&#xff0c;玩家追求的就是公平公正&#xff0c;各凭本事&#xff0c;像其他游戏可能还会有皮肤等装备属性加成&#xff0c;在csgo里面是不存在的。 纯…