编写可复用性的模块

news2025/1/7 4:11:15

在生活中,重复的机械劳动会消耗我们的时间和精力,提高生产成本,降低工作效率。同样,在代码世界中,编写重复的代码会导致代码的冗余,页面性能的下降以及后期维护成本的增加。由此可见将重复的事情复用起来是提高生产效率、降低维护成本的不二之选。

在 Vue 项目中,每一个页面都可以看作是由大大小小的模块构成的,即便是一行代码、一个函数、一个组件都可以看作是一个个自由的模块。那么提高代码的复用性的关键便在于编写可复用的模块,也就是编写可复用的代码、函数和组件等。

一个简单的例子

let person = [];

for (let i = 0; i < data.obj.items.length; i++) {
    person.push({
        name: data.obj.items[i].name,
        age: data.obj.items[i].age
    });
}

不知道上方代码给你的第一印象是什么?总之给我的印象是糟糕的,因为出现了重复性的代码片段 data.obj.items,可能这样的代码在我们团队开发中随处可见,这也说明了重复编码现象其实无处不在。

面对自己编写的代码,我们应该保持一颗去重的心,发现重复的地方就相当于找到了可以复用的模块。在不复用的情况下,上述代码一旦需要修改变量 itemslists,那么我们就得修改 3 处地方,不知不觉就增加了维护成本。而到时候往往修改你代码的人并不是你自己,所以对自己好点,对他人也会好点。复用后的代码如下:

let person = [];
let values = data.obj.items;

for (let i = 0; i < values.length; i++) {
    person.push({
        name: values[i].name,
        age: values[i].age
    });
}

我们通过将 data.obj.items 的值赋值给变量 values 来实现了复用,此时修改 itemslists 的话我们只需修改一处地方即可,不管是维护成本还是代码可读性上,复用的优势都显而易见。

封装成一个函数

除了使用变量的赋值缓存使用来解决数据的重复读取外,我们在开发过程中重复性更多的也许是功能点的重复,比如:

<tempalte>
    <div>
        <input type="text" v-model="str1">
        <input type="text" v-model="str2">
        <div>{{ str1.slice(1).toUpperCase() }}</div>
        <div>{{ str2.slice(1).toUpperCase() }}</div>
    </div>
</template>

上述代码的重复功能点在于截取输入框中第二个字符开始到最后的值并把它们转化成大写字母,像这样很简单的操作虽然重复使用也不会出现太大的问题,但是如果是代码量较多的操作呢?重复书写相同功能的代码是一种不经过大脑思考的行为,我们需要对其进行优化,这里我们可以把功能点封装成一个函数:

export default {
    methods: {
        sliceUpperCase(val) {
            return val.slice(1).toUpperCase()
        }
    }
}

如此我们只要在用到该方法的地方调用即可,将值传入其中并返回新值。

当然像在双花括号插值和 v-bind 表达式中重复的功能点我们可以封装成过滤器:

仅做了解,在 Vue 3 中,过滤器被移除了,使用方法或计算属性可以代替它。

// 单文件组件注册过滤器
filters: {
    sliceUpperCase(val) {
        return val.slice(1).toUpperCase()
    }
}

// 全局注册过滤器
Vue.filter('sliceUpperCase', function (val) {
    return val.slice(1).toUpperCase()
})

然后在 html 中使用“管道”符进行过滤:

<div>{{ str1 | sliceUpperCase }}</div>
<div>{{ str2 | sliceUpperCase }}</div>

封装成一个组件

相比较于函数的封装,规模更大一点的便是组件的封装,组件包含了模板、脚本以及样式的代码,在实际开发中组件的使用频率也是非常大的,我们项目中的每一个页面其实都可以看作是一个父组件,其可以包含很多子组件,子组件通过接收父组件的值来渲染页面,父组件通过响应子组件的回调来触发事件。

封装一个组件主要包含两种方式,一种是最常见的整体封装,用户通过改变数据源来呈现不同的页面状态,代码结构不可定制化。例如:

<div>
    <my-component data="我是父组件传入子组件的数据"></my-component>
</div>

另一种便是自定义封装,也就是插槽(slot),我们可以开放一部分槽位给父组件,使其能够进行一定程度的定制化,例如:

<div>
    <my-component data="我是父组件传入子组件的数据">
        <template slot="customize">
            <span>这是定制化的数据</span>
        </template>
    </my-component>
</div>

在 myComponent 组件中我们便可以接收对应的 slot:

<div class="container">
    <span>{{ data }}</span>
    <slot name="customize"></slot>
<div>

这里我们通过定义 slot 标签的 name 值为 customize 来接收父组件在使用该组件时在 template 标签上定义的 slot="customize" 中的代码,不同父组件可以定制不同的 slot 代码来实现差异化的插槽。最终渲染出来的代码如下:

<div>
    <div class="container">
        <span>我是父组件传入子组件的数据</span>
        <span>这是定制化的数据</span>
    </div>
</div>

这样我们就完成了一个小型组件的封装,将共用代码封装到组件中去,页面需要引入的时候直接使用 import 并进行相应注册即可,当然你也可以进行全局的引入:

import myComponent from '../myComponent.vue'

// 全局
Vue.component('my-component', myComponent)

写了一个完整的例题,方便大家理解

我们将创建一个名为 BaseButton.vue 的按钮组件,该组件支持自定义文本、颜色和点击事件。

在 Vue 项目中,创建一个新的组件文件 BaseButton.vue

<template>
  <button
    :class="buttonClass"
    @click="handleClick"
    :style="{ backgroundColor: bgColor, color: textColor }"
  >
    <slot>{{ text }}</slot>
  </button>
</template>

<script>
export default {
  name: 'BaseButton',
  props: {
    text: {
      type: String,
      default: 'Button',
    },
    bgColor: {
      type: String,
      default: '#42b983',
    },
    textColor: {
      type: String,
      default: '#ffffff',
    },
  },
  computed: {
    buttonClass() {
      return {
        'base-button': true,
        'base-button--primary': this.bgColor === '#42b983',
        'base-button--secondary': this.bgColor === '#35495e',
      };
    },
  },
  methods: {
    handleClick(event) {
      this.$emit('click', event);
    },
  },
};
</script>

<style scoped>
.base-button {
  padding: 10px 20px;
  border: none;
  border-radius: 5px;
  font-size: 16px;
  cursor: pointer;
  transition: background-color 0.3s;
}

.base-button:hover {
  opacity: 0.9;
}
</style>

解释一下buttonClass 计算属性的作用

  1. 'base-button': true:

    • 这个条目保证了所有按钮都将始终拥有 base-button 类。
  2. 'base-button--primary': this.bgColor === '#42b983':

    • 当 bgColor 的值为 #42b983 时,计算属性返回 true,因此将 base-button--primary 类添加到按钮的类列表中,下面的同理。

Vue 会将 buttonClass 的返回值解析为按钮的 CSS 类。这样,根据 bgColor 的变化,按钮的外观可以动态调整,以便于根据不同的背景颜色应用不同的样式。这种方法使得组件更加灵活、可维护且计算属性会自动缓存,只有在依赖的 bgColor 属性发生变化时才会重新计算,从而提高性能。

在你的主组件或其他组件中使用 BaseButton 组件。假设我们在 App.vue 中使用它

<template>
  <div id="app">
    <BaseButton
      text="Primary Button"
      bgColor="#42b983"
      textColor="#ffffff"
      @click="onButtonClick"
    />
    <BaseButton
      text="Secondary Button"
      bgColor="#35495e"
      textColor="#ffffff"
      @click="onButtonClick"
    >
      Custom Slot Button
    </BaseButton>
  </div>
</template>

<script>
import BaseButton from './components/BaseButton.vue';

export default {
  name: 'App',
  components: {
    BaseButton,
  },
  methods: {
    onButtonClick(event) {
      console.log('Button clicked!', event);
    },
  },
};
</script>

