Vue2高级用法

Vue2高级用法

  • 1、mixin复用【vue不会用了,了解一下】
    • 1.1 基础使用
    • 1.2 选项合并
    • 1.3 全局混入
    • 1.4 细数 mixin 存在的问题
  • 2、vue.js 动画特效& 常见组件库介绍
    • 2.1 进入/离开基础使用示例
    • 2.2 进入/离开自定义过度类名
    • 2.3 进入/离开动画钩子
    • 2.4 多组件过渡与列表过渡
    • 2.5 状态过渡
    • 2.6 常用动画相关库
  • 3、 插槽
    • 3.1 插槽的三种使用方法
  • 4、插件
    • 4.1 定义插件
    • 4.2 使用插件
    • 4.3 插件化机制原理
    • 4.4 具体实践
  • 5、过滤器
    • 5.1 使用过滤器
    • 5.2 定义过滤器
    • 5.3 串联过滤器

1、mixin复用【vue不会用了,了解一下】

mixin实现复用的同时带来了很多问题,例如:命名污染依赖不透明
Vue3 用 Composition API替代

1.1 基础使用

混入 (mixin) 提供了一种非常灵活的方式,来分发 Vue 组件中的可复用功能。
例子:

// 定义一个混入对象
var myMixin = {created: function () {this.hello()},methods: {hello: function () {console.log('hello from mixin!')}}
}// 定义一个使用混入对象的组件
var Component = Vue.extend({mixins: [myMixin]
})var component = new Component() // => "hello from mixin!"

1.2 选项合并

当组件和混入对象含有同名选项时,这些选项将以恰当的方式进行“合并”。

  • 值为对象的选项:合并成一个对象,同名的话,组件的值会覆盖混入对象
  • 钩子函数:合并成一个数组,都执行,混入对象的钩子先执行,组件后执行(组件的函数覆盖混入的)

比如,数据对象在内部会进行递归合并,并在发生冲突时以组件数据优先。

