【Web开发手礼】探索Web开发的魅力(十二)-Vue(2)用户动态页面

news2024/11/20 9:29:23

前言

主要介绍了用vue框架创建用户动态页面的具体过程,可以帮助学习vue框架的基本知识!!!!


用户动态页面

Alt

用户信息

Alt

用户头像

通过 Bootstrap 所提供的 .img-fluid 类让图片支持响应式布局。其原理是将 max-width: 100%; 和 height: auto; 赋予图片,以便随父元素的宽度变化一起缩放。

 <img src="../assets/log.jpg" class="img-fluid" alt="用户头像">

将头像设置为圆形:

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

Alt

用户信息体

<template>
    <div class="card">
        <div class="card-body">
            <div class="row">
                <div class="col-3">
                <img src="../assets/log.jpg" class="img-fluid" alt="用户头像">
                </div>
            
                <div class="col-9">
                    <div class="username">hgq</div>
                    <div class="fans">粉丝:3000</div>
                    <button type="button" class="btn btn-info btn-sm" >关注</button>
                </div>
            </div>
        </div>
    </div>
</template>

<script>
export default{
    name: 'UserProfileInfo',
}
</script>

<style scoped>
img{
    border-radius: 50%;
}
.username{
    font-weight: bold;
}
.fans{
    font-size: 12px;
    color: gray;
}
button{
    padding: 2px 4px;
    font-size: 12px;
}
</style>

Alt
当我们需要动态的获取用户的头像、姓名、粉丝数等信息,我们需要把对象信息放在最高层,这样它的子组件也可以获取信息。
在UserProfileView.vue文件中:

<script>
import ContentBase from '@/components/ContentBase.vue';
import UserProfileInfo from '@/components/UserProfileInfo.vue';
import UserProfilePosts from '@/components/UserProfilePosts.vue';
import { reactive } from 'vue';

export default{
    name: "UserProfileView",
    components: {
        ContentBase,
        UserProfileInfo,
        UserProfilePosts
    },
    setup(){
        const user = reactive({
            id: 1,
            username: 'hgq',
            lastName: 'h',
            firstName: 'gq',
            followerCount: 0,
            is_followed: false
        });
        return {
            user: user
        }
    }
}
</script>

reactive 和 setup 函数:

  • reactive 是 Vue 3 Composition API 中的一个函数,用于将普通对象转换为响应式对象。这意味着当对象的属性发生变化时,相关的视图会自动更新以反映这些变化。
  • reactive 是 Vue 3 Composition API 中的一个函数,用于将普通对象转换为响应式对象。这意味着当对象的属性发生变化时,相关的视图会自动更新以反映这些变化。

user 对象:

  • 在 setup 函数中,首先创建了一个名为 user 的响应式对象。这个对象包含了用户的各种信息
    • id: 用户的唯一标识符,这里设置为 1。
    • username: 用户名,设置为 ‘hgq’。
    • lastName 和 firstName: 用户的姓和名,分别设置为 ‘h’ 和 ‘gq’。
    • followerCount: 用户的粉丝数量,初始化为 0。
    • is_followed: 表示当前用户是否被关注,初始化为 false。

return 语句:

  • setup 函数通过 return 返回一个对象,对象中包含了 setup 函数中定义的 user 对象。在 Vue 3 中,通过 return 返回的属性和方法可以在模板中使用,也可以在组件逻辑中进行操作。
<UserProfileInfo v-bind:user="user">

</UserProfileInfo>

v-bind:user=“user” 是 Vue.js 中用于将数据从父组件传递到子组件的方式。在这里,user 是一个父组件中定义的数据对象,它将作为 UserProfileInfo 组件的一个名为 user 的属性。
v-bind:user=“user” 可以缩写为 :user=“user”,这是 Vue.js 提供的语法糖,用来简化属性绑定的书写。

子组件获得高级传过来的参数

<div class="col-9">
     <div class="username">{{user.username}}</div>
      <div class="fans">粉丝:{{user.followerCount}}</div>
      <button type="button" class="btn btn-info btn-sm" >关注</button>
  </div>