<style>
#app {
  text-align: center;
  margin: 20px;
}
</style>
  • 属性BaseButton 组件接收三个 props:

    • text:按钮上的文本,默认为"Button"。
    • bgColor:按钮的背景颜色,默认为 #42b983
    • textColor:按钮的文本颜色,默认为 #ffffff

封装成一个插件

在某些情况下,我们封装的内容可能不需要使用者对其内部代码结构进行了解,其只需要熟悉我们提供出来的相应方法和 api 即可,这需要我们更系统性的将公用部分逻辑封装成插件,来为项目添加全局功能,比如常见的 loading 功能、弹框功能等。

Vue 提供给了我们一个 install 方法来编写插件,使用该方法中的第一个 Vue 构造器参数可以为项目添加全局方法、资源、选项等。比如我们可以给组件添加一个简单的全局调用方法来实现插件的编写:

/* toast.js */
import ToastComponent from './toast.vue' // 引入组件

let $vm

export default {    
    install(Vue, options) {
        
        // 判断实例是否存在
        if (!$vm) {            
            const ToastPlugin = Vue.extend(ToastComponent); // 创建一个“扩展实例构造器”
            
            // 创建 $vm 实例
            $vm = new ToastPlugin({                
                el: document.createElement('div')  // 声明挂载元素          
            });            
            
            document.body.appendChild($vm.$el); // 把 toast 组件的 DOM 添加到 body 里
        } 
        
        // 给 toast 设置自定义文案和时间
        let toast = (text, duration = options.duration || 3000) => {
            $vm.text = text;
            $vm.duration = duration;
            
            // 在指定 duration 之后让 toast 消失
            setTimeout(() => {
                $vm.isShow = false;  
            }, $vm.duration);
        }
        
        // 判断 Vue.$toast 是否存在
        if (!Vue.$toast) {            
            Vue.$toast = toast;        
        }        
        
        Vue.prototype.$toast = Vue.$toast; // 全局添加 $toast 事件
    }
}

成功编写完插件的 JS 脚本后,我们在入口文件中需要通过 Vue.use() 来注册一下该插件:

import Toast from '@/widgets/toast/toast.js'

Vue.use(Toast); // 注册 Toast

最后我们在需要调用它的地方直接传入配置项使用即可,比如:

this.$toast('Hello World', 2000);

当然你也可以不使用 install 方法来编写插件,直接采用导出一个封装好的实例方法并将其挂载到 Vue 的原型链上来实现相同的功能。

拓展

1.在 Vue 中如何添加全局自定义指令?

1. 创建全局自定义指令

全局自定义指令可以通过 Vue 实例的 directive 方法来注册。下面是一个示例,展示如何创建一个简单的自定义指令,该指令用于改变元素的背景颜色。

示例:创建一个 v-color 指令

// main.js
import Vue from 'vue';
import App from './App.vue';

// 注册全局自定义指令
Vue.directive('color', {
  // 当被绑定的元素插入到 DOM 中时调用
  inserted(el, binding) {
    el.style.backgroundColor = binding.value; // 设置背景颜色
  }
});

new Vue({
  render: h => h(App),
}).$mount('#app');

在上面的代码中,我们创建了一个名为 v-color 的指令。当这个指令被绑定到一个元素时,它会将该元素的背景颜色设置为传入的值。

2. 在组件中使用自定义指令

一旦我们定义了全局指令,就可以在任何 Vue 组件中使用它。以下是如何在一个组件中使用 v-color 指令的示例:

<template>
  <div>
    <h1 v-color="'lightblue'">这是一个标题</h1>
    <p v-color="'lightgreen'">这是一个段落</p>
  </div>
</template>

<script>
export default {
  name: 'MyComponent'
}
</script>

<style>
/* 样式可以在这里定义 */
</style>

3. 自定义指令的钩子函数

