前端系列20集-vue3,微信小程序,brew,redis,WebSocket

news2024/12/22 20:25:14
onShow() {
 uni.checkSession({
     success: (data) => {
         this.getSessionId()
     },
     fail: () => {
         this.getSessionId()
     }
 })
},
// 获取用户的手机号
getPhoneNumber(info) {
    let wxAuth = {
        encryptedData: info.detail.encryptedData,
        iv: info.detail.iv,
        sessionId: uni.getStorageSync("sessionId")
    }
    this.$http("/user/authLogin", "post", wxAuth).then((res) => {
        if (res.data.code == 0 && res.data.data.token) {
            uni.setStorage({
                key: 'token',
                data: res.data.data.token,
                success: function({
                    uni.reLaunch({
                        url: '../home/home?isLogin=true'
                    })
                }
            })
        } else {
            uni.showToast({
                title: res.data.message,
                icon: "none"
            })
        }
    })
},

// 获取sessionId
getSessionId() {
    uni.login({
        provider: 'weixin',
        success: (res3) => {
            this.$http("/user/getSessionId", "get", {
                code: res3.code
            }).then(res2 => {
                if (res2.data.data.sessionId) {
                    uni.setStorageSync("sessionId", res2.data.data.sessionId)
                }
            })
        }
    })
}
34dbd374665a14ce3a2b21f9cbce6611.png
image.png
44ba3e2dd60c66e9bcff4b738609196c.png
image.png
baeca8ad94ba5a41f7031b4c408fa76f.png
image.png
41d0d5887e0e4246b8555d2a085d915d.png
image.png
UserController.java

@RestController
@RequestMapping("user")
public class UserController {
    
    @Autowired
    private UserService userService;

    // getSessionId
    @GetMapping("getSessionId")
    public Result getSessionId(String code) {
        return userService.getSessionId(code);
    }
}

service UserService.java

@Service
public class UserService {
    
    @Autowired
    private StringRedisTemplate redisTemplate;
    
    @Value("${wxmini.secret}")
    private String secret;
    
    @Value("${wxmini.appid}")
    private String appid;
    
    public Result getSessionId(String code) {
        //
    }
}

npm i --save-dev @types/websocket

特定的错误信息 "Invalid argument" 表明可能存在一个参数传递给数据库加载过程中的问题。

要解决这个问题,您可以考虑以下步骤:

  1. 检查加载数据库的代码,并检查是否存在传递错误或无效的参数。

  2. 验证数据库所需的依赖项或库是否已正确安装并更新。

  3. 确保数据库配置(如连接设置或文件路径)准确有效。

  4. 检查最近是否有代码、依赖项或环境的更改或更新可能导致此问题。

  5. 查找任何相关的错误日志或堆栈跟踪,提供关于错误的更详细信息。这有助于确定问题的具体原因。

如果根据提供的信息无法解决问题,请提供更多详细信息,例如与数据库加载过程相关的具体代码和任何相关的错误日志或消息。

一、brew 安装脚本 (自动选择软件源)

/bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)"

二、brew 卸载脚本

/bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/HomebrewUninstall.sh)"

三、常用命令

安装软件:brew install xxx
卸载软件:brew uninstall xxx
搜索软件:brew search xxx
更新软件:brew upgrade xxx
查看列表:brew list
更新brew:brew update
清理所有包的旧版本:brew cleanup
清理指定包的旧版本:brew cleanup $FORMULA
查看可清理的旧版本包,不执行实际操作:brew cleanup -n

Brotli 是一种数据压缩算法,它能够提供高效的压缩和解压缩性能。它由谷歌开发,并于2015年发布。Brotli 压缩算法在压缩比率和压缩速度方面都具有很好的表现,尤其在处理文本和网络传输数据时效果显著。

在 macOS 上,Homebrew(brew)是一个常用的包管理器,用于安装和管理各种开源软件包。brew brotli 是用于在 macOS 上安装 Brotli 压缩算法的 Homebrew 命令。通过运行该命令,您可以方便地从 Homebrew 仓库中获取 Brotli 并进行安装。

要安装 Brotli,请打开终端并运行以下命令:

brew install brotli

这将下载 Brotli 的二进制文件,并将其安装到您的 macOS 系统中。安装完成后,您可以使用 Brotli 命令行工具执行压缩和解压缩操作。

例如,要压缩文件,可以使用以下命令:

brotli -o compressed_file.br original_file

要解压缩文件,可以使用以下命令:

brotli -d -o decompressed_file original_file.br

