js 应用的几大原则 及 应用实例

news2024/12/16 14:33:06

文章目录

    • js 应用的几大原则
      • vue3 中原则应用体现
      • react 原则应用体现

js 应用的几大原则

  1. 单一职责原则(SRP)
    • 解释:一个函数或者一个对象应该只有一个职责。这意味着函数应该只做一件事情并且把它做好。例如,一个函数只负责计算两个数的和,而不应该同时进行和的计算、结果的打印以及数据的存储等多个任务。
    • 示例
// 符合单一职责原则的函数
function addNumbers(a, b) {
    return a + b;
}
// 不符合单一职责原则的函数
function addAndPrint(a, b) {
    let sum = a + b;
    console.log(sum);
    return sum;
}
  1. 开闭原则(OCP)
    • 解释:软件实体(类、模块、函数等)应该对扩展开放,对修改关闭。在JavaScript中,这意味着当需要添加新功能时,应该通过扩展代码(如添加新函数、新类)而不是修改现有稳定的代码来实现。
    • 示例:假设我们有一个计算图形面积的函数,最初只支持计算矩形面积。
// 原始的计算矩形面积的函数
function calculateRectangleArea(width, height) {
    return width * height;
}
// 扩展支持计算圆形面积,不修改原函数,通过添加新函数来实现开闭原则
function calculateCircleArea(radius) {
    return Math.PI * radius * radius;
}
  1. 里氏替换原则(LSP)
    • 解释:在JavaScript中,这意味着如果一个函数(或方法)接受一个父类型的参数,那么它应该能够正确地处理该父类型的任何子类型。简单来说,子类应该可以替换父类并且程序的行为保持正确。
    • 示例
class Animal {
    makeSound() {
        console.log("Some generic animal sound");
    }
}
class Dog extends Animal {
    makeSound() {
        console.log("Woof!");
    }
}
function animalSound(animal) {
    animal.makeSound();
}
let dog = new Dog();
animalSound(dog); // 这里用Dog类的实例替换Animal类的实例,程序行为正确
  1. 接口隔离原则(ISP)
    • 解释:在JavaScript中,虽然没有像传统编程语言中严格的接口概念,但可以理解为函数或者对象暴露的方法应该是最小化且与调用者相关的。不要强迫客户端(调用代码)依赖它们不需要的方法。
    • 示例:假设我们有一个包含多种方法的对象,不同的使用者可能只需要其中一部分方法。
let utilityObject = {
    // 计算两个数的和
    add: function (a, b) {
        return a + b;
    },
    // 计算两个数的差
    subtract: function (a, b) {
        return a - b;
    },
    // 将字符串转换为大写
    toUpperCase: function (str) {
        return str.toUpperCase();
    }
};
// 使用者1只需要加法和减法运算
function user1(util) {
    let sum = util.add(3, 5);
    let diff = util.subtract(7, 2);
    console.log(sum, diff);
}
// 使用者2只需要字符串转换方法
function user2(util) {
    let newStr = util.toUpperCase("hello");
    console.log(newStr);
}
user1(utilityObject);
user2(utilityObject);
  1. 依赖倒置原则(DIP)
    • 解释:高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该依赖细节,细节应该依赖抽象。在JavaScript中,这可以通过依赖注入等方式来实现。
    • 示例
// 抽象的日志记录器接口
class Logger {
    log(message) {
        throw new Error("Abstract method must be implemented");
    }
}
// 具体的控制台日志记录器实现
class ConsoleLogger extends Logger {
    log(message) {
        console.log(message);
    }
}
// 业务逻辑类,依赖于抽象的日志记录器
class BusinessLogic {
    constructor(logger) {
        this.logger = logger;
    }
    doSomething() {
        let result = "Some operation result";
        this.logger.log(result);
    }
}
// 使用控制台日志记录器注入到业务逻辑类
let consoleLogger = new ConsoleLogger();
let business = new BusinessLogic(consoleLogger);
business.doSomething();
  1. 最少知识原则(迪米特法则)
    • 解释:一个对象应该对其他对象有最少的了解。在JavaScript中,这意味着尽量减少对象之间的耦合,一个模块或者对象不应该深入了解其他模块或对象内部的细节,只需要和它直接相关的部分进行交互。
    • 示例