全局自定义指令有以下几个钩子函数,可以用于不同的生命周期阶段:

  • bind(el, binding, vnode): 指令第一次绑定到元素时调用,只调用一次。
  • inserted(el, binding, vnode): 被绑定元素插入父节点时调用。
  • update(el, binding, vnode, oldVnode): 被绑定元素所在的 VNode 更新时调用。
  • componentUpdated(el, binding, vnode, oldVnode): 指令所在组件的 VNode 及其子 VNode 更新时调用。
  • unbind(el, binding, vnode): 只调用一次,指令与元素解绑时调用。

示例:使用更多的钩子函数

下面是一个更复杂的自定义指令示例,演示了如何使用多个钩子:

// main.js
Vue.directive('highlight', {
  // 绑定时
  bind(el) {
    el.style.transition = 'background-color 0.5s';
  },
  // 插入时
  inserted(el) {
    el.style.backgroundColor = 'yellow';
  },
  // 更新时
  update(el, binding) {
    el.style.backgroundColor = binding.value;
  },
  // 解绑时
  unbind(el) {
    el.style.backgroundColor = '';
  }
});

在这个例子中,v-highlight 指令会在绑定时设置过渡效果,并在元素插入时将背景色设置为黄色。它还会在更新时根据传入值改变背景色,并在解除绑定时清除样式。

4. 使用指令修饰符

指令也可以使用修饰符(如 .stop, .prevent, .self 等),以提供更灵活的功能。例如,如果你希望在点击元素时阻止事件冒泡,可以使用 v-on:click.stop

2.在 vue 路由切换时如何全局隐藏某个插件?

在路由切换时,你可以在 beforeEachbeforeResolve 钩子中调用隐藏 Toast 的方法。

下面是一个示例,展示如何在 Vue Router 中实现这一功能。

1. 创建 Toast 插件

这里是一个简单的示例:

// toast.js
let $vm;

const ToastPlugin = {
  install(Vue) {
    if (!$vm) {
      const ToastComponent = Vue.extend({
        data() {
          return {
            isShow: false,
            text: '',
            duration: 3000
          };
        },
        template: `<div v-if="isShow" class="toast">{{ text }}</div>`,
        methods: {
          show(text, duration = this.duration) {
            this.text = text;
            this.isShow = true;
            setTimeout(() => {
              this.isShow = false;
            }, duration);
          },
          hide() {
            this.isShow = false;
          }
        }
      });

      $vm = new ToastComponent({ el: document.createElement('div') });
      document.body.appendChild($vm.$el);
    }

    Vue.prototype.$toast = {
      show(text, duration) {
        $vm.show(text, duration);
      },
      hide() {
        $vm.hide();
      }
    };
  }
};

export default ToastPlugin;

2. 在 Vue Router 中使用导航守卫

接下来,设置 Vue Router 并在路由切换时调用 Toast 的 hide 方法:

// router.js
import Vue from 'vue';
import Router from 'vue-router';
import ToastPlugin from './toast';  // 导入 Toast 插件

Vue.use(Router);
Vue.use(ToastPlugin);  // 使用 Toast 插件

const routes = [
  // 定义你的路由
];

const router = new Router({
  routes
});

// 在路由切换前隐藏 Toast
router.beforeEach((to, from, next) => {
  // 调用 Toast 的 hide 方法以隐藏 Toast
  Vue.prototype.$toast.hide();
  next(); // 继续路由导航
});

export default router;

3. 在主入口文件中整合

将路由和 Toast 插件整合到主入口文件中:

// main.js
import Vue from 'vue';
import App from './App.vue';
import router from './router';  // 导入路由

Vue.config.productionTip = false;

new Vue({
  router,
  render: h => h(App),
}).$mount('#app');

4. 使用 Toast 插件

在你的组件中使用 Toast 插件:

<template>
  <div>
    <button @click="showToast">显示 Toast</button>
  </div>
</template>

<script>
export default {
  methods: {
    showToast() {
      this.$toast.show('这是一个 Toast 提示!', 2000);
    }
  }
}
</script>

5. 完整效果

通过以上步骤,当你在应用中的任意位置使用 $toast.show 方法时,Toast 会显示。在每次路由切换时,beforeEach 钩子会调用 $toast.hide 方法,从而确保在新路由加载时 Toast 被隐藏。

