Vue3——简易个人空间(下半部分)

news2024/11/27 8:33:23

书接上回:

好友列表页面实现:

 根据提供的api从云端将10个用户读进来

根据提供的api获得如下的json格式的数据,里面有四个用户的信息。 

这里使用ajax进行实现要先在项目中安装jquery,使用命令行安装

npm i jquery

 然后在用户列表页面要先引入jquery

import $ from 'jquery';

又或者使用axios获取网络请求

有如下流程:

现在终端下载axios

npm i axios

 封装axios。。。

算了,这里不实现了,好麻烦,以后有一会再来写,还是ajax方便点

效果图:

 代码:

<template>
    <ContentBase>
        <div class="card" v-for="user in users" :key="user.id">
            <div class="card-body">
                <div class="row">
                    <div class="col-1">
                        <img class="img-fluid" :src="user.photo" alt="" /> <!--此处img-fluid实现了一个响应式布局,可以使图片随着父元素大小缩放-->
                    </div>
                    <div class="col-11">
                        <div class="username">{{ user.username }}</div>
                        <div class="follow-count">{{ user.followerCount }}</div>
                    </div>
                </div>
            </div>
        </div>
    </ContentBase>
</template>
  
<script>
import $ from 'jquery';
import { ref } from 'vue';
import ContentBase from '@/components/ContentBase.vue';
export default {
    name: 'UserListView',
    components: {
        ContentBase
    }, setup() {
        let users = ref([]);
        $.ajax({
            url: "https://app165.acapp.acwing.com.cn/myspace/userlist/",
            type: "get",
            success(resp) {
                users.value = resp;

            }
        });
        return {
            users
        }
    }

}
</script>
<style scope>
.img-fluid {
    border-radius: 50%;
}

.username {
    font-weight: bold;
    height: 50%;
}

.follow-count {
    font-size: 12px;
    color: gray;
    height: 50%;
}

.card {
    margin-bottom: 20px;
    /*间隔*/
    cursor: pointer;
    /*将鼠标变成手的效果*/

}


/*鼠标悬浮效果*/
.card:hover {
    box-shadow: 2px 2px 10px gray;
    transition: 500ms;
}
</style>
  

这里上面代码里面使用的是课程里面提供的链接。 

此处上面的后端的userlist的链接也可以自己在本地实现,这里我本地新建了一个springboot的后端项目实现了一个userlist的获取url,效果图如下。

实现方法放在这篇文章里面:

Springboot——根据需求创建后端接口_北岭山脚鼠鼠的博客-CSDN博客

页面跳转404

在router当中加上一个额外正则表达式匹配,上面的所有url都匹配不上时就会重定向到404页面

.表示匹配任意字符,*表示匹配任意长度

用户动态页面完善

在用户动态页面需要根据两个用户的信息判断显示关注与否

 在router当中修改一下,加上一个:userId,表示这个url后面需要一个userId,

然后在访问用户动态页面的时候是通过userId查询访问.

在NavBar.vue当中还需要进行如下修改,

先随便起一个userId 

在UserProfileView.vue当中要想访问userId要先引入一个东西

import { useRoute} from 'vue-router'

然后在setup函数中获取url当中userId参数 

演示,url当中输入任何数字都可以被useRoute捕获并输出到控制台上 

登录页面实现

到bootstrap当中寻找表单

复制该表单的内容到login.vue当中

经过修改得到如下

    <ContentBase>
        <form>
            <div class="mb-3">
                <label for="username" class="form-label">鼠鼠名</label>
                <input type="text" class="form-control" id="username">
            </div>
            <div class="mb-3">
                <label for="password" class="form-label">鼠鼠码</label>
                <input type="password" class="form-control" id="exampleInputPassword1">
            </div>
            <button type="submit" class="btn btn-primary">登录</button>
        </form>
    </ContentBase>

 此外要想登陆还要获取到姓名和密码发送到后端,所以这里还需要两个双向绑定的变量

username,password

此外还需要一个登陆错误报错error_message,以及一个点击登录会触发的一个函数login().

这四个东西都要贼setup中定义并返回,才能在template中使用。

最后得到如下的代码:

<template>
    <ContentBase>

        <div class="row justify-content-md-center">
            <div class="col-3">
                <form @submit.prevent="login"> <!--此处.prevent的作用是阻止其默认行为-->
                    <div class="mb-3">
                        <label for="username" class="form-label">鼠鼠名</label>
                        <input type="text" class="form-control" id="username" v-model="username">
                    </div>
                    <div class="mb-3">
                        <label for="password" class="form-label">鼠鼠码</label>
                        <input type="password" class="form-control" id="exampleInputPassword1" v-model="password">
                    </div>
                    <div class="error-message">{{ error_message }}</div>
                    <button type="submit" class="btn btn-primary">登录</button>
                </form>
            </div>
        </div>

    </ContentBase>
</template>
  
<script>
import { ref } from 'vue';
import ContentBase from '@/components/ContentBase.vue';
export default {
    name: 'LoginView',
    components: {
        ContentBase
    }, setup() {
        let username = ref('');
        let password = ref('');
        let error_message = ref('');
        const login = () => {
            alert("登陆了");
        }
        return {
            username,
            password,
            login,
            error_message
        }
    }
}
</script>
<style scope>
button {
    width: 100%;
}

.error-message {
    color: red;
}
</style>
  

 维护使用全局变量——vuex

 vuex会维护一个state树,所有全局信息都会被维护到这个state树当中。

任意两个组件之间想通信都可以通过到state树当中查找对应变量。

使用

安装完vuex之后,就可以直接在store下的index.js里面定义全局变量了,

下面只是一个介绍样例

import { createStore } from 'vuex'

export default createStore({
  state: {   //此处用于存储所有全局数据,可以是对象也可以是一个属性
    user: {
      username: "",
      id: "",
      firstname: "",
      lastname:""
    }
  },
  getters: {   //此处存放方法,用于计算需要组合使用的数据,只能读信息不能修改
    fullname(state) {
      return state.user.firstname + state.user.lastname;
    }
  },
  mutations: {  //定义所有对state的修改操作,但这里不能进行异步操作,比如从云端获取
    update(state, user)
    {
      state.user = user;
    }


  },
  actions: {  //此处用于定义所有对于state的更新方式,这里不能直接对state进行修改,要调用mutations中的方法修改
    updateUser(context) {
      let resp;    }
  },
  modules: { //对于多个对象可以使用不同modules进行维护,并在这里进行引入,这里以后用到再来详细讲
    modulesA,
    modulesB
  }
})

现在先在store下新建一个user.js,里面存放如下信息

const ModuleUser = {
    state: {  
        id: "",
        username: "",
        photo: "",
        followerCount:0,
    },
    getters: {   
         
    },
    mutations: {  
    },
    actions: {  
    },
    modules: { 
  
    }
};

export default ModuleUser;

 然后在index.js中进行如下的引入

import { createStore } from 'vuex'
import ModuleUser from './user'

export default createStore({
  state: {   //此处用于存储所有全局数据,可以是对象也可以是一个属性
  },
  getters: {   //此处存放方法,用于计算需要组合使用的数据,只能读信息不能修改

  },
  mutations: {  //定义所有对state的修改操作,但这里不能进行异步操作,比如从云端获取
  },
  actions: {  //此处用于定义所有对于state的更新方式,这里不能直接对state进行修改,要调用mutations中的方法修改
  },
  modules: { //对于多个对象可以使用不同modules进行维护,并在这里进行引入,这里以后用到再来详细讲
    user:ModuleUser
  }
})

传统登录验证方式 

在用户访问服务器时,服务器会返回一个session_id给用户并保存信息到数据库,用户端会保存该session_id,之后再访问服务器时(比如跳转别的页面)就带上session_id一起访问服务器,服务器会检查session是否存在于数据库。一般存到cookie当中,js无法访问。

因此就无法使用ajax维护登录状态,因为无法得到session_id.

新的登录验证方式——jwt方式:json web token

第一次访问时会将用户名和密码传给服务器。

然后服务器会返回一个有时长限制的令牌。

此后每次访问服务器都会带上令牌,服务器检查令牌是否在有效期内。

这个令牌就是一个字符串,但是并不会存到数据库中,但是服务器端可以验证jwt是否在有效期。

原理:就是类似与哈希算法,比对哈希结果。。。

在user.js的actions中加入如下 

        login(context, data) {
            $.ajax({
                url: "https://app165.acapp.acwing.com.cn/api/token/",
                type: "POST",
                data: {
                    username: data.username,
                    password: data.password
                },
                success(resp) {
                    console.log(resp);
                }
            })
        }

 在loginView当中再改login方法为如下:

