前端开发笔记[2]-页面布局

摘要

使用vue.js和mdui进行简单页面布局,实现一个聊天网页的大致框架.

平台信息

  • macOS
  • safari:版本16.6 (18615.3.12.11.2)
  • node.js
  • "vue": "^2.5.2",
  • "vue-router": "^3.0.1"
  • "mdui": "^1.0.2",
  • "eslint": "^4.15.0"

CSS的viewport相关单位

视口(viewport)相关的单位 vwvh 等,如 100vw = 100% 视口宽度。但视口宽度是多少呢?响应式布局页面中,视口所发挥的作用如下。
viewport(视口)是用户可以看到的 Web 页面视口区域。在早期,许多 Web 页面没有针对移动端优化。由于移动设备像素比较低,多为 320px,从而在打开 PC 端的页面时,会因为视口太窄导致页面布局错乱。为了解决这个问题,浏览器会在一个虚拟视口中渲染页面,通常会将 viewport 设置为一个较大的值(如 Safari 默认是 980px),这样 PC 端的网页在移动设备浏览器上都能在一屏内显示所有内容,只是页面元素看上去比较小。用户可能需要通过水平滚动、缩放等操作才能查看页面的不同区域,体验很差。

但是,移动互联网发展了这么长时间,已经不再像移动互联网初始阶段一样存在大量超过 980px 的页面,同时,很多移动端站点都会使用媒体查询等其他技术来适配较窄的屏幕,那么浏览器提供的虚拟视口就不再必要了。
为了支持响应式布局,我们首先需要通过 viewport meta 标签正确设置页面的 viewport。一个针对移动端做过优化的站点中,应该包含以下类似的内容:

<meta name="viewport" content="width=device-width, initial-scale=1">

其中 width 控制视口的宽度,可以设置为设备宽度 device-width,或是具体的像素值。在上面的例子中,viewport 的宽度设置为 device-width。这意味着,如果屏幕宽度是 375px(如 iPhone X),则浏览器也使用 375px 的视口宽度来渲染页面,而不是使用 980px 或其他宽度使页面缩小展示。initial-scale=1 设置了浏览器首次加载页面时的初始缩放级别。我们还可以通过 minimum-scale 和 maximum-scale 等属性控制用户的缩放操作,但这也可能导致页面的可访问性问题。

mdui进行页面布局