<script>
export default{
    name: 'UserProfileInfo',
    props: {
        user: {
            type: Object,
            required: true
        }
    }
}
</script>

user 的定义为:

  • type: Object 表示这个 user 属性的类型是一个对象。这是 Vue.js 中 props 的一个重要特性,通过类型声明可以进行类型检查,确保传入的数据符合预期的格式。
  • required: true 表示 user 这个属性是必须的,即父组件在使用 UserProfileInfo 组件时必须传递一个 user 对象作为属性。

动态改变,当父级对应的参数修改,子级对应修改

<div class="col-9">
   <div class="username">{{username}}</div>
   <div class="fans">粉丝:{{followerCount}}</div>
    <button type="button" class="btn btn-info btn-sm" >关注</button>
</div>
<script>
import { computed } from 'vue';
export default{
    name: 'UserProfileInfo',
    props: {
        user: {
            type: Object,
            required: true
        }
    },
    setup(props){
        let username = computed(() => props.user.username);
        let followerCount = computed(() => props.user.followerCount);
        return{
            username,
            followerCount
        }

    }
}
</script>

setup(props) 是 Vue 3 中组合式 API 的一部分,用于设置组件的响应式状态、计算属性、方法等。它接收一个参数 props,用来接收从父组件传递过来的属性数据。

计算属性的创建:

  • computed(() => props.user.username) 和 computed(() => props.user.followerCount) 是使用 computed 函数创建的计算属性。
  • computed 函数接收一个函数作为参数,这个函数返回计算后的值。Vue 3 会自动追踪计算属性所依赖的响应式数据(在这里是 props.user.username 和 props.user.followerCount),并在依赖数据变化时重新计算并更新计算属性的值。

现在我们要实现点击关注按钮,此时按钮变为取消关注,表示已经关注了;点击取消关注,按钮变为关注,表示取消关注了。

<button v-on:click="followed" v-if = "!user.is_followed" type="button" class="btn btn-info btn-sm" >关注</button>
 <button v-on:click="unfollowed" v-if = "user.is_followed" type="button" class="btn btn-info btn-sm" >取消关注</button>

当然我们还得实现具体的followed和unfollowed函数。
UserProfileInfo.vue文件中的user是从父级UserProfileView.vue文件传过去的,此时我们想要修改user的is_followed,那么我们就需要从子级传送值到父级。
子组件向父组件传递信息是通过绑定事件的方法
子类通过触发followed和unfollowed函数来向高级即UserProfilieView.vue界面传达。

 setup(props,context){
        let username = computed(() => props.user.username);
        let followerCount = computed(() => props.user.followerCount);
        const followed = () =>{
            context.emit('followed');
        };
        const unfollowed = () =>{
            context.emit('unfollowed');
        };
        return{
            username,
            followerCount,
            followed,
            unfollowed
        }

    }
}
</script>

父级UserProfilieView.vue界面通过判断子级传过来哪个函数来进行具体的响应。

<UserProfileInfo v-bind:user="user" @followed = "followed" @unfollowed = "unfollowed">
 </UserProfileInfo>
 
 <script>
import ContentBase from '@/components/ContentBase.vue';
import UserProfileInfo from '@/components/UserProfileInfo.vue';
import UserProfilePosts from '@/components/UserProfilePosts.vue';
import { reactive } from 'vue';

export default{
    name: "UserProfileView",
    components: {
        ContentBase,
        UserProfileInfo,
        UserProfilePosts
    },
    setup(){
        const user = reactive({
            id: 1,
            username: 'hgq',
            lastName: 'h',
            firstName: 'gq',
            followerCount: 1000,
            is_followed: true
        });
        const followed = () => {
            if(user.is_followed){
                return;
            }
            user.is_followed = true;
            user.followerCount++;
        };
        const unfollowed = () => {
            if(!user.is_followed){
                return;
            }
            user.is_followed = false;
            user.followerCount--;
        };
        return {
            user: user,
            followed,
            unfollowed
        }
    }
}