要调用actions中的方法就要使用dispatch

        const login = () => {
            store.dispatch("login", {
                username: username.value,
                password: password.value,
                success() {
                    console.log("success");
                },
                error() {
                    console.log("failed");
                }
            });
        };

然后登陆验证输出成功,这里就成功获取到了账号123的令牌。

 然后需要进行编码阶码先在终端下一个包

npm i jwt-decode

 经过解码后得到 

然后再根据userid获取用户信息

 成功获取

 顺序上是ajax获得jwt,jwt获得userid,userid获取用户信息。

然后获取到的jwt令牌会过期,所以写个周期函数每五分钟获取一次新的access。

最后loginView.vue变成如下

<template>
    <ContentBase>

        <div class="row justify-content-md-center">
            <div class="col-3">
                <form @submit.prevent="login"> <!--此处.prevent的作用是阻止其默认行为-->
                    <div class="mb-3">
                        <label for="username" class="form-label">鼠鼠名</label>
                        <input type="text" class="form-control" id="username" v-model="username">
                    </div>
                    <div class="mb-3">
                        <label for="password" class="form-label">鼠鼠码</label>
                        <input type="password" class="form-control" id="exampleInputPassword1" v-model="password">
                    </div>
                    <div class="error-message">{{ error_message }}</div>
                    <button type="submit" class="btn btn-primary">登录</button>
                </form>
            </div>
        </div>

    </ContentBase>
</template>
  
<script>
import { useStore } from 'vuex';
import { ref } from 'vue';
import router from '@/router/index';
import ContentBase from '@/components/ContentBase.vue';
export default {
    name: 'LoginView',
    components: {
        ContentBase
    }, setup() {
        const store = useStore();
        let username = ref('');
        let password = ref('');
        let error_message = ref('');
        const login = () => {
            store.dispatch("login", {
                username: username.value,
                password: password.value,
                success() {
                    router.push({ name: 'userlist' })  //登录成功后自动跳转,这里的push是其自带的
                },
                error() {
                    error_message.value = "账号或密码错误"
                }
            });
        };

        return {
            username,
            password,
            login,
            error_message,
        }
    }
}
</script>
<style scope>
button {
    width: 100%;
}

.error-message {
    color: red;
}
</style>
  

user.js变成如下

其中actions的方法在js中通过store.dispath("方法名",参数)调用

其中muation中的方法在user.js中的actions中通过context.commit(“方法名”,参数)调用

import $ from 'jquery'
import jwt_decode from 'jwt-decode'
const ModuleUser = {
    state: {  
        id: "",
        username: "",
        photo: "",
        followerCount: 0,
        access: "",
        refresh: "",
        is_login: false,

    },
    getters: {   
         
    },
    mutations: {  
        updateUser(state, user) {  //把下面通过ajax获取到的user信息放到全局变量
            state.id = user.id;
            state.username = user.username;
            state.photo = user.photo;
            state.followerCount = user.followerCount;
            state.access = user.access;
            state.refresh = user.refresh;
            state.is_login = user.is_login;
        }, updateAccess(state, access) {
            state.access = access;
        }
    },
    actions: {  
        login(context, data) {
            
            $.ajax({
                url: "https://app165.acapp.acwing.com.cn/api/token/",   //第一层ajax,先尝试登录是否成功并获取令牌
                type: "POST",
                data: {
                    username: data.username,
                    password: data.password
                },
                
                success(resp) {
                    const { access,refresh } = resp;
                    const access_obj = jwt_decode(access);   //成功获取后对令牌解码并获取用户id

                    setInterval(() => { //每隔五分钟获取一次令牌
                        $.ajax({
                            url: "https://app165.acapp.acwing.com.cn/api/token/refresh/",
                            type: "POST",
                            data: {
                                refresh
                            },
                            success(resp) {
                                context.commit("updateAccess", resp.access);
                            }
                        });
                    }, 4.5 * 60 * 1000);
                    
                    $.ajax({                                  //第二层ajax根据id获取用户信息
                        url: "https://app165.acapp.acwing.com.cn/myspace/getinfo/",
                        type: "GET",
                        data: {
                            user_id:access_obj.user_id
                        },
                        headers: {
                            'Authorization': "Bearer " + access, //这里一定要注意空格
                        },
                        success(resp) {
                            context.commit("updateUser", {
                                ...resp,  //此处resp解构作用是将对象数组展开
                                access: access,
                                refresh: refresh,
                                is_login: true,
                            });
                            data.success(); //成功就调成功的回调哈数
                        }
                    })
                }, error() {
                    data.error();  //失败就调失败的回调函数
                }
            })
        }
    },
    modules: { 
  
    }
};