var mixin = {data: function () {return {message: 'hello',foo: 'abc'}}
}new Vue({mixins: [mixin],data: function () {return {message: 'goodbye',bar: 'def'}},created: function () {console.log(this.$data)// => { message: "goodbye", foo: "abc", bar: "def" }}
})

同名钩子函数将合并为一个数组,因此都将被调用。另外,混入对象的钩子将在组件自身钩子之前调用。

var mixin = {created: function () {console.log('混入对象的钩子被调用')}
}new Vue({mixins: [mixin],created: function () {console.log('组件钩子被调用')}
})// => "混入对象的钩子被调用"
// => "组件钩子被调用"

值为对象的选项,例如 methods、components 和 directives,将被合并为同一个对象。两个对象键名冲突时,取组件对象的键值对。

var mixin = {methods: {foo: function () {console.log('foo')},conflicting: function () {console.log('from mixin')}}
}var vm = new Vue({mixins: [mixin],methods: {bar: function () {console.log('bar')},conflicting: function () {console.log('from self')}}
})vm.foo() // => "foo"
vm.bar() // => "bar"
vm.conflicting() // => "from self"

注意:Vue.extend() 也使用同样的策略进行合并。

1.3 全局混入

混入也可以进行全局注册。使用时格外小心!一旦使用全局混入,它将影响每一个之后创建的 Vue 实例。使用恰当时,这可以用来为自定义选项注入处理逻辑。

// 为自定义的选项 'myOption' 注入一个处理器。
Vue.mixin({created: function () {var myOption = this.$options.myOptionif (myOption) {console.log(myOption)}}
})new Vue({myOption: 'hello!'
})
// => "hello!"

1.4 细数 mixin 存在的问题

  1. 命名冲突:vue组件的值会覆盖mixin选项,相同类型的生命周期钩子添加到同一个数组里依次执行
  2. 依赖不透明:mixin 和使用它的组件之间没有层次关系。组件可以用mixin的数据,mixin可以用设定在vue里的数据(如上文的this.$options.myOption)。这样要是修改mixin,就比较复杂。

2、vue.js 动画特效& 常见组件库介绍

Vue 在插入、更新或者移除 DOM 时,提供多种不同方式的应用过渡效果。包括以下工具:

  • 在 CSS 过渡和动画中自动应用 class
  • 可以配合使用第三方 CSS 动画库,如 Animate.css
  • 在过渡钩子函数中使用 JavaScript 直接操作 DOM
  • 可以配合使用第三方 JavaScript 动画库,如 Velocity.js;

Vue 提供了 transition 的封装组件,在下列情形中,可以给任何元素和组件添加进入/离开过渡

  • 条件渲染 (使用 v-if)
  • 条件展示 (使用 v-show)
  • 动态组件
  • 组件根节点

2.1 进入/离开基础使用示例

<div id="demo"><button v-on:click="show = !show">Toggle</button><transition name="fade"><p v-if="show">hello</p></transition>
</div>
.fade-enter-active, .fade-leave-active {transition: opacity .5s;
}
.fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {opacity: 0;
}
export default {data() {show: true}
}

在这里插入图片描述

2.2 进入/离开自定义过度类名

<link href="https://cdn.jsdelivr.net/npm/animate.css@3.5.1" rel="stylesheet" type="text/css">
<div id="example-3"><button @click="show = !show">Toggle render</button><transitionname="custom-classes-transition"enter-active-class="animated tada"leave-active-class="animated bounceOutRight"><p v-if="show">hello</p></transition>
</div>

2.3 进入/离开动画钩子

<transitionv-on:before-enter="beforeEnter"v-on:enter="enter"v-on:after-enter="afterEnter"v-on:enter-cancelled="enterCancelled"v-on:before-leave="beforeLeave"v-on:leave="leave"v-on:after-leave="afterLeave"v-on:leave-cancelled="leaveCancelled"
><!-- ... -->
</transition>

2.4 多组件过渡与列表过渡

<div id="list-demo" class="demo"><button v-on:click="add">Add</button><button v-on:click="remove">Remove</button><transition-group name="list" tag="p"><span v-for="item in items" v-bind:key="item" class="list-item">{{ item }}</span></transition-group>
</div>
{data: {items: [1,2,3,4,5,6,7,8,9],nextNum: 10},methods: {randomIndex: function () {return Math.floor(Math.random() * this.items.length)},add: function () {this.items.splice(this.randomIndex(), 0, this.nextNum++)},remove: function () {this.items.splice(this.randomIndex(), 1)},}
}
.list-item {display: inline-block;margin-right: 10px;
}
.list-enter-active, .list-leave-active {transition: all 1s;
}
.list-enter, .list-leave-to
/* .list-leave-active for below version 2.1.8 */ {opacity: 0;transform: translateY(30px);
}

2.5 状态过渡

通过状态去驱动视图更新从而实现动画过渡

<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.2.4/gsap.min.js"></script><div id="animated-number-demo"><input v-model.number="number" type="number" step="20"><p>{{ animatedNumber }}</p>
</div>
{data: {number: 0,tweenedNumber: 0},computed: {animatedNumber: function() {return this.tweenedNumber.toFixed(0);}},watch: {number: function(newValue) {gsap.to(this.$data, { duration: 0.5, tweenedNumber: newValue });//gsap js动画库, gsap.to('要变化的对象,数据对象或者dom对象',{对象里变化的参数},)}}
}

2.6 常用动画相关库

  • gsap
  • animated.css
  • tween.js

3、 插槽

插槽 slot 是写在子组件的代码中,供父组件使用的占位符

3.1 插槽的三种使用方法

  • 默认插槽:没有名字,普通的
  • 具名插槽:带名字,父组件可以根据名字插入子组件的对应的位置(多个,区分占位符位置)<slot name='‘header’>(区分位置)
  • 作用域插槽:父组件可以使用子组件插槽传过来的games数据(传值)

ps: vue 2.6.0版本之后的slot插槽: 用v-slot:default=‘ctx’ 替代slot=‘’。

默认和具名案例:

<template><div class="parent">我是父组件<Child></Child></div>
</template><script>
import Child from './components/Child.vue'export default {name: 'app',components: {Child}
}
</script><style>
.parent {font-family: 'Avenir', Helvetica, Arial, sans-serif;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;text-align: center;color: #2c3e50;margin-top: 60px;padding:10px;background-color:#eee;
}
</style>
<template><div class="hello">我是子组件<!-- 如果父组件没有填充内容,就显示slot里的默认内容,如果父组件填充内容,显示父组件的内容 --><div><!-- 具名插槽 --><slot name="header">把头放这里</slot> </div><div><!-- 默认插槽 --><slot>这里是默认插槽</slot> </div><div><!-- 具名插槽 --><slot name="footer">把尾巴放这里</slot></div></div>
</template><script>
export default {name: 'Child',}
</script><!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>.hello{background-color: #097493;color: #fff;padding:20px;
}
.hello>div{padding:10px;border: 1px solid red;margin: 5px;
}
</style>

当父组件什么都没传时,子组件按自己默认的显示
在这里插入图片描述
当父组件填入对应内容,将会替换子组件的默认占位(子组件也可以不设置默认内容)
父组件改为

<template><div class="parent">我是父组件<Child><div slot="header"> 替换头部内容</div><div slot="header">替换头部内容2</div><div slot="footer">替换底部内容</div><div>没有定义slot='',默认放默认插槽</div><div>如果再来一个默认插槽呢,都会进入默认插槽里</div></Child></div>
</template><script>
import Child from './components/Child.vue'export default {name: 'app',components: {Child}
}
</script><style>
.parent {font-family: 'Avenir', Helvetica, Arial, sans-serif;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;text-align: center;color: #2c3e50;margin-top: 60px;padding:10px;background-color:#eee;
}
</style>

显示:
在这里插入图片描述
作用域插槽:子组件定义数据,传出去,在父组件用slot-scope接收并使用,就是作用域插槽的功能

<template><div class="parent">我是父组件<Child><div slot="header" > 替换头部内容</div><div slot="footer" slot-scope="user">替换底部内容{{user.games}}</div><div slot-scope="{games}">没有定义slot='',默认放默认插槽{{games}}</div></Child></div>
</template><script>
import Child from './components/Child.vue'export default {name: 'app',components: {Child}
}
</script><style>
.parent {font-family: 'Avenir', Helvetica, Arial, sans-serif;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;text-align: center;color: #2c3e50;margin-top: 60px;padding:10px;background-color:#eee;
}
</style>
<template><div class="hello">我是子组件<!-- 如果父组件没有填充内容,就显示slot里的默认内容,如果父组件填充内容,显示父组件的内容 --><div><!-- 具名插槽 --><slot :games="games" name="header">把头放这里</slot> </div><div><!-- 默认插槽 --><slot :games="games">这里是默认插槽</slot> </div><div><!-- 具名插槽 --><slot :games="games" name="footer">把尾巴放这里</slot></div></div>
</template><script>
export default {name: 'Child',data() {return {games:['王者荣耀','吃鸡','斗地主']}},
}
</script><!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>.hello{background-color: #097493;color: #fff;padding:20px;
}
.hello>div{padding:10px;border: 1px solid red;margin: 5px;
}
</style>

显示:
在这里插入图片描述

4、插件

插件可以是对象,或者是一个函数。如果是对象,那么对象中需要提供 install 函数,如果是函数,形态需要跟前面提到的 install 函数保持一致。
install 是组件安装的一个方法,跟 npm install 完全不一样,npm install 是一个命令

4.1 定义插件

const MyPlugin = {install(Vue, options) {// 1. 添加全局方法或 propertyVue.myGlobalMethod = function () {// 逻辑...}// 2. 添加全局资源Vue.directive('my-directive', {bind (el, binding, vnode, oldVnode) {// 逻辑...}...})// 3. 注入组件选项Vue.mixin({created: function () {// 逻辑...}...})// 4. 添加实例方法Vue.prototype.$myMethod = function (methodOptions) {// 逻辑...}}
};

4.2 使用插件

Vue.use(MyPlugin);{{ $myMethod }}

4.3 插件化机制原理

export function initUse (Vue: GlobalAPI) {Vue.use = function (plugin: Function | Object) {// 获取已经安装的插件const installedPlugins = (this._installedPlugins || (this._installedPlugins = []))// 看看插件是否已经安装,如果安装了直接返回if (installedPlugins.indexOf(plugin) > -1) {return this}// toArray(arguments, 1)实现的功能就是,获取Vue.use(plugin,xx,xx)中的其他参数。// 比如 Vue.use(plugin,{size:'mini', theme:'black'}),就会回去到plugin意外的参数const args = toArray(arguments, 1)// 在参数中第一位插入Vue,从而保证第一个参数是Vue实例args.unshift(this)// 插件要么是一个函数,要么是一个对象(对象包含install方法)if (typeof plugin.install === 'function') {// 调用插件的install方法,并传入Vue实例plugin.install.apply(plugin, args)} else if (typeof plugin === 'function') {plugin.apply(null, args)}// 在已经安装的插件数组中,放进去installedPlugins.push(plugin)return this}
}

4.4 具体实践

Vue-Router
for Vue2

import View from './components/view'
import Link from './components/link'export let _Vueexport function install (Vue) {if (install.installed && _Vue === Vue) returninstall.installed = true_Vue = Vueconst isDef = v => v !== undefinedconst registerInstance = (vm, callVal) => {let i = vm.$options._parentVnodeif (isDef(i) && isDef(i = i.data) && isDef(i = i.registerRouteInstance)) {i(vm, callVal)}}Vue.mixin({beforeCreate () {if (isDef(this.$options.router)) {this._routerRoot = thisthis._router = this.$options.routerthis._router.init(this)Vue.util.defineReactive(this, '_route', this._router.history.current)} else {this._routerRoot = (this.$parent && this.$parent._routerRoot) || this}registerInstance(this, this)},destroyed () {registerInstance(this)}})Object.defineProperty(Vue.prototype, '$router', {get () { return this._routerRoot._router }})Object.defineProperty(Vue.prototype, '$route', {get () { return this._routerRoot._route }})Vue.component('RouterView', View)Vue.component('RouterLink', Link)const strats = Vue.config.optionMergeStrategies// use the same hook merging strategy for route hooksstrats.beforeRouteEnter = strats.beforeRouteLeave = strats.beforeRouteUpdate = strats.created
}

for Vue3

 install(app: App) {const router = thisapp.component('RouterLink', RouterLink)app.component('RouterView', RouterView)app.config.globalProperties.$router = routerObject.defineProperty(app.config.globalProperties, '$route', {enumerable: true,get: () => unref(currentRoute),})// this initial navigation is only necessary on client, on server it doesn't// make sense because it will create an extra unnecessary navigation and could// lead to problemsif (isBrowser &&// used for the initial navigation client side to avoid pushing// multiple times when the router is used in multiple apps!started &&currentRoute.value === START_LOCATION_NORMALIZED) {// see abovestarted = truepush(routerHistory.location).catch(err => {if (__DEV__) warn('Unexpected error when starting the router:', err)})}const reactiveRoute = {} as {[k in keyof RouteLocationNormalizedLoaded]: ComputedRef<RouteLocationNormalizedLoaded[k]>}for (const key in START_LOCATION_NORMALIZED) {// @ts-expect-error: the key matchesreactiveRoute[key] = computed(() => currentRoute.value[key])}app.provide(routerKey, router)app.provide(routeLocationKey, reactive(reactiveRoute))app.provide(routerViewLocationKey, currentRoute)const unmountApp = app.unmountinstalledApps.add(app)app.unmount = function () {installedApps.delete(app)// the router is not attached to an app anymoreif (installedApps.size < 1) {// invalidate the current navigationpendingLocation = START_LOCATION_NORMALIZEDremoveHistoryListener && removeHistoryListener()removeHistoryListener = nullcurrentRoute.value = START_LOCATION_NORMALIZEDstarted = falseready = false}unmountApp()}// TODO: this probably needs to be updated so it can be used by vue-termuiif ((__DEV__ || __FEATURE_PROD_DEVTOOLS__) && isBrowser) {addDevtools(app, router, matcher)}},}

5、过滤器

Vue.js允许我们自定义过滤器,对数据进行格式化。过滤器应该放在JS表达式的尾部,由管道符号连接。过滤器可以用在两个地方:双花括号差值和v-bind表达式。

5.1 使用过滤器

<!-- 在双花括号中 -->
{{ message | capitalize }}<!--`v-bind`-->
<div v-bind:id="message | capitalize"></div>

5.2 定义过滤器

组件中定义过滤器:

filters: {capitalize: function (value) {if (!value) return ''value = value.toString()return value.charAt(0).toUpperCase() + value.slice(1)}
}

全局中定义过滤器:

Vue.filter('capitalize', function (value) {if (!value) return ''value = value.toString()return value.charAt(0).toUpperCase() + value.slice(1)
})new Vue({// ...
})

5.3 串联过滤器

我们可以同时使用多个过滤器,过滤器函数总接收表达式的值 (上一个过滤器的结果) 作为第一个参数。

{{ message | filterA | filterB }}

过滤器是 JavaScript 函数,因此可以接收参数:
ps:没有传参时候,默认传入当前值filterA等价于filterA(message)

{{ message | filterA('arg1', 'arg2') }}

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

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

相关文章

c++树(一)定义,遍历

目录 树的定义 树的基本术语 树的初始起点&#xff1a;我们定义为根 树的层次&#xff1a; 树的定义&#xff1a; 树的性质 性质1&#xff1a; 性质2&#xff1a; 树形结构存储的两种思路 树的遍历模板 树上信息统计方式1-自顶向下统计 树上信息统计方式2-自底向上统…

【UbuntuDebian安装Nginx】在线安装Nginx

云计算&#xff1a;腾讯云轻量服务器 操作系统&#xff1a;Ubuntu-v22 1.更新系统软件包列表 打开终端并运行以下命令来确保你的系统软件包列表是最新的&#xff1a; sudo apt update2.安装 Nginx 使用以下命令安装 Nginx&#xff1a; sudo apt install nginx3.启动 Nginx…

Docker-Compose配置zookeeper+KaFka+CMAK简单集群

1. 本地DNS解析管理 # 编辑hosts文件 sudo nano /etc/hosts # 添加以下三个主机IP 192.168.186.77 zoo1 k1 192.168.186.18 zoo2 k2 192.168.186.216 zoo3 k3注&#xff1a;zoo1是192.168.186.77的别名&#xff0c;zoo2是192.168.186.18的别名&#xff0c;zoo3是192.168.186.1…

企元数智引领新零售合规分销系统免费送

企元数智近日宣布推出全新的新零售合规分销系统&#xff0c;并免费向企业提供这一创新解决方案。这一举措旨在帮助更多企业实现数字化转型&#xff0c;提高管理效率&#xff0c;促进业务增长。 新零售合规分销系统是企元数智引领的一项全新数字解决方案&#xff0c;涵盖了销售数…

Linux第四节课(指令与权限)

1、date指令(时间) 程序运行到自己的每一个关键时刻&#xff0c;都要自己打日志&#xff01; 日志包括时间、日志等级、日志具体信息、其他信息等&#xff0c;然后按照行为单位写入文件中&#xff0c;这个文件被称为日志文件&#xff01; 在日志文件中筛选信息时&#xff0c…

【Unity国产化信创平台】虚拟机VMware Workstation Pro虚拟机下载安装

目录 一、虚拟机软件VMware Workstation Pro下载 二、虚拟机安装流程 1.傻瓜式安装 2.是否自动安装WHP 一、虚拟机软件VMware Workstation Pro下载 https://www.vmware.com/products/desktop-hypervisor/workstation-and-fusion 官网各种访问出错&#xff0c;下载界面总是…

H3CNE(vlan与子接口技术)

目录 10.1 vlan间通信技术 示例一&#xff08;多臂路由&#xff09;&#xff1a; 10.2 子接口技术 示例二&#xff08;子接口技术&#xff09;&#xff1a; 10.3 vlannif接口技术 10.3.1 三层交换机与VLANNIF技术 示例三VLANNIF配置&#xff08;将交换机当成路由器使用&…

DLMS/COSEM中公开密钥算法的使用_椭圆曲线加密法

1.概述 椭圆曲线密码涉及有限域上的椭圆曲线上的算术运算。椭圆曲线可以定义在任何数字域上(实数、整数、复数)&#xff0c;但在密码学中&#xff0c;椭圆曲线最常用于有限素数域。 素数域上的椭圆曲线由一组实数(x, y)组成&#xff0c;满足以下等式: 方程的所有解的集合构成…

Go语言---list的声明、常用方法以及遍历

List所在的库 Go语言的链表实现在其标准库的container/list代码包中。 import "container/list"这个包含了两个公开的程序实体&#xff1a;List和Element。 List代表一个双向链表&#xff0c;其零值为一个空的、可用的链表&#xff1b;Element代表双向链表中的一个…

Python | Leetcode Python题解之第279题完全平方数

题目&#xff1a; 题解&#xff1a; class Solution { public:// 判断是否为完全平方数bool isPerfectSquare(int x) {int y sqrt(x);return y * y x;}// 判断是否能表示为 4^k*(8m7)bool checkAnswer4(int x) {while (x % 4 0) {x / 4;}return x % 8 7;}int numSquares(i…

注册邮箱需要实名认证吗

注册邮箱需要进行实名认证吗&#xff1f;都需要认证哪些信息呢&#xff1f;邮箱实名认证提高安全性和责任感&#xff0c;但可能涉及隐私顾虑。本文将详细介绍邮箱实名认证的相关内容。 一、邮箱实名认证的定义和目的 1、定义 电子邮件实名验证是指客户在注册电子邮件服务时&…

初阶数据结构之栈和队列

栈和队列是两种特殊的线性表&#xff0c;都可以用数组或者链表来实现&#xff0c;接下来就让我们看看栈和队列会有什么奥秘吧~ 目录 1.栈 1.1栈的概念 1.2栈的实现 1.2.1 Stack.h 1.2.2 Stack.c 1.2.3 test.c 2.队列 2.1队列的概念 2.2队列的实现 2.2.1 Queue.h 2…

【科研】# Taylor Francis 论文 LaTeX template模版 及 Word模版

【科研写论文】系列 文章目录 【科研写论文】系列前言一、Word 模板&#xff08;附下载网址&#xff09;&#xff1a;二、LaTeX 版本方法1&#xff1a;直接网页端打开&#xff08;附网址&#xff09;方法2&#xff1a;直接下载到本地电脑上编辑下载地址说明及注意事项 前言 给…

【Gin】精准应用:Gin框架中工厂模式的现代软件开发策略与实施技巧(下)

【Gin】精准应用&#xff1a;Gin框架中工厂模式的现代软件开发策略与实施技巧(下) 大家好 我是寸铁&#x1f44a; 【Gin】精准应用&#xff1a;Gin框架中工厂模式的现代软件开发策略与实施技巧(下)✨ 喜欢的小伙伴可以点点关注 &#x1f49d; 前言 本次文章分为上下两部分&…

配置web服务器练习

4练习要求&#xff1a; 练习一&#xff1a;配置web服务器&#xff0c;当访问网站 www.haha.com 时显示&#xff1a;haha 练习二&#xff1a;配置web服务器&#xff0c;当访问网站 www.xixi.com/secret/ 时显示&#xff1a;this is secret 具体步骤&#xff1a; 1、配置yum…

压测实操--produce压测方案

作者&#xff1a;九月 环境信息&#xff1a; 操作系统centos7.9&#xff0c;kafka版本为hdp集群中的2.0版本。 Producer相关参数 使用Kafka自带的kafka-producer-perf-test.sh脚本进行压测&#xff0c;该脚本参数为&#xff1a; 在producer涉及到性能的关键因素可能会存在如…

记录|使用HslCommunication库进行写入Real数据的坑

项目场景&#xff1a; 现在已经通过HslCommunication连接上了PLC&#xff0c;需要对DB1.DBD10的位置处进行数据写入。 问题描述 但是进行将12.2写入指定位置DB1.DBD10时&#xff0c;发现无法从博图中实时检测到数据的写入。 下面是我当时错误的数据写入方法&#xff1a;【主…

光伏发电管理软件:光伏企业的核心驱动力

光伏产业面对日益增长的装机容量、复杂多变的运维需求以及激烈的市场竞争&#xff0c;光伏企业如何高效管理、优化运营、提升效益&#xff0c;成为了行业关注的焦点。在此背景下&#xff0c;鹧鸪云光伏发电管理软件应运而生&#xff0c;并逐渐成为光伏企业的核心驱动力。 一、提…

回文数-双指针

题目描述&#xff1a; 个人题解&#xff1a; 先将整数转换成字符串&#xff0c;再利用双指针逐一比较数字。 代码实现&#xff1a; class Solution { public:bool isPalindrome(int x) {if(x<0||(x%100&&x!0)){return false;}//c标准库调用&#xff0c;将整数下转…

opencv - py_calib3d - py_calibration 相机校准

文章目录 Camera Calibration 相机校准目标基础知识代码设置校准去失真1. 使用 **cv.undistort()**2. 使用 **remapping** 重新投影误差 Camera Calibration 相机校准 目标 在本节中&#xff0c;我们将学习 相机造成的失真类型如何找到相机的内在和外在属性如何根据这些属性…