3.如何实现一个表单验证插件?需要运用到哪些知识?

需要掌握以下知识点:

  • Vue 的插件机制:理解如何创建和使用 Vue 插件。
  • Vue 的混入(Mixin):使用混入将验证逻辑添加到组件中。
  • Vue 的数据响应性:使用 this.$set 来确保响应式地更新错误信息。
  • 事件处理:处理表单输入和提交事件。
  • 条件渲染:使用 v-if 条件渲染错误信息。

1. 创建基本的插件结构

目录结构示例:

/form-validator
  ├── index.js        // 插件入口
  ├── validator.js    // 验证逻辑
  └── styles.css      // 样式(可选)

2. 编写验证逻辑

创建一个 validator.js 文件,定义你的验证规则和逻辑。

// validator.js
const validators = {
  required(value) {
    return !!value || '该字段是必填的';
  },
  email(value) {
    const re = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
    return re.test(value) || '请输入有效的邮箱地址';
  },
  minLength(min) {
    return value => {
      return value.length >= min || `至少需要 ${min} 个字符`;
    };
  },
  maxLength(max) {
    return value => {
      return value.length <= max || `最多 ${max} 个字符`;
    };
  },
  // 可以添加更多验证规则
};

export default validators;

3. 创建插件入口文件

index.js 中,定义插件的 API 和如何与 Vue 组件进行交互。

// index.js
import validators from './validator';

const FormValidator = {
  install(Vue) {
    Vue.mixin({
      data() {
        return {
          formErrors: {}, // 存储表单错误信息
        };
      },
      methods: {
        validateField(fieldName, value, rules) {
          const errors = [];
          rules.forEach(rule => {
            const validate = typeof rule === 'function' ? rule : validators[rule];
            const result = validate(value);
            if (typeof result === 'string') {
              errors.push(result);
            }
          });
          this.$set(this.formErrors, fieldName, errors);
        },
        validateForm(fields) {
          this.formErrors = {};
          let isValid = true;

          for (const field in fields) {
            const { value, rules } = fields[field];
            this.validateField(field, value, rules);
            if (this.formErrors[field].length) {
              isValid = false;
            }
          }

          return isValid;
        },
      },
    });
  },
};

export default FormValidator;

4. 使用插件

在你的 Vue 组件中使用这个插件。确保在你的主入口文件中安装该插件。

// main.js
import Vue from 'vue';
import App from './App.vue';
import FormValidator from './form-validator';

Vue.use(FormValidator);

new Vue({
  render: h => h(App),
}).$mount('#app');

5. 示例组件

创建一个示例组件,展示如何使用这个表单验证插件。

<template>
  <form @submit.prevent="handleSubmit">
    <div>
      <label for="email">邮箱:</label>
      <input type="text" v-model="email" @blur="validateField('email', email, ['required', 'email'])" />
      <span v-if="formErrors.email.length">{{ formErrors.email[0] }}</span>
    </div>
    <div>
      <label for="password">密码:</label>
      <input type="password" v-model="password" @blur="validateField('password', password, [minLength(6)])" />
      <span v-if="formErrors.password.length">{{ formErrors.password[0] }}</span>
    </div>
    <button type="submit">提交</button>
  </form>
</template>

<script>
export default {
  data() {
    return {
      email: '',
      password: '',
    };
  },
  methods: {
    handleSubmit() {
      const isValid = this.validateForm({
        email: { value: this.email, rules: ['required', 'email'] },
        password: { value: this.password, rules: [this.minLength(6)] },
      });

      if (isValid) {
        // 表单有效,执行提交逻辑
        alert('表单提交成功!');
      }
    },
  },
};
</script>

<style>
/* 添加一些样式 */
</style>

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

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

相关文章

三甲医院等级评审八维数据分析应用(一)--组织、制度、管理可视化篇

一、引言 1.1 研究背景与意义 在当今医疗领域,三甲医院作为医疗服务的核心载体,肩负着保障民众健康、推动医学进步的重任。随着信息技术的飞速发展,数据已成为医院运营管理、医疗质量提升以及科学决策的关键要素。三甲医院等级评审作为衡量医院综合实力与服务水平的重要标…