export default ModuleUser;

经过上面的操作,已经将用户的所有信息都存到了全局状态里面,登录成功之后还要将右上角的信息变成头像和昵称。

这时候就可以根据全局信息里面is_login判断是显示登录注册还是显示个人信息。

显示登陆者信息在右上角——实现登录和退出

在NavBar.vue当中根据is_login的信息选择显示什么,这里全局变量可以直接访问,

格式如下

这个是访问一个子模块里面的state

$store.stare.user.usernmae

还需要实现退出,退出只需要定义一个函数将jwt令牌删除即可。

所以这里需要需要修改全局state。还需要将修改的逻辑写到actions里面,把具体修改放到mutations里面。也可以直接写到mutation里面

在user.js中实现如下,在mutations里面加一个函数,传state进去修改

        logout(state) {
            state.id = "",
                state.username = "",
                state.photo = "",
                state.followerCount = 0,
                state.access = "",
                state.refresh = "",
                state.is_login = false;
        }

在NavBar中实现如下: 

<template>
    <nav class="navbar navbar-expand-lg bg-body-tertiary">
        <div class="container">
            <router-link class="navbar-brand" :to="{ name: 'home', params: {} }">
                鼠鼠空间
            </router-link>
            <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarText"
                aria-controls="navbarText" aria-expanded="false" aria-label="Toggle navigation">
                <span class="navbar-toggler-icon"></span>
            </button>
            <div class="collapse navbar-collapse" id="navbarText">
                <ul class="navbar-nav me-auto mb-2 mb-lg-0">
                    <li class="nav-item">
                        <router-link class="nav-link active" to="/">首页</router-link>
                    </li>
                    <li class="nav-item">
                        <router-link class="nav-link" :to="{ name: 'userlist', params: {} }">鼠友列表</router-link>
                    </li>
                    <li class="nav-item">
                        <router-link class="nav-link"
                            :to="{ name: 'userprofile', params: { userId: 2 } }">鼠友动态</router-link>
                    </li>
                </ul>
                <ul class="navbar-nav" v-if="!$store.state.user.is_login">
                    <li class="nav-item">
                        <router-link class="nav-link" :to="{ name: 'login', params: {} }">登录</router-link>
                    </li>
                    <li class="nav-item">
                        <router-link class="nav-link" :to="{ name: 'register', params: {} }">注册</router-link>
                    </li>
                </ul>
                <ul class="navbar-nav" v-else>
                    <li class="nav-item">
                        <router-link class="nav-link" :to="{
                            name: 'userprofile',
                            params: { userId: $store.state.user.id }
                        }">{{ $store.state.user.username }}</router-link>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link" style="cursor:pointer" @click="logout">退出</a>
                    </li>
                </ul>

            </div>
        </div>
    </nav>
</template>

<script >
import { useStore } from 'vuex';
export default {
    name: "NavBar",
    setup() {
        const store = useStore();
        const logout = () => {
            store.commit("logout");
        };
        return {
            logout,
        }
    }
}
</script>

<style scoped></style>

用户动态页面实现

用户动态应该根据进入的用户空间不同显示不同的用户页面,不能直接放在导航栏,因为需要传一个userId的参数,所以需要先将用户动态从导航栏删除

 要在用户列表页面实现点击不同的用户并跳转不同的用户动态。

跳转就是跳到别的用户的页面,需要一个用户id,如下所示

                router.push({ name: 'userprofile', params: { userId } })

用户动态页面根据传入的userId不同显示不同的内容,需要将信息动态从云端拉取下来,就是一个getbyid,再到获取一个人所有的帖子,也是根据id获取。

使用提供的api

userprofileView.vue页面