通过使用 brew brotli 命令安装 Brotli,您可以轻松地在 macOS 上使用该压缩算法,并将其应用于您的项目或数据处理需求。

  1. 压缩文件:

brotli -o compressed_file.br original_file

这将使用 Brotli 压缩算法将 original_file 文件压缩,并将压缩后的结果保存为 compressed_file.br

  1. 解压缩文件:

brotli -d -o decompressed_file original_file.br

这将使用 Brotli 压缩算法解压缩 original_file.br 文件,并将解压缩后的结果保存为 decompressed_file

请确保在运行以上命令时,将 original_file 替换为要压缩或解压缩的实际文件名,并提供适当的目标文件名。

Name  Status  User    File

redis started jeskson ~/Library/LaunchAgents/homebrew.mxcl.redis.plist

安装 Redis 之后,你可以使用以下命令来启动 Redis 服务:

brew services start redis

这将启动 Redis 服务,并使其在后台运行。你可以通过以下命令来检查 Redis 服务是否正在运行:

brew services list

你应该看到 Redis 服务的状态为 "started"。

一旦 Redis 服务正在运行,你可以使用以下命令来连接到 Redis 服务器:

redis-cli

这将打开 Redis 命令行界面,你可以在其中执行各种 Redis 命令和操作。例如,你可以使用以下命令来设置和获取键值对:

set mykey "Hello, Redis"
get mykey

这些命令将设置键名为 "mykey" 的键值对,并从 Redis 中获取它的值。

当你完成使用 Redis 后,可以使用以下命令来停止 Redis 服务:

brew services stop redis

这将停止 Redis 服务,并使其不再运行。

const connectWebSocket = () => {
    socket.value = new WebSocket('') // 替换为你的 WebSocket 服务器地址

    socket.value.onopen = () => {
        console.log('WebSocket 连接已建立')
        const message = JSON.stringify({
        })
        socket.value.send(message)
    }

    socket.value.onmessage = (event: { data: any }) => {
        console.log('接收到 WebSocket 消息:', event.data)
        // 处理接收到的消息
    }

    socket.value.onclose = () => {
        console.log('WebSocket 连接已关闭')
    }

    socket.value.onerror = (error: any) => {
        console.error('WebSocket 错误:', error)
    }
}

重新连接

如果 WebSocket 连接断开,可以通过重新创建 WebSocket 实例来重新连接。

socket.value.onclose = () => {
  console.log('WebSocket disconnected');
  // 重新连接
  socket.value = useWebSocket('wss://example.com/socket');
};

为了保持 WebSocket 连接的活跃状态,可以使用心跳机制定期发送心跳消息。

// 心跳消息
const heartbeatMessage = 'ping'
// 定时发送心跳消息
setInterval(() => {
    socket.value.send(heartbeatMessage)
}, 5000000000)
// 监听消息事件
socket.value.onmessage = (event: { data: any }) => {
    const message = event.data
    console.log('定时发送心跳消息:', event.data)

    if (message === heartbeatMessage) {
        // 收到心跳消息,做相应处理
    } else {
        // 处理其他消息
    }
}

定期发送心跳消息,并在收到心跳消息时进行相应处理。

微信小程序登录流程前后端描述,小程序通过wx.login()获取code,如0f14dT0w3P2bT03Pgz0w3ugqsE44dxxx,
const { code }: any = await uni.login({
    provider: 'weixin'
})
const data = await mnpLogin({
    code
})
loginHandle(data)

通过wx.request()发送code,后端的接口带入参数code,获取getSessionId,后端通过登录凭证校验接口 appid + appsecret + code 去微信接口服务拿取数据 如:session_key+openid等 然后 后端 可以(自定义登录态)与openid,session_key关联,返回前端-返回自定义登录态 (不关紧要的内容:自定义登录状态存入storage,wx.request()发起业务请求,携带 自定义登录态,后端通过自定义登录态,查询openid和session_key,返回业务数据)

server {
    listen    8080;
        # 用户访问 ip:8080/test 下的所有路径代理到 github
        location /test {
         proxy_pass   https://github.com;
        }

        # 所有 /api 下的接口访问都代理到本地的 8888 端口
        # 例如你本地运行的 java 服务的端口是 8888,接口都是以 /api 开头
        location /api {
            proxy_pass   http://127.0.0.1:8888;
        }

}

反向代理

我们最常说的反向代理的是通过反向代理解决跨域问题。

其实反向代理还可以用来控制缓存(代理缓存 proxy cache),进行访问控制等等,以及后面说的负载均衡其实都是通过反向代理来实现的。