Spring Bean的初始化过程是怎么样的?

文章内容收录到个人网站&#xff0c;方便阅读&#xff1a;http://hardyfish.top/ 文章内容收录到个人网站&#xff0c;方便阅读&#xff1a;http://hardyfish.top/ 文章内容收录到个人网站&#xff0c;方便阅读&#xff1a;http://hardyfish.top/ Spring Bean 的初始化过程主…

快速上手LangChain(四)LangChain Hub和LangSmith

文章目录 快速上手LangChain&#xff08;四&#xff09;LangChain Hub和LangSmith什么是LangChain HubLangChain Hub功能 LangSmith使用 快速上手LangChain&#xff08;四&#xff09;LangChain Hub和LangSmith 什么是LangChain Hub LangChain Hub官网地址&#xff1a;https:…

无人机遥控器频率解析!

1.4GHz无人机遥控器工作核心技术 传输距离&#xff1a;1.4GHz频率的无人机遥控器具有较远的传输距离&#xff0c;这使得无人机可以在较大范围内与地面控制站或其他通信节点进行可靠的通信。这种特性特别适用于需要覆盖较大区域的任务或远距离飞行的场景。 穿透力&#xff1a;…

TypyScript从入门到精通

TypyScript从入门到精通 TypyScript 是什么&#xff1f;增加了什么环境搭建二、为何需要 TypeScript三、编译 TypeScript四、类型声明五、类型推断基本类型六、类型总览JavaScript 中的数据类型TypeScript 中的数据类型1. 上述所有 JavaScript 类型2. 六个新类型&#xff1a;3.…

RabbitMq的Java项目实践

在现代软件开发中&#xff0c;消息队列&#xff08;Message Queue&#xff0c;简称MQ&#xff09;作为一种重要的组件&#xff0c;承担着上下游消息传递和通信的重任。RabbitMQ作为一款流行的开源消息队列中间件&#xff0c;凭借其高可用性、可扩展性和易用性等特点&#xff0c…

CK40N或CK24标准成本发布出现标记不到物料的情况:评估视图中允许的成本核算变式选择错误

用户打电话反馈标准成本发布在标记环节出现错误&#xff1a; 检查&#xff1a; 1、MM03已经维护了税价1。 2、CK13N&#xff1a; 没有成本没本滚算。 用户是用CK40N处理的&#xff0c; 我让他用CK11N/CK24再处理一次。 仍然报错. 我也试了一个也是报错。 准备CRK1删除原来的…

【HENU】河南大学计院2024 计算机体系结构 期末复习知识点

和光同尘_我的个人主页 一直游到海水变蓝。 体系结构 第一章&#xff1a;计算机系统基础知识计算机系统的实质计算机系统的设计的4个定量原理Amdahl定律CPU性能公式程序的局部性原理: 第二章&#xff1a;指令系统的设计指令系统结构的分类通用寄存器型结构 哈夫曼编码MIPS指令…

Docker 远程访问完整配置教程以及核心参数理解

Docker 远程访问完整配置教程 以下是配置 Docker 支持远程访问的完整教程&#xff0c;包括参数说明、配置修改、云服务器安全组设置、主机防火墙配置&#xff0c;以及验证远程访问的详细步骤。 1. 理解 -H fd:// 参数的作用&#xff08;理解了以后容易理解后面的操作&#xff…

如何在不丢失数据的情况下从 IOS 14 回滚到 IOS 13

您是否后悔在 iPhone、iPad 或 iPod touch 上安装 iOS 14&#xff1f;如果你这样做&#xff0c;你并不孤单。许多升级到 iOS 14 beta 的 iPhone、iPad 和 iPod touch 用户不再适应它。 如果您在正式发布日期之前升级到 iOS 14 以享受其功能&#xff0c;但您不再适应 iOS 14&am…

vue3 css实现文字输出带光标显示,文字输出完毕,光标消失的效果