<template>
    <ContentBase>
        <div class="row">
            <div class="col-3">
                <UserInfo @follow="follow" @unfollow="unfollow" :user="user" />
                <UserWrite v-if="is_me" @post_a_post="post_a_post" />
            </div>
            <div class="col-9">
                <UserPosts :posts="posts" />
            </div>
        </div>
    </ContentBase>
</template>
  
<script>
import { computed } from 'vue';
import UserInfo from '../components/UserInfo.vue'
import UserPosts from '../components/UserPosts.vue'
import UserWrite from '../components/UserWrite.vue'
import { reactive } from 'vue';
import { useRoute } from 'vue-router'
import $ from 'jquery';
import { useStore } from 'vuex';
import ContentBase from '@/components/ContentBase.vue';



export default {
    name: 'UserProfileView',
    components: {
        ContentBase,
        UserInfo,
        UserPosts,
        UserWrite
    }, setup() {
        const route = useRoute();
        const userId = route.params.userId;
        const user = reactive({});
        const posts = reactive({});
        const store = useStore();
        $.ajax({   //获取某个用户的信息
            url: "https://app165.acapp.acwing.com.cn/myspace/getinfo/",
            type: "GET",
            data: {
                user_id: userId
            },
            headers: {
                'Authorization': "Bearer " + store.state.user.access,

            }, success(resp) {
                user.id = resp.id;
                user.username = resp.username;
                user.photo = resp.photo;
                user.followcount = resp.followerCount;
                user.is_followd = resp.is_followd;
            }
        })

        $.ajax({  //获取某个用户发过的所有帖子
            url: "https://app165.acapp.acwing.com.cn/myspace/post/",
            type: "GET",
            data: {
                user_id: userId
            },
            headers: {
                'Authorization': "Bearer " + store.state.user.access,

            },
            success(resp) {
                posts.posts = resp
            }
        });

        const post_a_post = (content) => {
            posts.count++;
            posts.posts.unshift({
                id: posts.count,
                userId: 1,
                content: content
            })
        }
        const follow = () => {
            if (user.is_followd) return;
            user.is_followd = true;
            user.followcount++;

        }
        const unfollow = () => {
            if (!user.is_followd) return;
            user.is_followd = false;
            user.followcount--;
        }
        const is_me = computed(() => userId == store.state.user.id);

        return {
            is_me,
            user,
            follow,
            unfollow,
            posts,
            post_a_post
        }
    }
}
</script>
<style scope></style>
  

Userinfo页面

<template>
    <div class="card">
        <div class="card-body">
            <div class="row">
                <div class="col-3 img-field">
                    <img class="img-fluid" :src="user.photo" alt="我图片呢" />
                </div>
                <div class="col-9">
                    <div class="username">
                        {{ user.username }}
                    </div>
                    <div class="fans">粉丝数:{{ user.followcount }}</div>
                    <button v-if="!user.is_followd" @click="follow" type="button" class="btn btn-primary btn-sm">关注</button>
                    <button v-if="user.is_followd" @click="unfollow" type="button"
                        class="btn btn-primary btn-sm">取消关注</button>

                    <!---此处的btn-primary是控制按钮颜色,btn-sm是控制按钮大小 -->
                </div>
            </div>
        </div>
    </div>
</template> 
<script>
export default {
    name: "UserInfo",
    props: {
        user: {
            type: Object,      //参数的类型
            required: true,     //是否必须
        }
    }, setup(props, context) {
        const follow = () => {
            context.emit('follow');
        };
        const unfollow = () => {

            context.emit('unfollow');
        }
        return {
            follow,
            unfollow
        }
    }



}
</script>
<style scoped>
img {
    border-radius: 50%;
}

.username {
    /* 变成粗体 */
    font-weight: bold;
}

.fans {
    font-size: 15px;
    color: gray;
}

button {
    padding: 2px, 4px;
    font-size: 15px
}

.img-field {
    display: flex;
    flex-direction: column;
    justify-content: center;
}
</style>

在App.vue当中

<template>
  <NavBar></NavBar>
  <router-view :key="$route.fullPath" /> <!--用完整路径判重,这里重复路径不会跳转,判断有点神奇-->
</template>



<script>
import 'bootstrap/dist/css/bootstrap.css';
import 'bootstrap/dist/js/bootstrap';
import NavBar from './components/NavBar.vue'
export default {
  name: "App",
  components: {
    NavBar
  }
}