UserProfileView 组件,它包含了一个 UserProfileInfo 组件,并向其传递了 user 数据和两个事件 followed 和 unfollowed。

  • 同时,使用 @followed=“followed” 和 @unfollowed=“unfollowed” 将 followed 和 unfollowed 事件绑定到子组件上,以便子组件可以在相应的操作时调用这两个方法。
  • followed 方法用来处理用户关注操作,当用户已关注时,不执行任何操作;否则将 user.is_followed 设置为 true,并增加 followerCount。
  • unfollowed 方法用来处理用户取消关注操作,当用户未关注时,不执行任何操作;否则将 user.is_followed 设置为 false,并减少 followerCount。
    Alt
    Alt

帖子列表

此时我们需要在UserProfileView.vue中先把帖子的内容声明出来,然后再将帖子的内容传到子组件UserProfilePosts.vue中。

<UserProfilePosts v-bind:posts="posts">

</UserProfilePosts>
<script>
import ContentBase from '@/components/ContentBase.vue';
import UserProfileInfo from '@/components/UserProfileInfo.vue';
import UserProfilePosts from '@/components/UserProfilePosts.vue';
import { reactive } from 'vue';

export default{
    name: "UserProfileView",
    components: {
        ContentBase,
        UserProfileInfo,
        UserProfilePosts
    },
    setup(){
        const user = reactive({
            id: 1,
            username: 'hgq',
            lastName: 'h',
            firstName: 'gq',
            followerCount: 0,
            is_followed: false
        });
        const posts = reactive({
            count: 3,
            posts: [
                {
                    id: 1,
                    userId: 1,
                    content: 'vue框架练习!!!'
                },
                {
                    id: 2,
                    userId: 2,
                    content: '玩梗大赛!!!'
                },
                {
                    id: 3,
                    userId: 3,
                    content: '最喜欢的动物!!!'
                },
            ]
        });
        const followed = () => {
            if(user.is_followed){
                return;
            }
            user.is_followed = true;
            user.followerCount++;
        };
        const unfollowed = () => {
            if(!user.is_followed){
                return;
            }
            user.is_followed = false;
            user.followerCount--;
        };
        return {
            user: user,
            followed,
            unfollowed,
            posts
        }
    }
}
</script>

将posts作为一个prop传递给名为UserProfilePosts的组件。在Vue中,可以使用v-bind或其简写形式:来传递prop。
在UserProfilePosts组件中接收和使用posts:在UserProfilePosts组件内部,定义posts作为一个prop,并根据需要使用它,类型为 Object,并且必须被传入(required: true)

<template>
    <div class="card">
        <div class="card-body">
            {{ posts }}
        </div>
    </div>
</template>

<script>
export default{
    name: 'UserProfilePosts',
    props: {
        posts: {
            type: Object,
            required: true
        },
    }
}
</script>

<style scoped>

</style>

Alt

<template>
    <div class="card">
        <div class="card-body">
            <!--我们传过来的posts是对象,它的第一个值是count,第二个值是posts-->
            <div v-for="post in posts.posts" :key="post.id">
                <div class="card single-post">
                    <div class="card-body">
                        {{ post.content }}
                    </div>
                </div>
            </div>
        </div>
    </div>
</template>

<script>
export default{
    name: 'UserProfilePosts',
    props: {
        posts: {
            type: Object,
            required: true
        },
    }
}
</script>

<style scoped>
.single-post{
    margin-bottom: 10px;
}
</style>
  • div class=“card”> 和
    用来创建一个卡片样式的容器,用于包裹帖子列表。
  • v-for=“post in posts.posts” 遍历传入的 posts 对象的 posts 属性,这个属性应该是一个数组,包含了多个帖子对象。
  • :key=“post.id” 为每个帖子项提供唯一的标识符,Vue 使用这个标识符来高效地更新 DOM。
  • 单个帖子之间的底部间距10px