// 假设我们有三个对象:A、B、C
class A {
    constructor() {
        this.b = new B();
    }
    doSomething() {
        // A对象只通过B对象的公共方法来获取结果,不关心B对象内部如何处理
        let result = this.b.getResult();
        console.log(result);
    }
}
class B {
    constructor() {
        this.c = new C();
    }
    getResult() {
        // B对象内部使用C对象的公共方法来获取数据,不暴露C对象的细节给A对象
        return this.c.getData();
    }
}
class C {
    getData() {
        return "Some data";
    }
}
let a = new A();
a.doSomething();
  1. 组合/聚合复用原则(CARP)
    • 解释:在JavaScript中,优先使用组合或聚合关系来实现复用,而不是继承。组合是指将对象作为另一个对象的属性,聚合是一种特殊的组合,指整体和部分之间的关系。通过组合或聚合,可以使代码更加灵活和可维护。
    • 示例
// 发动机类
class Engine {
    start() {
        console.log("Engine started");
    }
}
// 汽车类,通过组合发动机类来复用发动机的功能
class Car {
    constructor() {
        this.engine = new Engine();
    }
    startCar() {
        this.engine.start();
        console.log("Car started");
    }
}
let myCar = new Car();
myCar.startCar();

vue3 中原则应用体现

  1. 单一职责原则(SRP)
    • 原则解释:一个组件或者函数应该只有一个职责。在Vue 3中,reactive函数就体现了这一原则。
    • 源码实例reactive函数主要职责是将一个普通对象转换为响应式对象。其核心代码(简化版)如下:
function reactive(target) {
    if (isReadonly(target)) {
        return target;
    }
    return createReactiveObject(
        target,
        false,
        mutableHandlers,
        mutableCollectionHandlers
    );
}
  • 这个函数专注于完成对象的响应式转换这一个任务。它通过判断对象是否为只读,然后调用createReactiveObject函数来创建响应式对象,不会涉及到例如组件渲染或者事件处理等其他职责。
  1. 开闭原则(OCP)
    • 原则解释:软件实体(类、模块、函数等)应该对扩展开放,对修改关闭。在Vue 3的插件系统中有所体现。
    • 源码实例:Vue 3允许通过app.use()方法来扩展应用。例如,定义一个简单的插件:
const myPlugin = {
    install(app) {
        app.directive('my - directive', {
            mounted(el) {
                console.log('My directive mounted');
            }
        });
    }
};
const app = createApp(App);
app.use(myPlugin);
  • 这里app对象(createApp返回的应用实例)可以通过use方法添加新的插件,而不需要修改app对象内部关于应用核心功能(如组件渲染、响应式系统等)的代码。通过这种方式,Vue 3的应用可以方便地扩展功能,符合开闭原则。
  1. 里氏替换原则(LSP)
    • 原则解释:在面向对象编程中,子类应该可以替换父类并且程序的行为保持正确。在Vue 3的组件继承(虽然Vue 3组件更强调组合,但也有继承的影子)中可以看到类似思想。
    • 源码实例:假设我们有一个基础组件BaseComponent,和一个继承它的组件SubComponent
<template>
  <div>Base Component</div>
</template>
<script>
export default {
    name: 'BaseComponent'
}
</script>
<template>
  <BaseComponent></BaseComponent>
  <div>Sub Component additional content</div>
</template>
<script>
import BaseComponent from './BaseComponent.vue';
export default {
    name: 'SubComponent',
    components: {
        BaseComponent
    }
}
</script>
  • 在这个简单的例子中,SubComponent使用了BaseComponent,并且添加了额外的内容。在整个Vue应用的渲染过程中,SubComponent在包含BaseComponent的基础上进行扩展,在渲染流程等行为上保持了一致性,类似于里氏替换原则中子类可以替换父类并且程序行为正确的思想。
  1. 接口隔离原则(ISP)
    • 原则解释:函数或者对象暴露的方法应该是最小化且与调用者相关的。在Vue 3的refreactive接口设计中可以体现。
    • 源码实例ref函数主要用于创建一个包含响应式数据的引用对象,reactive函数用于创建一个响应式对象。