</script>

<style></style>

实现了用户动态页面的展示,以及判断自己或者别人的页面下展示内容不同 

添加帖子和删除帖子以及登录和关注功能实现

太麻烦了,建议去报课看吧

acwing

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

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

相关文章

数据结构——插入排序与希尔排序

&#x1f307;个人主页&#xff1a;_麦麦_ &#x1f4da;今日名言&#xff1a;喜你成疾&#xff0c;药石无医。——《玫瑰与鹿》 一、前言 在本篇文章&#xff0c;我们将为小伙伴们进行排序概念的基本讲解并具体讲解其中的两种基础排序&#xff1a;插入排序和希尔排序&#xff…

BSQ格式数据转换为RSD缺省的BIP格式数据

李国春 RSD内部统一以BIP格式排列数据&#xff0c;并且文件格式&#xff08;非TFS&#xff09;数据倒放&#xff08;North Down&#xff09;。早期是为了和设备无关位图&#xff08;DIB&#xff09;一致节省一点处理时间。现在设备处理能力增强了这点时间已经无关紧要&#xf…

目标检测复盘 -- 1.mAP及其他评价指标

前言 为什么想单独做一个目标检测篇&#xff0c;主要是感觉自己是个半吊子&#xff0c;满瓶不响、半瓶晃荡&#xff0c;找工作的过程中&#xff0c;也被很多面试官问到哑口无言&#xff0c;基础真的不扎实&#xff0c;自己非常虚&#xff0c;想好好地、静下心来捋一下&#xf…

Linux环境搭建及问题解决方案

本文介绍了Linux环境搭建的过程以及遇到的问题和解决方案&#xff0c;并且介绍了常用的Linux命令. 一、Linux环境搭建 整体所需的环节 安装VMware安装Linux &#xff08;这边我选的是Server版本&#xff09;安装配置Samba&#xff08;Samba是一种Linux和Windows之间进行文件共…

基础知识(王爽老师书第一章)

文章目录 基础知识1.1 引言1.2 机器语言1.2 引言汇编语言的产生1.3 汇编语言的组成1.4 存储器1.5 指令和数据1.6 存储单元1.7 CPU对存储器的读写1.8 地址总线1.9 数据总线1.10 控制总线小结检测点1.11.11 内存地址空间1.12 主板1.13 接口卡1.14 各类存储器芯片1.15 内存地址空间…

【Linux】在Ubuntu中下载jdk以及卸载oraclejdk

介绍 这里是小编成长之路的历程&#xff0c;也是小编的学习之路。希望和各位大佬们一起成长&#xff01; 以下为小编最喜欢的两句话&#xff1a; 要有最朴素的生活和最遥远的梦想&#xff0c;即使明天天寒地冻&#xff0c;山高水远&#xff0c;路远马亡。 一个人为什么要努力&a…

短视频矩阵系统源码/开发技术文档

短视频矩阵系统技术文档&#xff1a; 可以采用电子文档或者纸质文档的形式交付&#xff0c;具体取决于需求方的要求。电子文档可以通过电子邮件、远程指导交付云存储等方式进行传输、 短视频矩阵{seo}源码是指将抖音平台上的视频资源进行筛选、排序等操作&#xff0c;进而提升…

【AcWing刷题】蓝桥杯专题突破-动态规划-dp入门(17)

目录 写在前面&#xff1a; 题目&#xff1a;821. 跳台阶 - AcWing题库 题目描述&#xff1a; 输入格式&#xff1a; 输出格式&#xff1a; 数据范围&#xff1a; 输入样例&#xff1a; 输出样例&#xff1a; 解题思路&#xff1a; 方法一&#xff1a;暴力搜索 代码…

chatgpt赋能Python-pandas_归一化

Pandas归一化是什么&#xff1f; 数据归一化是数据预处理中的一个重要步骤&#xff0c;它能够将不同范围的数值转化为相同的数值范围。Pandas是一种数据处理工具&#xff0c;因此它提供了许多函数来实现数据归一化。其中最常用的函数是Normalization。 Normalization函数的使…

树形结构数据扁平化js方法