server {
    listen    8080;
        # 用户访问 ip:8080/test 下的所有路径代理到 github
        location /test {
         proxy_pass   https://github.com;
        }

        # 所有 /api 下的接口访问都代理到本地的 8888 端口
        # 例如你本地运行的 java 服务的端口是 8888,接口都是以 /api 开头
        location /api {
            proxy_pass   http://127.0.0.1:8888;
        }

}

负载均衡

通过负载均衡充利用服务器资源,nginx 目前支持自带 4 种负载均衡策略,还有 2 种常用的第三方策略。

轮询策略(默认)

每个请求按时间顺序逐一分配到不同的后端服务器,如果有后端服务器挂掉,能自动剔除。但是如果其中某一台服务器压力太大,出现延迟,会影响所有分配在这台服务器下的用户。

http {
    upstream test.com {
        server 192.168.1.12:8887;
        server 192.168.1.13:8888;
    }
    server {
        location /api {
            proxy_pass  http://test.com;
        }
    }
}

根据服务器权重

例如要配置:10 次请求中大概 1 次访问到 8888 端口,9 次访问到 8887 端口:

http {
    upstream test.com {
        server 192.168.1.12:8887 weight=9;
        server 192.168.1.13:8888 weight=1;
    }
    server {
        location /api {
            proxy_pass  http://test.com;
        }
    }
}

客户端 ip 绑定(ip_hash)

来自同一个 ip 的请求永远只分配一台服务器,有效解决了动态网页存在的 session 共享问题。例如:比如把登录信息保存到了 session 中,那么跳转到另外一台服务器的时候就需要重新登录了。

所以很多时候我们需要一个客户只访问一个服务器,那么就需要用 ip_hash 了。

http {
    upstream test.com {
     ip_hash;
        server 192.168.1.12:8887;
        server 192.168.1.13:8888;
    }
    server {
        location /api {
            proxy_pass  http://test.com;
        }
    }
}

最小连接数策略

将请求优先分配给压力较小的服务器,它可以平衡每个队列的长度,并避免向压力大的服务器添加更多的请求。

http {
    upstream test.com {
     least_conn;
        server 192.168.1.12:8887;
        server 192.168.1.13:8888;
    }
    server {
        location /api {
            proxy_pass  http://test.com;
        }
    }
}

最快响应时间策略(依赖于第三方 NGINX Plus)

依赖于 NGINX Plus,优先分配给响应时间最短的服务器。

http {
    upstream test.com {
     fair;
        server 192.168.1.12:8887;
        server 192.168.1.13:8888;
    }
    server {
        location /api {
            proxy_pass  http://test.com;
        }
    }
}

Provide/Inject 调用

main.ts
import axios from 'axios'
import VueAxios from 'vue-axios'
app.use(VueAxios, axios)
app.provide('axios', app.config.globalProperties.axios) 
App.vue
const axios: any = inject('axios')  // inject axios
axios({url,data,...其他配置}).then() // 同上

什么是 hook ?

在 React 中的意思是将一个以 use 开头,含react 状态和 effect 纯函数的外部代码挂入到它的节点当中。

<template>
    <div class="demo1-container">
        <div ref="sectionRef" class="ref-section"></div>
    </div>
</template>

<script setup lang="ts">
import {ref} from 'vue'
const sectionRef = ref()
</script>
<template>
    <div class="demo1-container">
        <p>通过ref直接拿到dom</p>
        <div ref="sectionRef" class="ref-section"></div>
        <button @click="higherAction" class="btn">变高</button>
    </div>
</template>

<script setup lang="ts">
import {ref} from 'vue'
const sectionRef = ref()
let height = 100;

const higherAction = () => {
    height += 50;
    sectionRef.value.style = `height: ${height}px`;
}
</script>

<style lang="scss" scoped>
.demo1-container {
    width: 100%;
    height: 100%;

    .ref-section {
        width: 200px;
        height: 100px;
        background-color: pink;
        transition: all .5s ease-in-out;
    }

    .btn {
        width: 200px;
        height: 50px;
        background-color: gray;
        color: #fff;
        margin-top: 100px;
    }
}
</style>
<template>
    <div class="demo2-container">
        <p>通过父容器遍历拿到dom</p>
        <div ref="listRef" class="list-section">
            <div @click="higherAction(index)" class="list-item" v-for="(item, index) in state.list" :key="index">
                <span>{{item}}</span>
            </div>
        </div>
    </div>
</template>

<script setup lang="ts">
import { ref, reactive } from 'vue'
const listRef = ref()
const state = reactive({
    list: [1, 2, 3, 4, 5, 6, 7, 8]
})