import { ref, reactive } from 'vue';
const count = ref(0);
const state = reactive({
    name: 'John',
    age: 30
});
  • 它们各自提供了简洁且有针对性的功能接口。ref针对基本数据类型的响应式处理,reactive针对对象类型的响应式处理。用户可以根据自己的需求选择合适的接口,而不会暴露过多不必要的功能。这符合接口隔离原则,使得开发者在使用这些功能时只关注自己需要的部分。
  1. 依赖倒置原则(DIP)
    • 原则解释:高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该依赖细节,细节应该依赖抽象。在Vue 3的响应式系统和组件系统的分层设计中有体现。
    • 源码实例:在Vue 3的响应式系统中,组件(高层模块)依赖于响应式数据(抽象概念,通过refreactive等函数创建)。而响应式数据的实现细节(如effect的收集和触发、proxy的具体操作等)被封装起来。
// 组件中使用响应式数据
<script setup>
import { ref } from 'vue';
const count = ref(0);
function increment() {
    count.value++;
}
</script>
<template>
  <button @click="increment">{{ count }}</button>
</template>
  • 这里组件只依赖于响应式数据的抽象操作(如ref函数创建的引用和其value属性的更新),而不依赖于响应式系统如何在底层实现数据的监听和更新。这符合依赖倒置原则,使得组件和响应式系统的耦合度降低,便于维护和扩展。
  1. 最少知识原则(迪米特法则)
    • 原则解释:一个对象应该对其他对象有最少的了解。在Vue 3的事件处理机制中有体现。
    • 源码实例:在组件内部进行事件处理时,组件只需要知道如何处理事件,而不需要了解事件是如何在DOM层面或者其他组件内部传播的细节。
<template>
  <button @click="handleClick">Click Me</button>
</template>
<script setup>
function handleClick() {
    console.log('Button clicked');
}
</script>
  • 这个组件中的handleClick函数只关心自己被触发后要执行的逻辑,不需要知道@click事件是如何在浏览器的DOM事件系统中被捕获、冒泡等细节,也不需要了解其他组件是否也在监听这个事件,符合最少知识原则。
  1. 组合/聚合复用原则(CARP)
    • 原则解释:优先使用组合或聚合关系来实现复用,而不是继承。在Vue 3的Composition API中体现明显。
    • 源码实例
import { ref, onMounted } from 'vue';
export default {
    setup() {
        const count = ref(0);
        onMounted(() => {
            console.log('Component mounted');
        });
        return {
            count
        };
    }
}
  • 这里通过组合ref函数和onMounted生命周期钩子来构建组件的逻辑,而不是通过继承一个复杂的基类来获取这些功能。不同的组件可以根据自己的需求灵活地组合各种函数和钩子,实现功能的复用,符合组合/聚合复用原则。

react 原则应用体现

  1. 单一职责原则(SRP)
    • 原则解释:一个组件或者函数应该只有一个主要职责。
    • 体现示例
      • 在React中,组件的设计很好地体现了这一原则。例如,一个简单的Button组件,其主要职责就是渲染一个按钮并处理按钮的点击事件。
import React, { useState } from 'react';

const Button = () => {
    const [count, setCount] = useState(0);
    const handleClick = () => {
        setCount(count + 1);
    };
    return (
        <button onClick={handleClick}>
            Click me! ({count})
        </button>
    );
};

export default Button;
  • 这个Button组件专注于按钮相关的功能,包括维护自身的状态(点击次数)和处理点击事件。它不会同时负责获取数据、进行数据验证等其他无关职责。
  1. 开闭原则(OCP)
    • 原则解释:软件实体(类、模块、函数等)应该对扩展开放,对修改关闭。
    • 体现示例
      • React的高阶组件(HOC)是开闭原则的一个很好体现。例如,有一个基本的组件用于显示用户信息。
const UserInfo = ({ user }) => {
    return (
        <div>
            <p>Name: {user.name}</p>
            <p>Age: {user.age}</p>
        </div>
    );
};
  • 现在我们想要为这个组件添加权限验证功能,而不是修改UserInfo组件本身,我们可以创建一个高阶组件。
const withAuthorization = (WrappedComponent) => {
    return (props) => {
        const isAuthorized = checkAuthorization();// 假设这是一个检查权限的函数
        if (isAuthorized) {
            return <WrappedComponent {...props} />;
        } else {
            return <div>Unauthorized</div>;
        }
    };
};

