IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> Vue框架 -> 正文阅读

[JavaScript知识库]Vue框架

前言

? ? ? ? ? 学习 Vue 框架 内容!

简介

vue 会将所有的组件打包成一个 js 文件,采用前端渲染。
整个项目的设计要从上往下来进行构思。

组成

views:用于写各个页面,每个页面对应一个 view,里面也可以写组件。
components:组件。
router:路由。
main.js:整个的入口,根组件,将根组件挂载到 index.html 里。
.vue:每个页面是一个 .vue 文件,是 vue 自定义的文件类型,每个 .vue 文件都有三部分组成,分别是 htmlcssjs。每个 .vue 文件都会 export 一个对象。

<template>
  <ContentBase>
    首页
  </ContentBase>
</template>

<script>
import ContentBase from '../components/ContentBase';
// components表示在template区域会用到哪些组件,用到的全部放到components里,container可以响应式调整中间区域大小
export default {
  name: 'HomeView',
  components: {
    ContentBase,
  }
}
</script>

<style scoped>

</style>


特点

  1. 每个页面(.vue 文件)定义好 html 后,通过将 css 文件和 js 文件动态引入。
    在这里插入图片描述
  2. 组件化的框架
    一个页面需要拆分成若干不同的部分,每个部分用组件实现,每个组件又可以单独拆分,每个组件由 htmlcssjs 组成,定义完组件后,通过 <组件/> 的方式在其它组件中使用。

在这里插入图片描述

个人空间项目简介

  1. 项目图示如下:
    在这里插入图片描述

  2. 导航栏(NavBar):不同内容中不同页面对应的导航栏不变。

  3. 页面不同(Content):分成多个页面如下,每个页面用组件实现。

    • 首页:每个页面的首页都相同
    • 好友列表:可以索引到所有好友
    • 好友动态:展示发过所有的帖子
    • 登录
    • 注册
    • 404

项目实现

导航栏实现

所用知识点:路由,不同页面(组件)对应不同的 urlrouter-link 实现前端渲染。

// router->index.js
import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '../views/HomeView.vue';
import LoginView from '../views/LoginView';
import NotFoundView from '../views/NotFoundView';
import RegisterView from '../views/RegisterView';
import UserListView from '../views/UserListView';
import UserProfileView from '../views/UserProfileView';

const routes = [
  {
    path: '/',  // 路径
    name: 'home',  // 定义路径的名字,也html对应
    component: HomeView
  },
  {
    path: '/userlist',
    name: 'userlist',
    component: UserListView
  },
  {
    path: '/login',
    name: 'login',
    component: LoginView
  },
  {
    path: '/register',
    name: 'register',
    component: RegisterView
  },
  {
    path: '/userprofile',
    name: 'userprofile',
    component: UserProfileView
  },
  {
    path: '/404',
    name: '404',
    component: NotFoundView
  },

]

const router = createRouter({
  history: createWebHistory(),
  routes
})

export default router
// 导航栏
<template>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
  <div class="container">
    <router-link class="navbar-brand" :to="{name: 'home'}">我的空间</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" :to="{name: 'home'}">首页</router-link>
        </li>
        <li class="nav-item">
          <router-link class="nav-link" :to="{name: 'userlist'}">好友列表</router-link>
        </li>
        <li class="nav-item">
          <router-link class="nav-link" :to="{name: 'userprofile'}">用户动态</router-link>
        </li>
      </ul>
      <ul class="navbar-nav">
        <li class="nav-item">
          <router-link class="nav-link" :to="{name: 'login'}">登录</router-link>
        </li>
        <li class="nav-item">
          <router-link class="nav-link" :to="{name: 'register'}">注册</router-link>
        </li>
      </ul>
    </div>
  </div>
</nav>
</template>

<script>
export default {
    name: "NavBar",
}
</script>


用户动态页面

1. 知识点

  1. 当某个组件(父组件)调用另一个组件(子组件)时,父组件中有子元素,子元素传递给组件,子组件通过 slot 接收所有的子元素,<slot></slot> 存放父组件传过来的children。
  2. 组件间数据交互
    • 多个组件进行数据交互时,将数据放到最顶层的组件中,这里最顶层的组件为用户动态组件。
    • export default 中定义
      • setup(props, context) :定义并初始化变量、定义函数,在 setup 中定义的只有 return 之后才能在当前 templante 中使用。
        • ref :定义变量,当变量需要重新赋值时用 ref 定义,() 中内容用于初始化初值。
        • reactive:当变量不需要重新赋值时用 reactive 定义,只能定义对象,() 中内容用于初始化初值。
        • props存储父组件传递过来的数据。
        • context.emit():触发父组件绑定的函数
    • 不同组件间传递信息:父组件传子组件数据通过 props 接收,子组件调用父组件通过事件的方式调用父组件中的函数
      • 传数据,给父组件绑定属性通过 :名字 = "在setup中定义的变量名"{{}} 取值
    • template
      • v-if:当条件成立此标签显示出来,不成立则隐藏掉。
      • v-on:click或 @click 属性:绑定事件。子组件想要修改父组件中的数据,通过绑定事件的方式触发父组件中的函数进而修改父组件中的数据。@事件名 = ”绑定的函数名“
      • v-for 属性:循环,:key循环的每个元素需要有唯一的 key

2. 代码