[https://www.mdui.org/docs/introduction]
[https://gitee.com/zdhxiong/mdui]
MDUI:漂亮、轻量且好用,它能让你更轻松地开发 Material Design 网页应用.

MDUI 提供了一套响应式、移动设备优先的 12 列网格布局系统。

  • .mdui-col-xs-[1-12] 所有屏幕设备上都会生效,如手机、电脑等。
  • .mdui-col-sm-[1-12] 在小屏幕及以上的设备上生效,如平板电脑。
  • .mdui-col-md-[1-12] 在中等屏幕及以上的设备上生效,如笔记本电脑。
  • .mdui-col-lg-[1-12] 在大屏幕及以上的设备上生效,如台式电脑。
  • .mdui-col-xl-[1-12] 在特大屏幕设备上生效,如电视。
    混用这些类,可以达到响应式的效果。

添加涟漪动画效果后,会在点击元素时,产生向外扩散的水波纹效果。

vue.js的页面构成

[https://www.yisu.com/zixun/624919.html]
一个vue页面由三部分组成:

  1. template标签包裹的界面展示代码(HTML代码)
  2. script标签包裹的业务实现代码(js脚本代码)
  3. style标签包裹的界面布局代码(css样式代码)

现在流行的Vue项目中,Vue页面都是采用组件套娃的形式,由一个一个的组件拼接而成整个页面。一个组件就是一个.vue文件。

设置node的localhost为0.0.0.0

[https://blog.csdn.net/chinatopno1/article/details/104035082]
[https://segmentfault.com/q/1010000012132756?sort=created]
[https://blog.csdn.net/Cookysurongbin/article/details/86077241]
修改项目下config目录下的index.js的文件.

vue-cli搭建的环境,用nginx做代理服务器,访问时显示:Invalid Host header

经查是因为新版的webpack-dev-server出于安全考虑,默认检查hostname,如果hostname不是配置内的就不能访问。这样有2种方法,一种是设置跳过host检查,一种是直接host设置成你的地址。

  1. 关闭host检查
    可以在build目录下的webpack.dev.conf.js文件,devServer下添加disableHostCheck: true,跳过检查
    同样的原理,可以在package.json文件修改scripts命令:webpack-dev-server --disableHostCheck=true

  2. 设置成你的host,加入你的host是xxx.com,同样2中方法,修改配置文件,和script命令

在config目录下修改index.js文件的host,这个默认是localhost,可修改成 xxx.com
package.json的script语句: webpack-dev-server --host=xxx.com或者--public=xxx.com.

vim package.json
#修改scripts命令:webpack-dev-server --disableHostCheck=true
vim config/index.js
#host: '0.0.0.0'
#port: 8666

访问[127.0.0.1:8666]即可.

实现

目录结构

./components
├── MessageBubbleMe.vue
├── MessageBubbleShe.vue
├── test-cookie.vue
├── test-indexedDB.vue
├── test-mdui.vue
└── test-webStorage.vue

./pages
├── ChatPage.vue
├── HelloWorld.vue
├── LoginPage.vue
├── SettingsPage.vue
└── SideBarPage.vue

关键代码

ChatPage.vue

<!--主页面-->
<template>

<!--start 顶层容器-->
<div class="mdui-row">

<!--start 侧边栏容器-->
<div class="mdui-col-md-3" id="chatpage-sidebar" style="background-color:#c7edcc;height:100vh;opacity: 0.8;/*80%透明度*/">
 <!-- 侧边栏内容 -->
 <SideBarPage />
</div>
<!--end 侧边栏容器-->

<!--start 聊天区容器-->
<div class="mdui-col-sm-12 mdui-col-md-9" id="chatpage-content" style="background-color:white;height:100vh;opacity: 0.8;/*80%透明度*/">

        <!-- start 消息区域 MessageArea -->
        <div class="message-area">

            <!-- 自动插入消息气泡 -->

        <!-- end 消息区域 MessageArea -->
        </div>

      <!-- start 编辑区域 EditArea -->
      <div class="edit-area">

        <!-- start 编辑文本块 -->
        <div class="edit-text-block mdui-textfield">

            <textarea class="mdui-textfield-input mdui-ripple" rows="4" placeholder="在这里输入内容..."></textarea>

        <!-- end 编辑文本块 -->
        </div>

        <!-- start 编辑小部件块 -->
        <div class="edit-widgets-block">

          <!-- start 添加图片按钮 -->
          <button class="add-img-button mdui-btn mdui-ripple">
            <i class="mdui-icon material-icons">&#xe3f4;</i>
          <!-- end 添加图片按钮 -->
          </button>

          <!-- start 添加语音按钮 -->
          <button class="add-voice-button mdui-btn mdui-ripple">
            <i class="mdui-icon material-icons">&#xe31d;</i>
          <!-- start 添加语音按钮 -->
          </button>

          <!-- start 添加按钮 -->
          <button class="add-button mdui-btn mdui-ripple">
            <i class="mdui-icon material-icons">&#xe147;</i>
          <!-- end 添加按钮 -->
          </button>

           <!-- start 发送按钮 -->
           <button class="edit-send-button mdui-btn mdui-color-indigo mdui-ripple">
            <i class="mdui-icon material-icons">&#xe5d8;</i>
           <!-- end 发送按钮 -->
          </button>

        </div>
        <!-- end 编辑小部件块 -->

      </div>
      <!-- end 编辑区域 EditArea -->

      <!--end 聊天区容器-->
    </div>

<!--end 顶层容器-->
</div>

</template>

<style>
/* 竖屏模式的侧边栏 */
#chatpage-sidebar {
  display: none;
}

/* 横屏模式的侧边栏 */
@media (orientation: landscape) {
  #chatpage-sidebar {
    display: block;
  }
}

/* 编辑区域 */
.edit-area{
  position: absolute;
  bottom: 0;
  right: 0;
  backdrop-filter: blur(10px); /* 调整模糊程度 */
  /*background-color: rgba(0, 255, 255, 0.5); /* 调整背景颜色和透明度 */
}
</style>

<script>
/* eslint-disable */ 
import SideBarPage from '@/pages/SideBarPage'
import MessageBubbleMe from '@/components/MessageBubbleMe'
import MessageBubbleShe from '@/components/MessageBubbleShe'
import mdui from 'mdui';
//import { openDB } from 'idb';

export default {
    name: 'MainPage',
    components: {
    SideBarPage,
    MessageBubbleShe,
    MessageBubbleMe
  }
}
</script>

SideBarPage.vue

<template>
    <!-- start 侧边栏容器 SideBarPage -->
    <div class="mdui-row">

    <!-- start SideBarSettings 区域 -->
    <div class="mdui-col-xs-12 sidebar-settings-area">

       <h2>侧边栏设置</h2>

       <!-- start 清除对话历史按钮 -->
       <button class="mdui-btn mdui-color-indigo mdui-col-xs-5 mdui-ripple" @click="clearChatHistory">

           <i class="mdui-icon material-icons">&#xe92b;</i>
           <span class="mdui-text-truncate" style="max-width: 5px;">清除历史</span>

       <!-- end 清除对话历史按钮 -->
       </button>

       <!-- start 设置对话API按钮 -->
       <button class="mdui-btn mdui-color-indigo mdui-col-xs-5 mdui-ripple" @click="gotoChatApiSettings">

           <i class="mdui-icon material-icons">&#xe560;</i>
           <span>设置对话API</span>

       <!-- end 设置对话API按钮 -->
       </button>

       <!-- start 进入设置页面按钮 -->
       <button class="mdui-btn mdui-color-indigo mdui-col-xs-5 mdui-ripple" @click="gotoSettingsPage">

           <i class="mdui-icon material-icons">&#xe8b9;</i>
           <span>设置</span>

       <!-- end 进入设置页面按钮 -->
       </button>

    <!-- end SideBarSettings 区域 -->
    </div>

    <!-- start 分割线 -->
    <div class="mdui-divider">
    <!-- end 分割线 -->
    </div>

    <!-- start Plugins 区域 -->
       <div class="plugins-area mdui-col-xs-12">

        <h2>插件</h2>

           <!-- start MyMusicPlugin按钮 -->
           <button class="mdui-btn mdui-color-indigo mdui-col-xs-5 mdui-ripple" @click="toggleMyMusicPlugin">

               <i class="mdui-icon material-icons">&#xe030;</i>
               <span>我的音乐</span>

           <!-- end MyMusicPlugin按钮 -->
           </button>

       <!-- end Plugins 区域 -->
       </div>

    <!-- end 侧边栏容器 -->
    </div>

    </template>

    <!-- Add "scoped" attribute to limit CSS to this component only -->
    <style scoped>
    button{
        margin:3px;
    }
    </style>

<script>
/* eslint-disable */
    export default {  
       name: 'SideBarPage',
       methods: {  
           clearChatHistory() {  
               console.log('ClearChatHistory');
           },
           gotoChatApiSettings() {  
               console.log('gotoChatApiSettings');
           },
           gotoSettingsPage() {  
               console.log('gotoSettingsPage');
           },
           toggleMyMusicPlugin() {  
               console.log('toggleMyMusicPlugin');
           }
       }
    }
</script>

index.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <title>晓晓学习助手</title>
  </head>

  <style>
    #main-background {
      background-color: #c7edcc; /* 豆沙绿 */
      background-image: url("./static/imgs/background-girl1.jpg");
      background-size: cover;
      background-repeat: no-repeat;
      background-position: center;
      width:100vw;
      height:100vh;
    }
    
    /* 横屏时应用不同的背景图像 */
    @media screen and (orientation: landscape) {
      #main-background {
        background-image: url("./static/imgs/background-girl2.jpg");
      }
    }
  </style>

  <body  id="main-background">
    <!--开始 MDUI 布局容器-->
    <div class="mdui-container-fluid">

    <!--开始 Vue.js自动插入内容-->
    <div id="app"></div>
    <!-- built files will be auto injected -->
    <!--对应template中 id='app' 的内容-->
    </div>
    <!--结束 Vue.js自动插入内容-->

  </div>
  <!--结束 MDUI 布局容器-->

  </body>

</html>

MessageBubbleShe.vue

<template>

<!-- start 她的消息气泡 MessageBubble-She -->
<div class="message-bubble message-bubble-she">

<!--start 她的消息文本 -->
<div class="message-text">

  你好,我是你的 AI 朋友晓晓!希望我能帮到你。

<!--end 她的消息文本 -->
</div>

<!-- start 她的消息小部件 -->
<div class="message-widgets">

  <!-- start 消息点赞按钮 -->
  <button class="message-like-button mdui-btn">
  <i class="mdui-icon material-icons">&#xe8dc;</i>
  <!-- end 消息点赞按钮-->
  </button>

  <!-- start 消息不喜欢按钮 -->
  <button class="message-unlike-button mdui-btn">
  <i class="mdui-icon material-icons">&#xe8db;</i>
  <!-- end 消息不喜欢按钮 -->
  </button>

  <!-- start 消息复制按钮 -->
  <button class="message-unlike-button mdui-btn">
  <i class="mdui-icon material-icons">&#xe14d;</i>
  <!-- end 消息复制按钮 -->
  </button>

  <!-- 消息时间戳 -->
  <b class="message-timestamp mdui-chip-title">2023-8-20 23:34:44</b>

  <!-- start 消息状态 -->
  <i class="mdui-icon material-icons message-status">&#xe86c;</i>
  <!-- <i class="mdui-icon material-icons">&#xe5cd;</i> -->
  <!-- end 消息状态 -->

<!--end 她的消息小部件-->
</div>

<!-- end 她的消息气泡 MessageBubble-She -->
</div>

</template>

<style>
/* 她的消息气泡 */
.message-bubble-she {
  text-align: left;
  padding-right: 10%;
  width:90%;
  border-radius: 10px;
  background-color: pink;
}

/* 气泡控件区 */
.message-widgets{
    margin-right:0;
}

/* 气泡 */
.message-bubble{
  /* 设置垂直间距为10像素 */
  margin-bottom: 5vh;
  margin-top: 5vh;
}

/* 气泡消息文本 */
.message-text{
    padding: 5px;
}
</style>

<script>
/* eslint-disable */
export default {
    name: 'MessageBubbleShe'
}
</script>

MessageBubbleMe.vue

<template>

<!-- start 我的消息气泡 MessageBubble-Me -->
<div class="message-bubble message-bubble-me">

<!-- start 我的消息文本 -->
<div class="message-text">

  你好!

<!-- end 我的消息文本 -->
</div>

<!-- start 我的消息小部件 -->
<div class="message-widgets">

  <!-- start 消息点赞按钮 -->
  <button class="message-like-button mdui-btn">
  <i class="mdui-icon material-icons">&#xe8dc;</i>
  <!-- end 消息点赞按钮 -->
  </button>

  <!-- start 消息不喜欢按钮 -->
  <button class="message-unlike-button mdui-btn">
  <i class="mdui-icon material-icons">&#xe8db;</i>
  <!-- end 消息不喜欢按钮 -->
  </button>

  <!-- start 消息复制按钮 -->
  <button class="message-unlike-button mdui-btn">
  <i class="mdui-icon material-icons">&#xe14d;</i>
  <!-- end 消息复制按钮 -->
  </button>

  <!-- 消息时间戳 -->
  <b class="message-timestamp mdui-chip-title">2023-8-20 23:33:33</b>

  <!-- start 消息状态 -->
  <i class="mdui-icon material-icons message-status">&#xe86c;</i>
  <!-- <i class="mdui-icon material-icons">&#xe5cd;</i> -->
  <!-- end 消息状态 -->

<!--end 我的消息小部件-->
</div>

<!-- end 我的消息气泡 MessageBubble-Me -->
</div>

</template>

<style>
/* 我的消息气泡 */
.message-bubble-me {
  text-align: right;
  padding-left: 10%;
  width:90%;
  border-radius: 10px;
  background-color: lightblue;
}

/* 气泡控件区 */
.message-widgets{
    margin-right:0;
}

/* 气泡 */
.message-bubble{
  /* 设置垂直间距为10像素 */
  margin-bottom: 5vh;
  margin-top: 5vh;
}

/* 气泡消息文本 */
.message-text{
    padding: 5px;
}
</style>

<script>
/* eslint-disable */ 
export default {
    name: 'MessageBubbleMe'
}
</script>

封装为docker镜像

docker pull node:lts-hydrogen
docker run -it --network=bridge -v $PWD:/srv -p 8666:8666 node:lts-hydrogen bash
export https_proxy=http://192.168.31.94:7890 http_proxy=http://192.168.31.94:7890 all_proxy=socks5://192.168.31.94:7890
cp -r /srv/learn-sys /home/node
cd /home/node/learn-sys
npm install
npm run dev
docker commit da5f9f8f1db0 qsbye/runtime-env2:v0.2
docker push qsbye/runtime-env2:v0.2

编译&运行

docker run -it -p 8666:8666 qsbye/runtime-env2:v0.2 bash -c "cd /home/node/learn-sys && npm run dev"

访问:[127.0.0.1:8666]

效果

有气泡 有侧边栏
posted @ 2023-08-21 04:11  qsBye  阅读(42)  评论(0编辑  收藏  举报