Alt

发帖子

整体框架

<template>
    <div class="card edit-filed">
        <div class="card-body">
            <label for="edit-post" class="form-label">编辑帖子</label>
            <textarea class="form-control" id="edit-post" rows="3"></textarea>
            <button type="button" class="btn btn-primary btn-sm">发帖</button>
        </div>
    </div>

</template>


<script>
export default{
    name: 'UserProfileWrite',
    
}
</script>

<style scoped>
.edit-filed{
    margin-top: 10px;
}
button{
    margin-top: 10px;
}
</style>

Alt

<textarea v-model="content" class="form-control" id="edit-post" rows="3"></textarea>
<script>
import { ref } from 'vue';
export default{
    name: 'UserProfileWrite',
    setup(){
        let content = ref('');
        return{
            content: content
        }
    }
}
</script>

在模板中使用 v-model 指令将 textarea 组件与 content 双向绑定。这意味着当用户在文本框中输入内容时,content 的值会自动更新;反之亦然。

  • import { ref } from ‘vue’:导入 Vue 3 的 ref 函数,用于创建响应式数据。
  • setup():是 Vue 3 Composition API 的入口点。在这里可以定义组件的数据、方法等。
  • let content = ref(‘’):使用 ref 创建一个名为 content 的响应式对象,初始值为空字符串 ‘’。
  • return { content: content }:将 content 对象暴露出去,以便模板可以访问和绑定它。
<template>
    <div class="card edit-filed">
        <div class="card-body">
            <label for="edit-post" class="form-label">编辑帖子</label>
            <textarea v-model="content" class="form-control" id="edit-post" rows="3"></textarea>
            <button v-on:click="posted" type="button" class="btn btn-primary btn-sm">发帖</button>
        </div>
    </div>

</template>


<script>
import { ref } from 'vue';
export default{
    name: 'UserProfileWrite',
    setup(props,context){
        let content = ref('');
        const posted = () => {
            context.emit('posted',content.value);
            content.value = "";
        };
        return{
            content: content,
            posted
        }
    }
}
</script>

<style scoped>
.edit-filed{
    margin-top: 10px;
}
button{
    margin-top: 10px;
}
</style>
  • : 使用 v-on 指令绑定 click 事件到 posted 方法,点击按钮时触发 posted 方法。
  • const posted = () => { … }: 定义 posted 方法,在点击按钮时触发。它执行以下操作:
    • 使用 context.emit(‘posted’, content.value) 发送一个自定义事件 ‘posted’,并传递 content.value 作为参数。
    • 清空 content.value,以便下次编辑新帖子时开始空白。
  • return { content, posted }: 在 setup 函数中返回 content 和 posted,使它们能够在模板中使用。
    UserProfileView.vue中部分代码如下:
<UserProfileWrite @posted = "posted">

</UserProfileWrite>
const posted = (content) => {
      posts.count++,
      posts.posts.unshift({
            id: posts.count,
            userId: 1,
            content: content
      })
 };
 return {
    user: user,
    followed,
    unfollowed,
     posts,
     posted
 }
  • 在父组件中使用了 组件,并且绑定了 posted 事件到父组件的 posted 方法。
  • posted 方法接收一个 content 参数,用于将新的帖子内容添加到 posts 数据中。具体操作包括:
    • posts.count++:增加帖子计数器。
    • posts.posts.unshift({ … }):将新的帖子对象添加到 posts.posts 数组的开头,保证最新的帖子显示在列表顶部。

通过 return 返回要使用的方法和变量。

Alt


总结

主要介绍了用vue框架创建用户动态页面的具体过程,可以帮助学习vue框架的基本知识!!!!


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

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

相关文章

Java面试八股之Spring boot的自动配置原理

Spring boot的自动配置原理 Spring Boot 的自动配置原理是其最吸引人的特性之一&#xff0c;它大大简化了基于 Spring 框架的应用程序开发。以下是 Spring Boot 自动配置的基本原理和工作流程&#xff1a; 1. 启动类上的注解 Spring Boot 应用通常会在主类上使用 SpringBoot…