// 公共部分(首页)
<template>
  <div class="home">
    <div class="container">
      <div class="card">
        <div class="card-body">
          <slot></slot>   // 组件作为一个样式,里面的内容通过其它组件调用传过去,通过slot接收所有的子元素
        </div>
      </div>
    </div>
  </div>    
</template>

<script>

export default {
    name: "ContentBase",
}
</script>


<style scoped>
.container {
  margin-top: 20px;
}
</style>
// 用户个人信息
<template>
    <div class="card">
        <div class="card-body">
            <div class="row">
                <div class="col-3">
                    <img class="img-fluid" src="https://lh1.hetaousercontent.com/static/e643aba1d4f5d678" alt="">
                </div>
                <div class="col-9">
                    <div class="username">{{fullName}}</div>
                    <div class="fans">粉丝:{{user.followerCount}}</div>
                    <button @click="follow" v-if="!user.is_followed" type="button" class="btn btn-secondary btn-sm">+关注</button>
                    <button @click="unfollow" v-if="user.is_followed" type="button" class="btn btn-secondary btn-sm">取消关注</button>
                </div>
            </div>
        </div>
    </div>
    
</template>

<script>
import {computed} from 'vue';

export default {
    name: "UserProfileInfo",
    // 将从父组件接收的参数放到props里,将父组件中的user参数接收过来
    props: {
        user: {
            type: Object,
            required: true,  // 必须填的
        },
    },

    setup(props,context) {
        let fullName = computed(() => props.user.lastName + ' ' + props.user.firstName);
        
        const follow = () => {
            context.emit("follow");
        }

        const unfollow = () => {
            context.emit("unfollow");
        }
        
        return {  // 只有将定义的返回之后才可以用
            fullName,
            follow,
            unfollow,
        }
    }
}
</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>
// 发帖列表
<template>
    <div class="card">
        <div class="card-body">
            <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>

// 发帖栏
<template>
    <div class="card edit-field">
        <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 @click="post_a_post" type="button" class="btn btn-success btn-sm">发帖</button>
        </div>
    </div>
</template>

<script>
import {ref} from 'vue'
export default {
    name: "UserProfileWrite",
    setup(props, context) {
        let content = ref('');

        const post_a_post = () => {
            context.emit('post_a_post', content.value);
            content.value = "";
        }

        return {
            content,
            post_a_post
            // content: content
        }
    }
}
</script>

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

// 用户动态页面
<template>
  <ContentBase>
    <div class="row">
      <div class="col-3">
        <UserProfileInfo @follow="follow" @unfollow="unfollow" :user="user"/>
        <UserProfileWrite @post_a_post="post_a_post" />
      </div>
      <div class="col-9">
        <UserProfilePosts :posts="posts"/>
      </div>
    </div>
  </ContentBase>
</template>

<script>
// 当父组件事件名post_a_post事件出发时调用post_a_post函数处理父组件中的数据
import ContentBase from '../components/ContentBase';
import UserProfileInfo from '../components/UserProfileInfo';
import UserProfilePosts from '../components/UserProfilePosts';
import UserProfileWrite from '../components/UserProfileWrite';
import {reactive} from 'vue';
// components表示在template区域会用到哪些组件,用到的全部放到components里,container可以响应式调整中间区域大小
export default {
  name: 'UserProfile',
  components: {
    ContentBase,
    UserProfileInfo,
    UserProfilePosts,
    UserProfileWrite
  },
  // setup: () => {

  // }   简写为下面
  // 将数据存储到最顶层的组件,当前组件为最顶层组件,下面包含UserProfileInfo和UserProfilePosts
  setup() {
    const user = reactive({  // reactive用来定义对象
      id: 1,
      username: "Yjx",
      lastName: "Y",
      firstName: "jx",
      followerCount: 0,
      is_followed: false,
    });

    const posts = reactive({
      count: 3,
      posts: [
        {
          id: 1,
          userId: 1,
          content: "今天冲了!",
        },
        {
          id: 2,
          userId: 2,
          content: "今天冲猛了!",
        },
        {
          id: 3,
          userId: 3,
          content: "今天冲不动了!",
        },
      ]
    })

    const follow = () => {
      if (user.is_followed) return;  // 避免重复关注
      user.is_followed = true;  // 没关注,关注一下
      user.followerCount ++;
    }

    const unfollow = () => {
      if (!user.is_followed) return;
      user.is_followed = false;
      user.followerCount --;
    }

    const post_a_post = (content) => {
      posts.count ++;
      posts.posts.unshift({
          id: posts.count,
          userId: 1,
          content: content,
      })
    }

    // 返回的内容就可以在html部分调用了
    return {
      user,  // 简写
      // user: user
      follow,
      unfollow,
      posts,
      post_a_post
    }
  }

}
</script>

<style scoped>

</style>

vuex

维护全局变量的机制,在全局维护一个对象(状态树)
state:存储所有数据。
getters:对 state 里的内容需通过计算获得的内容放到 getters 中,只能读取,不能进行修改。
actions:更新 state 的操作。
mutations:对 state 的直接修改(= 操作)放到 mutations。
modules:对state 里面的内容进行拆分,避免 state 内容太多,代码复杂冗余。modules 维护的是 state 里的对象,还属于 state 里,维护时同样具有 getters,actions, mutations 这几个属性

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2022-07-17 16:13:49  更:2022-07-17 16:15:25 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 13:43:22-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码