const AuthorizedUserInfo = withAuthorization(UserInfo);
  • 通过高阶组件,我们可以在不修改UserInfo组件的情况下,为其添加新的功能(权限验证),实现了对扩展开放,对修改关闭。
  1. 里氏替换原则(LSP)
    • 原则解释:在面向对象编程中,子类应该可以替换父类并且程序的行为保持正确。在React中,组件的继承(虽然不常用,但存在这种情况)和组件的替换可以体现这一原则。
    • 体现示例
      • 假设有一个基类组件BaseComponent,它有一个基本的渲染方法。
class BaseComponent extends React.Component {
    render() {
        return <div>Base Component</div>;
    }
}
  • 然后有一个子类组件SubComponent继承自BaseComponent,并对渲染方法进行扩展。
class SubComponent extends BaseComponent {
    render() {
        return (
            <>
                {super.render()}
                <p>Additional content</p>
            </>
        );
    }
}
  • 当在应用中使用SubComponent替换BaseComponent时,程序的行为(如渲染流程)能够正确地进行,因为SubComponent在继承BaseComponent的基础上进行了合理的扩展,符合里氏替换原则。
  1. 接口隔离原则(ISP)
    • 原则解释:函数或者对象暴露的方法应该是最小化且与调用者相关的。
    • 体现示例
      • React的PropsState设计体现了接口隔离原则。一个组件通过Props接收外部传入的数据和方法,并且这些Props通常是与组件功能直接相关的。例如,一个List组件接收一个items数组作为Props
const List = ({ items }) => {
    return (
        <ul>
            {items.map((item, index) => (
                <li key={index}>{item}</li>
            ))}
        </ul>
    );
};
  • 组件只暴露了它需要的接口(这里是接收items作为Props),而不是接收大量无关的数据和方法,使得组件的接口简洁且与调用者(使用List组件的地方)相关,符合接口隔离原则。
  1. 依赖倒置原则(DIP)
    • 原则解释:高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该依赖细节,细节应该依赖抽象。
    • 体现示例
      • 在React中,组件(高层模块)和数据获取逻辑(低层模块)的关系可以体现这一原则。例如,使用React - Redux时,组件并不直接依赖于具体的数据获取方式(如Axios请求等细节),而是依赖于Redux提供的抽象(connect函数或者useSelectoruseDispatch钩子)。
import React from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { fetchDataAction } from './actions';

const MyComponent = () => {
    const data = useSelector((state) => state.data);
    const dispatch = useDispatch();
    React.useEffect(() => {
        dispatch(fetchDataAction());
    }, [dispatch]);
    return (
        <div>
            {data.map((item) => (
                <p>{item}</p>
            ))}
        </div>
    );
};

export default MyComponent;
  • 这里组件通过useSelectoruseDispatch依赖于Redux的抽象接口来获取和更新数据,而不依赖于具体的数据是如何从服务器获取的细节,符合依赖倒置原则。
  1. 最少知识原则(迪米特法则)
    • 原则解释:一个对象应该对其他对象有最少的了解。
    • 体现示例
      • 在React组件的通信中,例如,一个子组件只需要知道从父组件通过Props接收的数据和方法,不需要了解父组件内部是如何获取这些数据或者其他无关的操作。
const ParentComponent = () => {
    const [data, setData] = useState([]);
    const handleDataFetch = () => {
        // 假设这是一个获取数据的复杂操作
        const newData = fetchData();
        setData(newData);
    };
    return (
        <>
            <ChildComponent data={data} onFetch={handleDataFetch} />
        </>
    );
};

const ChildComponent = ({ data, onFetch }) => {
    return (
        <>
            <button onClick={onFetch}>Fetch Data</button>
            <ul>
                {data.map((item, index) => (
                    <li key={index}>{item}</li>
                ))}
            </ul>
        </>
    );
};
  • 子组件ChildComponent只需要知道从父组件接收的数据data和方法onFetch,不需要了解父组件内部是如何获取数据、如何设置状态等其他细节,符合最少知识原则。
  1. 组合/聚合复用原则(CARP)
    • 原则解释:优先使用组合或聚合关系来实现复用,而不是继承。
    • 体现示例
      • React的Hooks是组合/聚合复用原则的典型体现。例如,useStateuseEffect钩子可以在不同的组件中组合使用,以构建各种功能。
import React, { useState, useEffect } from 'react';