ZBrush入门使用介绍——4、笔刷选项说明

大家好&#xff0c;我是阿赵。   这次来看看ZBrush的笔刷的选项用法。 一、选择笔刷 点击笔刷&#xff0c;可以打开笔刷选择面板。 在最上面的Quick Pick&#xff0c;有最近使用过的笔刷&#xff0c;可以快速的选择。下面有很多可以选择的笔刷。但由于笔刷太多&#xff0c;…

AJAX之基础知识

目录 AJAX入门及axios使用什么是AJAX怎么用AJAX 认识URL协议域名资源路径URL查询参数 查询参数URL查询参数axios查询参数 常用请求方法axios请求配置 axios错误处理HTTP协议请求报文请求报文-错误排查响应报文HTTP响应状态码 form-serialize插件 AJAX入门及axios使用 什么是AJ…

【Python机器学习】决策树的构造——信息增益

决策树是最经常使用的数据挖掘算法。它之所以如此流行&#xff0c;一个很重要的原因就是不需要了解机器学习的知识&#xff0c;就能搞明白决策树是如何工作的。 决策树的优缺点&#xff1a; 优点&#xff1a;计算复杂度不高&#xff0c;输出结果易于理解&#xff0c;对中间值的…

RabbitMq手动ack的超简单案例+Confirm和Return机制的配置和使用

最简单的例子 先简单介绍一下这三个方法 basicAck 表示确认成功&#xff0c;使用此方法后&#xff0c;消息会被rabbitmq broker删除 basicNack 表示失败确认&#xff0c;一般在消费消息业务异常时用到此方法&#xff0c;可以将消息重新投递入队列 basicReject 拒绝消息&am…

Chainlit一个快速构建成式AI应用的Python框架,无缝集成与多平台部署

概述 Chainlit 是一个开源 Python 包&#xff0c;用于构建和部署生成式 AI 应用的开源框架。它提供了一种简单的方法来创建交互式的用户界面&#xff0c;这些界面可以与 LLM&#xff08;大型语言模型&#xff09;驱动的应用程序进行通信。Chainlit 旨在帮助开发者快速构建基于…

全网最适合入门的面向对象编程教程:25 类和对象的 Python 实现-Python 判断输入数据类型

全网最适合入门的面向对象编程教程&#xff1a;25 类和对象的 Python 实现-Python 判断输入数据类型 摘要&#xff1a; 本文主要介绍了在使用 Python 面向对象编程时&#xff0c;如何使用 type 函数、isinstance 函数和正则表达式三种方法判断用户输入数据类型&#xff0c;并对…

PWA(渐进式网页应用)方式实现TodoList桌面应用

参考&#xff1a; https://cloud.tencent.com/developer/article/2322236 todlist网页参考&#xff1a; https://blog.csdn.net/weixin_42357472/article/details/140657576 实现在线网页当成app应用&#xff1a; 一个 PWA 应用首先是一个网页, 是通过 Web 技术编写出的一个网…

如何全面提升架构设计的质量?

当我们从可扩展、高可用、高性能等角度设计出来架构的时候&#xff0c;我们如何优化架构呢&#xff1f;就需要从成本、安全、测试等角度进行优化。 如何设计更好的架构 - 步骤 成本 低成本复杂度本质 低成本手段和应用 低成本的主要应用场景 安全 安全性复杂度本质 架构安全…

大语言模型系列-Transformer:深入探索与未来展望

大家好&#xff0c;我是一名测试开发工程师&#xff0c;已经开源一套【自动化测试框架】和【测试管理平台】&#xff0c;欢迎大家联系我&#xff0c;一起【分享测试知识&#xff0c;交流测试技术】 Transformer模型自其问世以来&#xff0c;便迅速在自然语言处理领域崭露头角&a…