最近在公司项目中遇到树形结构数据,在进行遍历查找指定的数据的时候一搬进行递归调用的查询,因为递归是效率很慢的方式,尤其是在数据量特别大的时候是及其浪费性能,所以我想了一个树形结构扁平化的方法,代码如下: /**** param {Array} arrs 树形数据* param {string} childs 树…

Java面向对象程序设计实验报告(实验五 接口的练习)

✨作者&#xff1a;命运之光 ✨专栏&#xff1a;Java面向对象程序设计实验报告 ​ 目录 ✨一、需求设计 ✨二、概要设计 ✨三、详细设计 ✨四、调试结果 ✨五、测试结果 ✨附录&#xff1a;源程序代码&#xff08;带注释&#xff09; demo5类 Instrument类 Piano类 …

SpringSecurity入门

SpringSecurity 为什么要有SpringSecurity&#xff1f;SpringSecurity入门案例SpringSecurity基本原理SpringSecurity两个重要接口 SpringSecurity-web权限方案认证整合数据库 为什么要有SpringSecurity&#xff1f; 正如你可能知道的关于安全方面的两个主要区域是“认证”和“…

Linux:如何在虚拟机中装配JDK 与Tomcat服务器?【2023最新版】

Linux系统版本&#xff1a;centos 7.5 x64位 VMware版本&#xff1a; VMware Workstation Pro 16 Xshell工具版本&#xff1a;Xshell 7 &#xff08;for home and free&#xff09; Xftp工具版本&#xff1a;Xftp 7 &#xff08;for home and free&#xff09; 文章目录 一、如…

chatgpt赋能Python-pycharm_python版本切换

Pycharm Python版本切换指南 作为广受欢迎的Python IDE之一&#xff0c;Pycharm 提供了快捷的Python版本切换功能以适应不同的项目需求。本文将为您介绍如何在Pycharm 中进行Python版本切换&#xff0c;并解答一些与版本兼容性相关的常见问题。 如何在Pycharm中进行Python版本…

E6—4路GTX实现40G光纤通信2023-05-17

1.场景 从发送端&#xff08;一块硬件板卡&#xff09;通过40G QSFP接光纤连接到接收端&#xff08;另一块硬件板卡&#xff09;&#xff0c;实现从数据的发送与接收。连接如下&#xff0c;官方的example design即可实现这一功能&#xff0c;因此直接使用官方的代码即可。 2.硬…

【Redis】聊一下RDB持久化机制

上一篇文章中&#xff0c;AOF虽然可以通过重写机制减少AOF文件的大小&#xff0c;但是AOF数据恢复的时候依然是一个很耗费时间的操作&#xff0c;那么也就是不能够快速的进行数据的恢复&#xff0c;RDB正好可以解决这个问题。 RDB RDB&#xff08;Redis 数据库&#xff09;&a…

深度学习用于医学预后-第二课第四周5-10节-为个体患者制定风险评估模型

文章目录 相对风险按风险对患者进行排序个体与基线风险吸烟者与不吸烟者年龄对风险的影响 在本课中&#xff0c;您将学习 Cox 比例风险模型(Cox Proportional Hazards Model)。您将了解 Cox 模型如何考虑患者变量来比较不同患者的风险&#xff0c;使用他们的患者概况。 但到目前…

“出圈”警博会,欧科云链推动链上合规监管进程

5月13日&#xff0c;在由公安部主办的第11届中国国际警用装备博览会&#xff08;下简称“警博会”&#xff09;上&#xff0c;欧科云链接受中国警察网邀请&#xff0c;展开了“链上天眼科技助警”成果分享会&#xff0c;分享欧科云链持续创新应用区块链技术助力智慧警务的成果。…

chatgpt赋能Python-pandas_错位相减

Pandas&#xff1a;错位相减的重要性 如果你使用pandas进行数据处理&#xff0c;在一些数据分析的场景中你必须要逐行遍历并做一些数学计算&#xff0c;譬如你想要计算数据集中的同一列中相邻行之间的差异或“错位相减”以获得新的数据列。这在分析股票价格、交易和其他时间序…

nodejs 框架选型express koa egg midwayjs nestjs 对比

最近要做个开源项目&#xff0c;又要写node 工程&#xff0c;之前用的是koa 框架&#xff0c;最近看到了nestjs egg midwayjs 等框架一时间难以抉择。 人工智能的答案 文心一言 midwayjs 还写错了&#xff0c;感觉的很少&#xff0c;最后总结等于白说各有千秋。 chatgpt 好…