const higherAction = (index: number) => {
    let height = listRef.value.children[index].style.height ? listRef.value.children[index].style.height : '20px';
    height = Number(height.replace('px', ''));
    listRef.value.children[index].style = `height: ${height + 20}px`;
}
</script>

<style lang="scss" scoped>
.demo2-container {
    width: 100%;
    height: 100%;

    .list-section {
        width: 200px;
        .list-item {
            width: 200px;
            height: 20px;
            background-color: pink;
            color: #333;
            transition: all .5s ease-in-out;
            display: flex;
            justify-content: center;
            align-items: center;
        }
    }
}
</style>
<template>
  <img alt="Vue logo" src="./assets/logo.png" />
  <p>{{ message }}</p>
  <button @click="changeMsg">更改 message</button>
</template>
<script setup lang="ts">
import { ref, watch } from "vue";


const message = ref("小猪课堂");
watch(message, (newValue, oldValue) => {
  console.log("新的值:", newValue);
  console.log("旧的值:", oldValue);
});
const changeMsg = () => {
  message.value = "张三";
};
</script>

第一次渲染页面的时候,watch 监听器里面的回调函数就执行一遍。

watchEffect 也是一个监听器,只不过它不会像 watch 那样接收一个明确的数据源,它只接收一个回调函数。而在这个回调函数当中,它会自动监听响应数据,当回调函数里面的响应数据发生变化,回调函数就会立即执行。

如果我们想要在回调函数里面获取更新后的 DOM,非常简单,我们只需要再给监听器多传递一个参数选项即可:flush: 'post'

const unwatch = watchEffect(() => {}) // ...当该侦听器不再需要时 unwatch()

加群联系作者vx:xiaoda0423

仓库地址:https://github.com/webVueBlog/WebGuideInterview

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

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

相关文章

Java反射源码学习之旅 | 京东云技术团队

1 背景 前段时间组内针对“拷贝实例属性是应该用BeanUtils.copyProperties&#xff08;&#xff09;还是MapStruct”这个问题进行了一次激烈的battle。支持MapStruct的同学给出了他嫌弃BeanUtils的理由&#xff1a;因为用了反射&#xff0c;所以慢。 这个理由一下子拉回了我遥…

青岛农商与中电金信鲸Bot RPA的一次紧密合作

260%、350%、313%、400%、1200%&#xff0c;这些都是青岛农商银行近期通过鲸Bot RPA跑出来的各个业务流程的ROI&#xff0c;原来选择合适的RPA真的这么有用&#xff01;青岛农商还亲切地给RPA起了一个昵称&#xff1a;小鑫&#xff0c;从此小鑫就是青岛农商第一位正式的数智员工…

群晖安装、卸载、停用套件

安装套件 点击套件中心 点击所有套件&#xff0c;选中需要安装的套件&#xff0c;店家安装套件&#xff0c;或者试用&#xff0c;等待安装完成即可 卸载套件 点击已安装 点击图标或者文字&#xff0c;注意&#xff1a;不要点打开 点击向下的箭头 点击停用&#xff0c;或者卸载…

puppeteer实现文件下载

puppeteer实现文件下载 puppeteer版本&#xff1a; "puppeteer": "^20.7.3",脚本需要的其他依赖 const axios require(axios); const FormData require(form-data); const fs require(fs);本脚本测试数据网站&#xff1a;https://unsplash.com/photo…

基于Java民宿管理系统设计实现(源码+lw+部署文档+讲解等)

博主介绍&#xff1a;✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专…

【机器学习】数据预处理 - 归一化和标准化

「作者主页」&#xff1a;士别三日wyx 「作者简介」&#xff1a;CSDN top100、阿里云博客专家、华为云享专家、网络安全领域优质创作者 「推荐专栏」&#xff1a;对网络安全感兴趣的小伙伴可以关注专栏《网络安全入门到精通》 数据预处理 一、数据预处理API二、准备数据集三、归…

没有u盘,怎么将电脑上的便签文件拷贝到手机上?

在如今数字化的时代&#xff0c;便签软件已经成为我们工作和生活中很重要的一部分&#xff0c;在便签中我们会记录很多重要事项或者重要文件。有时候&#xff0c;我们可能会遇到这样的问题&#xff1a;当我们在电脑便签上保存了一些重要文件&#xff0c;想要将文件拷贝到手机上…

【Redis常见命令】 —— 关于Redis的一点儿知识

&#x1f4a7; 【 R e d i s 常见命令】——关于 R e d i s 的一点儿知识 \color{#FF1493}{【Redis常见命令】 —— 关于Redis的一点儿知识} 【Redis常见命令】——关于Redis的一点儿知识&#x1f4a7; &#x1f337; 仰望天空&#xff0c;妳我亦是行人.✨ &#x1f…