2024年【危险化学品生产单位安全生产管理人员】最新解析及危险化学品生产单位安全生产管理人员考试总结

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 危险化学品生产单位安全生产管理人员最新解析参考答案及危险化学品生产单位安全生产管理人员考试试题解析是安全生产模拟考试一点通题库老师及危险化学品生产单位安全生产管理人员操作证已考过的学员汇总&#xff0c;…

mysql基本数据类型(整型)

一、 常见面试题 整型都有哪些基础类型&#xff0c;各占几个字节 tinyint, smallint, mediumint, int, bigint: 1 2 3 4 8 int(n) 是什么意思&#xff0c;什么时候用到 指定显示位宽&#xff0c;需配合 zerofill 使用&#xff08;不够位宽则在前面补0&#xff09;&#xff0c;…

Could not find a version that satisfies the requirement

Could not find a version that satisfies the requirement 目录 Could not find a version that satisfies the requirement 【常见模块错误】 【解决方案】 欢迎来到英杰社区https://bbs.csdn.net/topics/617804998 欢迎来到我的主页&#xff0c;我是博主英杰&#xff0c;2…

MATLAB被360误杀的解决方案

前面被误杀&#xff0c;今天又被误杀。 前面误杀结果是缺少文件&#xff0c;重装MATLAB也不行。 结果重装了操作系统。 这次&#xff0c;看到了提示额外小心。 当时备份了“病毒”文件&#xff0c;结果备份的也被杀了。 解铃还须系铃人 在360安全卫士里面恢复&#xff0c;步骤…

线性代数|机器学习-P27用于深度学习的神经网络结构

文章目录 1. 概述2. 参数定义3. CNN 网络 1. 概述 – 1. 卷积神经网络 CNNs – 2. 连续型线性分段函数 F – 3. 损失函数 – 4. 链式法则计算反向传播算法梯度 ∇ F g r a d F \nabla F \mathrm{grad}\; F ∇FgradF 2. 参数定义 我们定义每个样本有m维度特征&#xff0c;有…

java找不到符号解决办法

一、java找不到符号 如果你的代码里没有报错&#xff0c;明明是存在的。但是java报错找不到符号。如下所示&#xff0c; 二、解决步骤 1.清除编码工具缓存 本人用的idea&#xff0c; eclipse清除缓存方式有需要的可以百度一下&#xff01; 2.如果是mavne项目的 先clean 再…

流媒体服务器一:使用成熟的流媒体SRS 搭建 RTMP流媒体服务器

1 安装和测试srs流媒体服务器 服务器&#xff1a;SRS(Simple RTMP Server&#xff0c;⽀持RTMP、HTTP-FLV&#xff0c;HLS) 推流端&#xff1a;ffmpeg OBS 拉流端&#xff1a;ffplay VLC srs播放器 1.1 安装srs流媒体服务器 官网 SRS (Simple Realtime Server) | SRS 码…

大模型算法面试题(十四)

本系列收纳各种大模型面试题及答案。 1、微调后的模型出现能力劣化&#xff0c;灾难性遗忘是怎么回事 微调后的模型出现能力劣化&#xff0c;灾难性遗忘&#xff08;Catastrophic Forgetting&#xff09;是一个在机器学习领域&#xff0c;尤其是在深度学习和大模型应用中频繁出…

【SpringBoot】6 全局异常捕获

介绍 在项目开发中&#xff0c;如果每个 Controller 都增加 try catch 方法去捕获异常及处理&#xff0c;就会导致代码变得很繁琐、效率低下&#xff0c;而大部分异常是不能直接向外抛出&#xff0c;需要有个统一的显示处理方法&#xff0c;因此需要加上全局异常捕获统一获取并…

深度学习中常用损失函数介绍

选择正确的损失函数对于训练机器学习模型非常重要。不同的损失函数适用于不同类型的问题。本文将总结一些常见的损失函数&#xff0c;并附有易于理解的解释、用法和示例 均方误差损失(MSE) loss_fn nn.MSELoss()py均方误差&#xff08;Mean Squared Error&#xff0c;简称 MSE…