const ComponentA = () => {
    const [count, setCount] = useState(0);
    useEffect(() => {
        console.log('ComponentA mounted');
    }, []);
    const handleClick = () => {
        setCount(count + 1);
    };
    return (
        <div>
            <p>Count in ComponentA: {count}</p>
            <button onClick={handleClick}>Increment in ComponentA</button>
        </div>
    );
};

const ComponentB = () => {
    const [text, setText] = useState('');
    useEffect(() => {
        console.log('ComponentB mounted');
    }, []);
    const handleChange = (e) => {
        setText(e.target.value);
    };
    return (
        <div>
            <input type="text" value={text} onChange={handleChange} />
            <p>Text in ComponentB: {text}</p>
        </div>
    );
};
  • 这里ComponentAComponentB通过组合useStateuseEffect钩子来构建自己的功能,而不是通过继承一个通用的基类来实现,体现了组合/聚合复用原则。

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

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

相关文章

Vue04

目录 一、学习目标 1.组件的三大组成部分&#xff08;结构/样式/逻辑&#xff09; 2.组件通信 3.综合案例&#xff1a;小黑记事本&#xff08;组件版&#xff09; 4.进阶语法 二、scoped解决样式冲突 1.默认情况&#xff1a; 三、data必须是一个函数 1、data为什么要写…

C# 探险之旅:第十八节 - 元组(Tuple):神奇的背包与丢弃的艺术,还有变身大法!

嘿&#xff0c;探险家们&#xff01;欢迎再次踏上C#的奇妙旅程。今天&#xff0c;我们要聊的是一个非常实用又有点懒散的旅行伴侣——元组&#xff08;Tuple&#xff09;。想象一下&#xff0c;你正准备来一场说走就走的旅行&#xff0c;但是不想带太多行李&#xff0c;只想简单…

SAP软件如何启用反记账功能

SAP软件和国内ERP软件不一样&#xff0c;它在录入会计凭证时是不可以录入负数的&#xff08;即红冲凭证&#xff09;&#xff0c;因此无法直接实现传统意义上的红字冲销。 比如&#xff0c;如下SAP正常和冲销业务产生会计凭证如下&#xff1a; 正常的业务凭证&#xff1a; 借…

若依-帝可得app后端

视频地址 https://www.bilibili.com/video/BV1pf421B71v?t=510.1 APP后端技术栈 架构解析 验证码功能 开发环境使用改的是固定的验证码 12345正式环境使用的是 阿里云的短信方案@Override public void sendSms(String mobile) {// String code = RandomUtil.randomNumbers(5);…

金融分析-Transformer模型(基础理论)

Transformer模型 1.基本原理 transformer的core是注意力机制&#xff0c;其本质就是编码器-解码器。他可以通过多个编码器进行编码&#xff0c;再把编码完的结果输出给解码器进行解码&#xff0c;然后得到最终的output。 1.1编码器 数据在编码器中会经过一个self-attention的…

JS-手写new

我们先再来理一理原型 Object1 {name:deng,age:18 } Object2 {name:ru,age:18 } const Person function(){} Person.prototype Object1; const p1 new Person(); console.log(p1.name); //deng Person.prototype null; console.log(p1.name); //deng上面给Person的构造函…

深圳国威HB1910数字IP程控交换机 generate.php 远程命令执行漏洞复现

0x01 产品描述: 深圳国威主营国威模拟、数字、IP 交换机、语音网关、IP 电话机及各种电话机。深圳国威电子有限公司HB1910是一款功能强大的网络通信设备,适用于各种企业通信需求。 0x02 漏洞描述: 深圳国威电子有限公司HB1910数字IP程控交换机generate.php存在远程命令执行…

机器学习预处理-表格数据的分析与可视化

机器学习预处理-表格数据的分析与可视化 最近在做一些模型部署的工作&#xff0c;但是发现对于数据的处理、分析、训练方面还是缺少一些系统的学习&#xff0c;因此抽空余时间分析总结一些使用python进行数据处理的实用案例&#xff0c;希望能够方便自己已经其他人的Ctrl CV。…

鸿蒙项目云捐助第六讲鸿蒙App应用的首页导航资讯功能的实现

鸿蒙项目云捐助第六讲鸿蒙App应用的首页导航资讯功能的实现 前面的教程中已实现了启动页&#xff0c;登录页&#xff0c;注册页及首页的部分功能。这里有一些朋友提出问题&#xff0c;如何设置登录页面的背景图片。这里稍带说一个这个功能的实现。 一、登录页面的背景图片实现…