Java框架学习(二)SSM体系:Spring、SpringMVC、MybatisPlus

文章目录 SpringIoC控制反转DI 依赖注入BeanBean基础配置namescope Bean实例化方式Bean的生命周期 依赖注入方式依赖自动装配 Mybatis-Plus配置BaseMapper通用Service常用注解TableNameTableId雪花算法 TableFieldTableLogic 条件构造器和常用接口QueryWrapperUpdateWrapper 插…

【数据库原理与实践】知识点归纳(下)

第6章 规范化理论 一、关系模式设计中存在的问题 关系、关系模式、关系数据库、关系数据库的模式 关系模式看作三元组&#xff1a;R < U,F >&#xff0c;当且仅当U上的一个关系r满足F时&#xff0c;r称为关系模式R < U,F >的一个关系 第一范式&#xff08;1NF&…

一步一步学OAK之七:通过OAK相机实现特征跟踪

目录 特征跟踪Setup 1: 创建文件Setup 2: 安装依赖Setup 3: 导入需要的包Setup 4: 定义FeatureTrackerDrawer类定义变量定义onTrackBar方法定义trackFeaturePath方法定义drawFeatures方法定义FeatureTrackerDrawer类的构造函数 Setup 5: 创建pipelineSetup 6: 创建节点创建相机…

Scrapy框架之下载中间件(详解)

目录 Scrapy中下载中间件 概念 方法 process_request(self, request, spider) 参数: process_response(self, request, response, spider) 参数 基本步骤 示例代码 注意 Scrapy 中 Downloader 设置UA 开发UserAgent下载中间件 代码 三方模块 配置模块到Settin…

Redis系列 | 分类树查询功能如何从2s优化到0.1s

大家好&#xff0c;今天我们继续来分享一个在项目开发过程中遇到的实际问题&#xff0c;这里也来梳理并总结一下我们是如何对它进行持续优化的&#xff0c;希望能对大家有所帮助。 分类树查询功能&#xff0c;在各个业务系统中可以说随处可见&#xff0c;特别是在一些电商系统中…

UGUI无线滑动列表

在游戏开发中&#xff0c;经常会遇到需要展示大量数据的情况&#xff0c;例如排行榜、背包等。为了优化显示效果和性能&#xff0c;一个常见的做法是使用无限滑动列表&#xff08;Infinite Scroll View&#xff09;。本文将详细解析如何实现无限滑动列表。 基本原理 无限滑动列…

市电电压双向越限报警保护器电路设计

该报警保护器能在市电电压高于或低于规定值时&#xff0c;进行声光报警&#xff0c;同时自动切断电器电源&#xff0c;保护用电器不被损坏。该装置体积小、功能全、制作简单、实用性强。 一、电路工作原理 电路原理如图 3 所示。 市电电压一路由C3降压&#xff0c;DW稳压&am…

驱动开发:应用DeviceIoContro模板精讲

在笔者上一篇文章《驱动开发&#xff1a;应用DeviceIoContro开发模板》简单为大家介绍了如何使用DeviceIoContro模板快速创建一个驱动开发通信案例&#xff0c;但是该案例过于简单也无法独立加载运行&#xff0c;本章将继续延申这个知识点&#xff0c;通过封装一套标准通用模板…

一、枚举类型——新特性(switch 中的箭头语法)

支持模式匹配 你可以认为模式匹配&#xff08;pattern matching&#xff09;是在 switch 关键字上进行了显著的功能扩充。 它是分成了多个模块、 历经了 Java 的多个版本持续实现的。这保证了每个模块在其他模块加入前都可以安全地运行。最后&#xff0c;所有的模块集中到一起…

LLM大模型应用开发的本地环境搭建

尽管 ChatGPT 仍然很受欢迎&#xff0c;但泄露的 Google 内部文件表明开源社区正在迎头赶上并取得重大突破。 我们现在能够在消费级 GPU 上运行大型 LLM 模型。 因此&#xff0c;如果你是一名开发人员&#xff0c;想要在本地环境中尝试这些 LLM 并用它构建一些应用程序&#x…

Kubernetes进阶实战2

Kubernetes具有以下几个重要特性 简言之&#xff0c;Kubernetes整合并抽象了底层的硬件和系统环境等基础设施&#xff0c;对外提供了一个统一的资源池供终端用户通过API进行调用。 Kubernetes具有以下几个重要特性。 &#xff08;1&#xff09;自动装箱 构建于容器之上&#x…