Vue实现过程如下&#xff1a; <template><div ><p ref"dom_element" class"typing" :class"{over_fill: record_input_over}"></p></div> </template> <script setup> import {onMounted, ref} from…

Postman测试big-event

报错500。看弹幕&#xff0c;知道可能是yml或sql有问题。 所以检查idea工作台&#xff0c; 直接找UserMapper检查&#xff0c;发现完全OK。 顺着这个error发现可能是sql有问题。因为提示是sql问题&#xff0c;而且是有now()的那个sql。 之后通过给的课件&#xff0c;复制课件…

Wonder Dynamics技术浅析(八):实拍与虚拟合成

该模块旨在将实拍视频与计算机生成的虚拟场景无缝融合&#xff0c;生成具有高度真实感的视觉效果。 一、实拍视频与虚拟场景合成概述 实拍视频与虚拟场景合成的主要目标是将实拍视频中的元素与计算机生成的虚拟场景进行无缝融合&#xff0c;生成具有高度真实感的最终影像。 …

Javascript算法——回溯算法(子集和全排列问题)

子集问题 思路 如果把 子集问题、组合问题、分割问题都抽象为一棵树的话&#xff0c;那么组合问题和分割问题都是收集树的叶子节点&#xff0c;而子集问题是找树的所有节点&#xff01; 78.子集 相比组合问题&#xff0c;此子集问题题目更为简单&#xff0c;收集的是树的所有…

网络安全系统学习实验1:RDP远程登录配置

准备工作&#xff1a; 0、准备好虚拟机 1、服务器侧&#xff08;虚拟机Windows 2003-01&#xff09;IP地址&#xff1a; # 获得服务器的IP地址192.168.58.223 ipconfig /all2、客户端侧(虚拟机Win7 pte_czj)IP地址&#xff1a; # 客户端侧IP地址192.168.58.222 ipconfig /al…

SMMU软件指南之系统架构考虑

安全之安全(security)博客目录导读 目录 5.1 I/O 一致性 5.2 客户端设备 5.2.1 地址大小 5.2.2 缓存 5.3 PCIe 注意事项 5.3.1 点对点通信 5.3.2 No_snoop 5.3.3 ATS 5.4 StreamID 分配 5.5 MSI 本博客介绍与 SMMU 相关的一些系统架构注意事项。 5.1 I/O 一致性 如…

[网络安全]sqli-labs Less-3 解题详析

判断注入类型 GET1 and 11&#xff0c;回显如下&#xff1a;GET1 and 12&#xff1a;没有回显&#xff0c;说明该漏洞类型为GET型单引号字符型注入 判断注入点个数 GET1 order by 2 --&#xff0c;回显如下&#xff1a;由上图可知&#xff0c;sql语法中给$id加上了() 猜测后…

vulnhub Earth靶机

搭建靶机直接拖进来就行 1.扫描靶机IP arp-scan -l 2.信息收集 nmap -sS -A -T4 192.168.47.132 得到两个DNS; 在443端口处会让我们加https dirb https://earth.local/ dirb https://terratest.earth.local/ #页面下有三行数值 37090b59030f11060b0a1b4e0000000000004312170a…

AWS 申请证书、配置load balancer、配置域名

申请AWS证书 点击 request 申请完证书&#xff0c;AWS 会验证你对于域名的所有权&#xff0c;有两种方式&#xff0c;DSN 验证和邮箱验证。 这里说一下DSN 验证&#xff0c;上图中 Domains 中有CNAME name 和 CNAME value 。 在domain 网站中添加一个CNAME DSN 项&#xff0c;…

【WPF】 数据绑定机制之INotifyPropertyChanged

INotifyPropertyChanged 是 WPF 中的一个接口&#xff0c;用于实现 数据绑定 中的 属性更改通知。它的主要作用是&#xff0c;当对象的某个属性值发生更改时&#xff0c;通知绑定到该属性的 UI 控件更新其显示内容。 以下是有关 INotifyPropertyChanged 的详细信息和实现方法&…