【Vue3】前端使用 FFmpeg.wasm 完成用户视频录制,并对视频进行压缩处理

强烈推荐这篇博客&#xff01;非常全面的一篇文章&#xff0c;本文是对该博客的简要概括和补充&#xff0c;在不同技术栈中提供一种可行思路&#xff0c;可先阅读该篇文章再阅读本篇&#xff1a; FFmpeg——在Vue项目中使用FFmpeg&#xff08;安装、配置、使用、SharedArrayBu…

17、ConvMixer模型原理及其PyTorch逐行实现

文章目录 1. 重点2. 思维导图 1. 重点 patch embedding : 将图形分割成不重叠的块作为图片样本特征depth wise point wise new conv2d : 将传统的卷积转换成通道隔离卷积和像素空间隔离两个部分&#xff0c;在保证精度下降不多的情况下大大减少参数量 2. 思维导图 后续再整…

金蝶云苍穹踩过的坑(慢慢更新)

IDEA不能用最新版&#xff0c;不然搜不到金蝶的插件。 我用的是2024.1.7/2023.1.7 IDEA里增加金蝶插件库的地址也变了&#xff0c;现在是 https://tool.kingdee.com/kddt/idea-updatePlugins.xml 金蝶云苍穹部署在服务器 MAC本地IDEA调试的时候&#xff0c;登录N次能成功一次…

springboot438校园志愿者管理系统(论文+源码)_kaic

摘 要 如今社会上各行各业&#xff0c;都喜欢用自己行业的专属软件工作&#xff0c;互联网发展到这个时候&#xff0c;人们已经发现离不开了互联网。新技术的产生&#xff0c;往往能解决一些老技术的弊端问题。因为传统校园志愿者管理系统信息管理难度大&#xff0c;容错率低&…

高项 - 信息系统管理

个人总结&#xff0c;仅供参考&#xff0c;欢迎加好友一起讨论 博文更新参考时间点&#xff1a;2024-11-09 高项 - 章节与知识点汇总&#xff1a;点击跳转 文章目录 高项 - 信息系统管理管理方法管理基础规划和组织设计和实施运维和服务优化和持续改进 管理要点数据管理运维管…

05、GC基础知识

JVM程序在跑起来之后&#xff0c;在数据的交互过程中&#xff0c;就会有一些数据是过期不用的&#xff0c;这些数据可以看做是垃圾&#xff0c;JVM中&#xff0c;这些垃圾是不用开发者管的&#xff0c;它自己会有一套垃圾回收系统自动回收这些内存垃圾&#xff0c;以备后面继续…

【前端开发】HTML+CSS网页,可以拿来当作业(免费开源)

HTML代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content_lizhongyu"widthdevice-width, initial-scale1.0"><title>小兔鲜儿-新鲜、惠民、快捷<…

【Unity3D】无限循环列表(扩展版)

基础版&#xff1a;【Unity技术分享】UGUI之ScrollRect优化_ugui scrollrect 优化-CSDN博客 using UnityEngine; using UnityEngine.UI; using System.Collections.Generic;public delegate void OnBaseLoopListItemCallback(GameObject cell, int index); public class BaseLo…

Git-基础操作命令

目录 Git基础操作命令 case *查看提交日志 log 版本回退 get add . Git基础操作命令 我们创建并且初始化这个仓库以后&#xff0c;我们就要在里面进行操作。 Git 对于文件的增删改查存在几个状态&#xff0c;这些修改状态会随着我们执行Git的命令而发生变化。 untracked、…

Flutter Navigator2.0的原理和Web端实践

01 背景与动机 在Navigator 2.0推出之前&#xff0c;Flutter主要通过Navigator 1.0和其提供的 API&#xff08;如push(), pop(), pushNamed()等&#xff09;来管理页面路由。然而&#xff0c;Navigator 1.0存在一些局限性&#xff0c;如难以实现复杂的页面操作&#xff08;如移…

【容器】k8s学习笔记基础部分(三万字超详细)

概念 应用部署方式演变 在部署应用程序的方式上&#xff0c;主要经历了三个时代&#xff1a; 传统部署&#xff1a;互联网早期&#xff0c;会直接将应用程序部署在物理机上 优点&#xff1a;简单&#xff0c;不需要其它技术的参与 缺点&#xff1a;不能为应用程序定义资源使…