首页

VUE&Element简单介绍。

前端达人

目录

一、VUE

1、基本介绍

2、Vue 指令

3、生命周期 

二、Element

1、基本介绍

2、Element 布局


一、VUE

1、基本介绍

▶ 概述

  Vue 是一套前端框架,免除原生JavaScript中的DOM操作,简化书写。

  我们之前也学习过后端的框架 `Mybatis` ,`Mybatis` 是用来简化 `jdbc` 代码编写的;而 `VUE` 是前端的框架,是用来简化 `JavaScript` 代码编写的。前面的综合性案例,里面进行了大量的DOM操作,如下

  使用 `VUE` 后,这部分代码我们就不需要再写了。那么 `VUE` 是如何简化 DOM 书写呢?基于MVVM(Model-View-ViewModel)思想,实现数据的双向绑定,将编程的关注点放在数据上。之前我们是将关注点放在了 DOM 操作上;而要了解 `MVVM` 思想,必须先了解 `MVC` 思想,如下图就是 `MVC` 思想图解

其中的C 就是咱们 js 代码,M 就是数据,而 V 是页面上展示的内容,如下图:

 `MVC` 思想是没法进行双向绑定的。双向绑定是指当数据模型数据发生变化时,页面展示的会随之发生变化,而如果表单数据发生变化,绑定的模型数据也随之发生变化。接下来了解`MVVM` 思想,如下图是三个组件图解:

 图中的 `Model` 就是我们的数据,`View` 是视图,也就是页面标签,用户可以通过浏览器看到的内容;`Model` 和 `View` 是通过 `ViewModel` 对象进行双向绑定的,而 `ViewModel` 对象是 `Vue` 提供的。双向绑定的效果:下图是提前准备的代码写出来的,输入框绑定了 `username` 模型数据,而在页面上也使用 `{{}}` 绑定了 `username` 模型数据

通过浏览器打开该页面可以看到如下页面

当我们在输入框中输入内容,而输入框后面随之实时的展示我们输入的内容,这就是双向绑定的效果。

▶ 快速入门

Vue 使用起来是比较简单的,总共分为如下三步:

1. 新建 HTML 页面,引入 Vue.js文件

<script src="js/vue.js"></scrip>

 2. 在JS代码区域,创建Vue核心对象,进行数据绑定

 
    
  1. new Vue({
  2.        el: "#app",
  3.        data() {
  4.            return {
  5.                username: ""
  6.            }
  7.        }
  8.    });

   创建 Vue 对象时,需要传递一个 js 对象,而该对象中需要如下属性:

   ●  `el` : 用来指定哪个地方的标签受 Vue 管理。 该属性取值 `#app` 中的 `app` 需要是受管理的标签的id属性值
   ● `data` :用来定义数据模型
   ● `methods` :用来定义函数。这个我们在后面就会用到

3. 编写视图

 
    
  1. <div id="app">
  2.        <input name="username" v-model="username" >
  3.        {{username}}
  4.    </div>

   `{{}}` 是 Vue 中定义的 `插值表达式` ,在里面写数据模型,到时候会将该模型的数据值展示在这个位置。

▷ 整体代码如下:

 
    
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4.     <meta charset="UTF-8">
  5.     <title>Title</title>
  6. </head>
  7. <body>
  8. <div id="app">
  9.     <input v-model="username">
  10.     <!--插值表达式-->
  11.     {{username}}
  12. </div>
  13. <script src="js/vue.js"></script>
  14. <script>
  15.     //1. 创建Vue核心对象
  16.     new Vue({
  17.         el:"#app",
  18.         data(){  // data() 是 ECMAScript 6 版本的新的写法
  19.             return {
  20.                 username:""
  21.             }
  22.         }
  23.         /*data: function () {
  24.             return {
  25.                 username:""
  26.             }
  27.         }*/
  28.     });
  29. </script>
  30. </body>
  31. </html>

2、Vue 指令

指令:HTML 标签上带有 v- 前缀的特殊属性,不同指令具有不同含义。例如:v-if,v-for…

▷ v-bind & v-model 指令

▷ v-bind

  该指令可以给标签原有属性绑定模型数据。这样模型数据发生变化,标签属性值也随之发生变化,例如:

<a v-bind:href="url">百度一下</a>

  上面的 `v-bind:"`  可以简化写成 `:`  ,如下:

 
    
  1. <!--
  2.       v-bind 可以省略
  3.   -->
  4.   <a :href="url">百度一下</a>

▷ v-model

  该指令可以给表单项标签绑定模型数据。这样就能实现双向绑定效果。例如:

<input name="username" v-model="username">

 ▷ 代码演示:

 
    
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4.     <meta charset="UTF-8">
  5.     <title>Title</title>
  6. </head>
  7. <body>
  8. <div id="app">
  9.     <a v-bind:href="url">点击一下</a>
  10.     <a :href="url">点击一下</a>
  11.     <input v-model="url">
  12. </div>
  13. <script src="js/vue.js"></script>
  14. <script>
  15.     //1. 创建Vue核心对象
  16.     new Vue({
  17.         el:"#app",
  18.         data(){
  19.             return {
  20.                 username:"",
  21.                 url:"https://www.baidu.com"
  22.             }
  23.         }
  24.     });
  25. </script>
  26. </body>
  27. </html>

  通过浏览器打开上面页面,并且使用检查查看超链接的路径,该路径会根据输入框输入的路径变化而变化,这是因为超链接和输入框绑定的是同一个模型数据

▶ v-on 指令

我们在页面定义一个按钮,并给该按钮使用 `v-on` 指令绑定单击事件,html代码如下:

<input type="button" value="一个按钮" v-on:click="show()">

而使用 `v-on` 时还可以使用简化的写法,将 `v-on:` 替换成 `@`,html代码如下

<input type="button" value="一个按钮" @click="show()">

上面代码绑定的 `show()` 需要在 Vue 对象中的 `methods` 属性中定义出来

 
    
  1. new Vue({
  2.     el: "#app",
  3.     methods: {
  4.         show(){
  5.             alert("我被点了");
  6.         }
  7.     }
  8. });

注意:`v-on:` 后面的事件名称是之前原生事件属性名去掉on。
例如:
 ● 单击事件 : 事件属性名是 onclick,而在vue中使用是 `v-on:click`
 ● 失去焦点事件:事件属性名是 onblur,而在vue中使用时 `v-on:blur`

▷ 整体页面代码如下:

 
    
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4.     <meta charset="UTF-8">
  5.     <title>Title</title>
  6. </head>
  7. <body>
  8. <div id="app">
  9.     <input type="button" value="一个按钮" v-on:click="show()"><br>
  10.     <input type="button" value="一个按钮" @click="show()">
  11. </div>
  12. <script src="js/vue.js"></script>
  13. <script>
  14.     //1. 创建Vue核心对象
  15.     new Vue({
  16.         el:"#app",
  17.         data(){
  18.             return {
  19.                 username:"",
  20.             }
  21.         },
  22.         methods:{
  23.             show(){
  24.                 alert("我被点了...");
  25.             }
  26.         }
  27.     });
  28. </script>
  29. </body>
  30. </html>

▶ 条件判断指令

接下来通过代码演示一下。在 Vue中定义一个 `count` 的数据模型,如下

 
    
  1. //1. 创建Vue核心对象
  2. new Vue({
  3.     el:"#app",
  4.     data(){
  5.         return {
  6.             count:3
  7.         }
  8.     }
  9. });

  现在要实现,当 `count` 模型的数据是3时,在页面上展示 `div1` 内容;当 `count` 模型的数据是4时,在页面上展示 `div2` 内容;`count` 模型数据是其他值时,在页面上展示 `div3`。这里为了动态改变模型数据 `count` 的值,再定义一个输入框绑定 `count` 模型数据。html 代码如下:

 
    
  1. <div id="app">
  2.     <div v-if="count == 3">div1</div>
  3.     <div v-else-if="count == 4">div2</div>
  4.     <div v-else>div3</div>
  5.     <hr>
  6.     <input v-model="count">
  7. </div>

▷ 整体页面代码如下:

 
    
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4.     <meta charset="UTF-8">
  5.     <title>Title</title>
  6. </head>
  7. <body>
  8. <div id="app">
  9.     <div v-if="count == 3">div1</div>
  10.     <div v-else-if="count == 4">div2</div>
  11.     <div v-else>div3</div>
  12.     <hr>
  13.     <input v-model="count">
  14. </div>
  15. <script src="js/vue.js"></script>
  16. <script>
  17.     //1. 创建Vue核心对象
  18.     new Vue({
  19.         el:"#app",
  20.         data(){
  21.             return {
  22.                 count:3
  23.             }
  24.         }
  25.     });
  26. </script>
  27. </body>
  28. </html>

通过浏览器打开页面并在输入框输入不同的值,效果如下

然后我们在看看 `v-show` 指令的效果,如果模型数据 `count ` 的值是3时,展示 `div v-show` 内容,否则不展示,html页面代码如下

 
    
  1. <div v-show="count == 3">div v-show</div>
  2. <br>
  3. <input v-model="count">

浏览器打开效果如下:

通过上面的演示,发现 `v-show` 和 `v-if` 效果一样,那它们到底有什么区别呢?我们根据浏览器的检查功能查看源代码:

通过上图可以看出 `v-show` 不展示的原理是给对应的标签添加 `display` css属性,并将该属性值设置为 `none` ,这样就达到了隐藏的效果。而 `v-if` 指令是条件不满足时根本就不会渲染。

▶ v-for 指令

这个指令看到名字就知道是用来遍历的,该指令使用的格式如下:

 
    
  1. <标签 v-for="变量名 in 集合模型数据">
  2.     {{变量名}}
  3. </标签>

注意:需要循环那个标签,`v-for` 指令就写在那个标签上。

如果在页面需要使用到集合模型数据的索引,就需要使用如下格式:

 
    
  1. <标签 v-for="(变量名,索引变量) in 集合模型数据">
  2.     <!--索引变量是从0开始,所以要表示序号的话,需要手动的加1-->
  3.    {{索引变量 + 1}} {{变量名}}
  4. </标签>

▷ 代码演示:

 
    
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4.     <meta charset="UTF-8">
  5.     <title>Title</title>
  6. </head>
  7. <body>
  8. <div id="app">
  9.     <div v-for="addr in addrs">
  10.         {{addr}} <br>
  11.     </div>
  12.     <hr>
  13.     <div v-for="(addr,i) in addrs">
  14.         {{i+1}}--{{addr}} <br>
  15.     </div>
  16. </div>
  17. <script src="js/vue.js"></script>
  18. <script>
  19.     //1. 创建Vue核心对象
  20.     new Vue({
  21.         el:"#app",
  22.         data(){
  23.             return {
  24.                 addrs:["北京","上海","西安"]
  25.             }
  26.         }
  27.     });
  28. </script>
  29. </body>
  30. </html>

通过浏览器打开效果如下

3、生命周期 

生命周期的八个阶段:每触发一个生命周期事件,会自动执行一个生命周期方法,这些生命周期方法也被称为钩子方法。

下图是 Vue 官网提供的从创建 Vue 到效果 Vue 对象的整个过程及各个阶段对应的钩子函数

看到上面的图,大家无需过多的关注这张图。这些钩子方法我们只关注 `mounted` 就行了。

`mounted`:挂载完成,Vue初始化成功,HTML页面渲染成功。而以后我们会在该方法中发送异步请求,加载数据。

二、Element

 1、基本介绍

▶ 概述

 Element:是饿了么公司前端开发团队提供的一套基于 Vue 的网站组件库,用于快速构建网页。

Element 提供了很多组件(组成网页的部件)供我们使用。例如 超链接、按钮、图片、表格等等~

如下图左边的是我们编写页面看到的按钮,上图右边的是 Element 提供的页面效果,效果一目了然。

我们学习 Element 其实就是学习怎么从官网拷贝组件到我们自己的页面并进行修改,官网网址是:元素 - 全球最受欢迎的 Vue UI 框架 (eleme.cn)

进入官网能看到如下页面

 接下来直接点击 `组件` ,页面如下

2、Element 布局

Element 提供了两种布局方式,分别是:

 ● Layout 布局
 ● Container 布局容器

▷ Layout 局部

通过基础的 24 分栏,迅速简便地创建布局。也就是默认将一行分为 24 栏,根据页面要求给每一列设置所占的栏数。

在左菜单栏找到 `Layout 布局` ,然后找到自己喜欢的按钮样式,点击 `显示代码` ,在下面就会展示出对应的代码,显示出的代码中有样式,有html标签。将样式拷贝我们自己页面的 `head` 标签内,将html标签拷贝到  `<div id="app"></div>` 标签内。

▷ 整体页面代码如下:

 
    
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4.     <meta charset="UTF-8">
  5.     <title>Title</title>
  6.     <style>
  7.         .el-row {
  8.             margin-bottom: 20px;
  9.         }
  10.         .el-col {
  11.             border-radius: 4px;
  12.         }
  13.         .bg-purple-dark {
  14.             background: #99a9bf;
  15.         }
  16.         .bg-purple {
  17.             background: #d3dce6;
  18.         }
  19.         .bg-purple-light {
  20.             background: #e5e9f2;
  21.         }
  22.         .grid-content {
  23.             border-radius: 4px;
  24.             min-height: 36px;
  25.         }
  26.         .row-bg {
  27.             padding: 10px 0;
  28.             background-color: #f9fafc;
  29.         }
  30.     </style>
  31. </head>
  32. <body>
  33. <div id="app">
  34.     <el-row>
  35.         <el-col :span="24"><div class="grid-content bg-purple-dark"></div></el-col>
  36.     </el-row>
  37.     <el-row>
  38.         <el-col :span="12"><div class="grid-content bg-purple"></div></el-col>
  39.         <el-col :span="12"><div class="grid-content bg-purple-light"></div></el-col>
  40.     </el-row>
  41.     <el-row>
  42.         <el-col :span="8"><div class="grid-content bg-purple"></div></el-col>
  43.         <el-col :span="8"><div class="grid-content bg-purple-light"></div></el-col>
  44.         <el-col :span="8"><div class="grid-content bg-purple"></div></el-col>
  45.     </el-row>
  46.     <el-row>
  47.         <el-col :span="6"><div class="grid-content bg-purple"></div></el-col>
  48.         <el-col :span="6"><div class="grid-content bg-purple-light"></div></el-col>
  49.         <el-col :span="6"><div class="grid-content bg-purple"></div></el-col>
  50.         <el-col :span="6"><div class="grid-content bg-purple-light"></div></el-col>
  51.     </el-row>
  52.     <el-row>
  53.         <el-col :span="4"><div class="grid-content bg-purple"></div></el-col>
  54.         <el-col :span="4"><div class="grid-content bg-purple-light"></div></el-col>
  55.         <el-col :span="4"><div class="grid-content bg-purple"></div></el-col>
  56.         <el-col :span="4"><div class="grid-content bg-purple-light"></div></el-col>
  57.         <el-col :span="4"><div class="grid-content bg-purple"></div></el-col>
  58.         <el-col :span="4"><div class="grid-content bg-purple-light"></div></el-col>
  59.     </el-row>
  60. </div>
  61. <script src="js/vue.js"></script>
  62. <script src="element-ui/lib/index.js"></script>
  63. <link rel="stylesheet" href="element-ui/lib/theme-chalk/index.css">
  64. <script>
  65.     new Vue({
  66.         el:"#app"
  67.     })
  68. </script>
  69. </body>
  70. </html>

现在需要添加一行,要求该行显示8个格子,通过计算每个格子占 3 栏,具体的html 代码如下

 
    
  1. <!--
  2. 添加一行,8个格子  24/8 = 3
  3. -->
  4. <el-row>
  5.     <el-col :span="3"><div class="grid-content bg-purple"></div></el-col>
  6.     <el-col :span="3"><div class="grid-content bg-purple-light"></div></el-col>
  7.     <el-col :span="3"><div class="grid-content bg-purple"></div></el-col>
  8.     <el-col :span="3"><div class="grid-content bg-purple-light"></div></el-col>
  9.     <el-col :span="3"><div class="grid-content bg-purple"></div></el-col>
  10.     <el-col :span="3"><div class="grid-content bg-purple-light"></div></el-col>
  11.     <el-col :span="3"><div class="grid-content bg-purple"></div></el-col>
  12.     <el-col :span="3"><div class="grid-content bg-purple-light"></div></el-col>
  13. </el-row>

▶ Container 布局容器

用于布局的容器组件,方便快速搭建页面的基本结构。如下图就是布局容器效果。

如下图是官网提供的 Container 布局容器实例:

该效果代码中包含了样式、页面标签、模型数据。将里面的样式 `<style>` 拷贝到我们自己页面的 `head` 标签中;将html标签拷贝到 `<div id="app"></div>` 标签中,再将数据模型拷贝到 `vue` 对象的 `data()` 中。

▷ 整体页面代码如下:

 
    
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4.     <meta charset="UTF-8">
  5.     <title>Title</title>
  6.     <style>
  7.         .el-header {
  8.             background-color: #B3C0D1;
  9.             color: #333;
  10.             line-height: 60px;
  11.         }
  12.         .el-aside {
  13.             color: #333;
  14.         }
  15.     </style>
  16. </head>
  17. <body>
  18. <div id="app">
  19.     <el-container style="height: 500px; border: 1px solid #eee">
  20.         <el-aside width="200px" style="background-color: rgb(238, 241, 246)">
  21.             <el-menu :default-openeds="['1', '3']">
  22.                 <el-submenu index="1">
  23.                     <template slot="title"><i class="el-icon-message"></i>导航一</template>
  24.                     <el-menu-item-group>
  25.                         <template slot="title">分组一</template>
  26.                         <el-menu-item index="1-1">选项1</el-menu-item>
  27.                         <el-menu-item index="1-2">选项2</el-menu-item>
  28.                     </el-menu-item-group>
  29.                     <el-menu-item-group title="分组2">
  30.                         <el-menu-item index="1-3">选项3</el-menu-item>
  31.                     </el-menu-item-group>
  32.                     <el-submenu index="1-4">
  33.                         <template slot="title">选项4</template>
  34.                         <el-menu-item index="1-4-1">选项4-1</el-menu-item>
  35.                     </el-submenu>
  36.                 </el-submenu>
  37.                 <el-submenu index="2">
  38.                     <template slot="title"><i class="el-icon-menu"></i>导航二</template>
  39.                     <el-submenu index="2-1">
  40.                         <template slot="title">选项1</template>
  41.                         <el-menu-item index="2-1-1">选项1-1</el-menu-item>
  42.                     </el-submenu>
  43.                 </el-submenu>
  44.                 <el-submenu index="3">
  45.                     <template slot="title"><i class="el-icon-setting"></i>导航三</template>
  46.                     <el-menu-item-group>
  47.                         <template slot="title">分组一</template>
  48.                         <el-menu-item index="3-1">选项1</el-menu-item>
  49.                         <el-menu-item index="3-2">选项2</el-menu-item>
  50.                     </el-menu-item-group>
  51.                     <el-menu-item-group title="分组2">
  52.                         <el-menu-item index="3-3">选项3</el-menu-item>
  53.                     </el-menu-item-group>
  54.                     <el-submenu index="3-4">
  55.                         <template slot="title">选项4</template>
  56.                         <el-menu-item index="3-4-1">选项4-1</el-menu-item>
  57.                     </el-submenu>
  58.                 </el-submenu>
  59.             </el-menu>
  60.         </el-aside>
  61.         <el-container>
  62.             <el-header style="text-align: right; font-size: 12px">
  63.                 <el-dropdown>
  64.                     <i class="el-icon-setting" style="margin-right: 15px"></i>
  65.                     <el-dropdown-menu slot="dropdown">
  66.                         <el-dropdown-item>查看</el-dropdown-item>
  67.                         <el-dropdown-item>新增</el-dropdown-item>
  68.                         <el-dropdown-item>删除</el-dropdown-item>
  69.                     </el-dropdown-menu>
  70.                 </el-dropdown>
  71.                 <span>王小虎</span>
  72.             </el-header>
  73.             <el-main>
  74.                 <el-table :data="tableData">
  75.                     <el-table-column prop="date" label="日期" width="140">
  76.                     </el-table-column>
  77.                     <el-table-column prop="name" label="姓名" width="120">
  78.                     </el-table-column>
  79.                     <el-table-column prop="address" label="地址">
  80.                     </el-table-column>
  81.                 </el-table>
  82.             </el-main>
  83.         </el-container>
  84.     </el-container>
  85. </div>
  86. <script src="js/vue.js"></script>
  87. <script src="element-ui/lib/index.js"></script>
  88. <link rel="stylesheet" href="element-ui/lib/theme-chalk/index.css">
  89. <script>
  90.     new Vue({
  91.         el:"#app",
  92.         data() {
  93.             const item = {
  94.                 date: '2016-05-02',
  95.                 name: '王小虎',
  96.                 address: '上海市普陀区金沙江路 1518 弄'
  97.             };
  98.             return {
  99.                 tableData: Array(20).fill(item)
  100.             }
  101.         }
  102.     })
  103. </script>
  104. </body>
  105. </html>

▶ 完成分页条展示

在 Element 官网找到 `Pagination 分页` ,在页面主体部分找到我们需要的效果,如下






转自:csdn


蓝蓝设计建立了UI设计分享群,每天会分享国内外的一些优秀设计,如果有兴趣的话,可以进入一起成长学习,请加蓝小助,微信号:ben_lanlan,报下信息,蓝小助会请您入群。欢迎您加入噢~~希望得到建议咨询、商务合作,也请与我们联系01063334945。


分享此文一切功德,皆悉回向给文章原作者及众读者.
免责声明:蓝蓝设计尊重原作者,文章的版权归原作者。如涉及版权问题,请及时与我们取得联系,我们立即更正或删除。


蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务UI设计公司、界面设计公司、UI设计服务公司、数据可视化设计公司、UI交互设计公司、高端网站设计公司、UI咨询、用户体验公司、软件界面设计公司

缺陷修改实践——replace函数的运用|思考?

前端达人

介绍

大家好,我是清风。今天给大家分享一个项目中遇到问题解决问题的案例,编程其实就是一个思考的过程,缺少思考就没有灵魂,遇到问题先静下心去思考,想到方法后再去实践。我们要学会灵活变通去解决问题,掌握方法,这样才能举一反三,临危不乱,遇到所有问题都能很好地去解决。

事情是这样的,做的一个答题小程序,要求在后台编辑题目,编辑题目是用的textarea文本域,即输入的是文本内容,配置之后小程序里查询显示后台配置的题目列表。

在这里插入图片描述

当然在测试时后台去配置文本内容,小程序显示是没有问题的。因为配置的题目是纯文本,小程序里也是直接在text里显示的,没有问题。

后台配置题目

在这里插入图片描述

小程序显示题目
在这里插入图片描述

问题出现

问题往往只有在用的时候才会发现,用户或管理员的各种操作才能显现出各种问题。现在小程序里已经不能正常显示了,有些显示的是html格式富文本格式,有些不显示。显然和需求大相径庭,已经出现问题了。

问题分析

在这里插入图片描述

如上图,在用的时候因为是从word文档里直接复制过去的题目(事先在word里整理好了题目,由于各部门工作对接,先是在word文档进行审核),直接复制会把富文本内容也携带过去,携带过去的当然也有style样式,小程序里不显示的原因是富文本的字体颜色是黑色字体,和小程序面背景都是黑色,导致看不到文字。打开控制台调试,问题确实是这么出现的。

在这里插入图片描述

word文档编辑的题目会出现不同的富文本的样式格式,这都会导致小程序的不正常显示。

在这里插入图片描述

富文本的文字颜色是黑色,这导致的小程序页里题目的不显示。

解决方法

既然后台有可能出现富文本,我们直接把小程序题目的渲染方式换成富文本渲染,这样就算是纯文本也可以显示的。而第二个问题,由于小程序页面背景颜色是黑色,所以题目的字体颜色不能是黑色,我们做一个查找替换,把style样式里的字体样式替换掉就可以了。

优化

样式可能是各种各样的,通过查找style样式里的字体样式考虑的匹配太多了,比如说color属性值可以是rgb形式,也可是rgba形式,也可能是#号颜色值形式,还有可能是英文形式颜色,所以不可取。我们换一种思路,直接把style属性替换掉,即查找到style,换成一个无效的属性名。案例中我们替换成了cc是一个无效的属性,不会触发节点的查找和计算。

replace函数

我们用到replace函数replace() 方法用于在字符串中用一些字符替换另一些字符,或替换一个与正则表达式匹配的子串。

参数

  1. regexp/substr,必需。规定子字符串或要替换的模式的 RegExp 对象。
  2. replacement,必需。一个字符串值。规定了替换文本或生成替换文本的函数。

请注意,regexp/substr 是一个字符串,则将它作为要检索的直接量文本模式,而不是首先被转换为 RegExp对象,返回值是一个新的字符串,是用 replacement 替换了 regexp 的第一次匹配或所有匹配之后得到的。

实现

replace() 方法用于在字符串中用一些字符替换另一些字符,或替换一个与正则表达式匹配的子串。

 that.setData({
          _list: res.data
        })
        let data = that.data._list
        data.forEach((element, index) => {
          var stemContent = '_list[' + index + '].stemContent'
          that.setData({
            [stemContent]: element.stemContent.replace(/style/g, 'c')
          })
          element.choiceTopicVos.forEach((item, i) => {
            var listCheck = '_list[' + index + '].choiceTopicVos[' + i + '].optionDes';
            that.setData({
              [listCheck]:  item.optionDes.replace(/style/g, 'c')

            })
          })
        })  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

用到的replace函数,进行了字符串的查找替换,查找到style属性,把它替换到了无效的属性c,没有了样式属性,从而达到了去除内联样式的效果,经过调试,完美解决问题。

在这里插入图片描述

总结

在这里插入图片描述

这是一个小问题,我为什么要拿出来说呢?抛去开发的测试流程不说,我认为它能引发一些思考。写代码的过程必须是一个思考的过程,怎么样更好地去实现效果,怎么样更简单有效地解决问题,怎么样优化,要去考虑一个大的方面。善于发现问题,解决问题,并不是说用了什么高级语言就鄙弃了思考,机器语言是相通的,开发中各种各样地应用才是魅力所在。编程是一门是艺术,最重要的是你怎样去巧妙地运用,就像解一道数学题,精绝巧妙的解法会让人眼前一亮,增色太多。同样都做出来了,但是你做的就显得十分优雅!




转自 csdn

蓝蓝设计建立了UI设计分享群,每天会分享国内外的一些优秀设计,如果有兴趣的话,可以进入一起成长学习,请加蓝小助,微信号:ben_lanlan,报下信息,蓝小助会请您入群。欢迎您加入噢~~希望得到建议咨询、商务合作,也请与我们联系01063334945。


分享此文一切功德,皆悉回向给文章原作者及众读者.
免责声明:蓝蓝设计尊重原作者,文章的版权归原作者。如涉及版权问题,请及时与我们取得联系,我们立即更正或删除。

蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务UI设计公司、界面设计公司、UI设计服务公司、数据可视化设计公司、UI交互设计公司、高端网站设计公司、UI咨询、用户体验公司、软件界面设计公司

【Vue】webpack的基本使用

前端达人

webpack的学习目标

  1. 理解什么是前端工程化
    • 转变对前端开发的认知
  2. 了解webpack的基本用法
    • 为后面Vue和React课程的学习做技术储备
  3. 不强制要求大家能手动配置 webpack
    • 一定要知道webpack在项目中有什么作用
    • 清除webpack中的核心概念

前端工程化

小白眼中的前端开发 vs 实际的前端开发

  1. 小白眼中的前端开发
    • 会写HTML + CSS +JavaScript就会前端开发
    • 需要美化页面样式,就拽一个bootstrap过来
    • 需要操作DOM或发起Ajax,再拽一个jquery过来
    • 需要快速实现网页布局效果,就拽一个Layui过来
  2. 实际的前端开发
    • 模块化(js的模块化,css的模块化,资源的模块化)
    • 组件化(复用现有的UI结构,样式,行为)
    • 规范化(目录结构的划分,编码规范化,接口规范化,文档规范化,Git分支管理)
    • 自动化(自动化构建,自动部署,自动化测试)

什么是前端工程化

前端工程化指的是:在企业级的前端项目开发中,把前端开发所谓的工具,技术,流程,经验等进行规范化,标准化。
企业中的Vue项目和React项目,都是基于工程画的方式进行开发。

好处:前端开发自成体系,有一套标准的开发方案和流量。

前端工程化的解决方案

  1. 早期的前端工程化解决方案
    • grunt
    • gulp
  2. 目前主流的前端工程化解决方案
    • webpack
    • parcel

webpack的基本使用

什么是webpack

概念: webpack是前端项目工程化的具体解决方案。

主要功能:它提供了友好的前端模块化开发支持,以及代码压缩混淆,处理浏览器端JavaScript的兼容性性能优化等强大的功能。

好处:让程序员把工作的重心放到具体功能的实现上,提高了前端开发效率和项目的可维护性。

注意:目前Vue,React等前端项目,基本上都是基于webpack进行工程化开发的。

列表隔行变色项目

步骤

  1. 新建项目空白目录,并运行npm init -y命令,初始化包管理配置文件package.json
  2. 新建src源代码目录
  3. 新建src->index.html首页和src->index.js脚本文件
  4. 初始化首页基本的结构
  5. 运行npm install jquery -s命令,安装jQuery
  6. 通过ES6模块化的方式导入jQuery,实现列表隔行变色的效果
    在这里插入图片描述
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> ul>li{这是第$个li}*9 </body> </html>  
        
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

在这里插入图片描述

在这里插入图片描述
import和require导入模块的区别
1、require对应导出的方法是module.exports,
import对应的方法是export default/export

2、require 是CommonJs的语法
import 是 ES6 的语法标准。

3、require是运行运行时加载模块里的所有方法(动态加载),
import 是编译的时候调用(静态加载),不管在哪里引用都会提升到代码顶部。

4、require 是CommonJs的语法,引入的是的是整个模块里面的对象,
import 可以按需引入模块里面的对象

5、require 导出是值的拷贝,
import 导出的是值的引用
6. require是node.js带有的 CommonJS语法里的东西,可以在终端中运行
如果要在浏览器端运行 我们要使用import这个es6语法
js代码

//导入模块 // const $ = require('jquery') import $ from "jquery"; //定义jquery入口函数 $(function () { $('li:odd').css('background-Color', 'red') $('li:even').css('background-Color', 'pink') })  
        
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

将js文件导入index.html之后,发现没有效果,这时我们就需要webpack工具了,将语法进行重新编译,把es6语法转化为es5语法。

在项目中安装并配置webpack

npm i webpack@5.42.1 webpack-cli -D  
        
  • 1

生产依赖
在这里插入图片描述
创建webpack.config.js配置文件并写入
在这里插入图片描述

//使用node.js的导出语法向外导出一个webpack的配置对象 //导入模块并进行导出内容,这样写会比直接导出内容多一个记录信息的txt文件,当然我们也可以使用es6语法进行导入导出,大家可以私下去了解。 const { Module } = require("webpack"); Module.export = { mode: 'development' } //也可以直接导出内容 // module.export = { //     mode: 'development' // }  
        
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

在package.json配置文件中的script中写入声明

在这里插入图片描述

最后执行npm命令进行编译,有一个注意点就是node.js版本需要是17版本以下的不然会出错,当然应该有其他解决办法,但博主不会,只好退回版本
执行 npm run dev 这个命令,可以看到src里的index.js和jquery.js都被压缩了。
在这里插入图片描述
会生成一个编译后的文件夹
在这里插入图片描述
将main.js文件导入index.html.,不用导入index.js。
在这里插入图片描述
打开页面就可以成功显示了
在这里插入图片描述
mode的可选值
mode节点的可选值有两个,分别是:

  1. development
    • 开发环境
    • 不会对打包生成的文件进行代码压缩和性能优化
    • 打包速度快,适合在开发阶段使用。
  2. production
    • 生产环境
    • 会对打包生成的文件进行代码压缩和性能优化
    • 打包速度很慢,仅适合在项目发布阶段使用
      开发的时候使用development,打包速度快,上线的时候使用production,体积小。

webpack.config.js的作用

当我们使用npm run dev这个命令的时候,会执行package里的dev里的内容,在这里插入图片描述
dev里写的webpack,那么它就会执行weboack.config.js这个文件里的内容,根据里面的内容再进行打包。
在这里插入图片描述
webpack中的默认约定

大家可能有个疑问,就是打包的时候为什么会打包index.js这个文件,它是怎么寻找的路径等问题。

在webpack4和5的版本中,有如下的默认约定,找不到就会报错。

  1. 默认的打包入口文件为src -> index.js
  2. 默认的输出文件路径为dist -> main.js
    在这里插入图片描述

注意:可以在webpack.config.js中修改打包的默认约定。

自定义打包的入口和出口

在webpack.config.js配置文件中,通过entry节点指定打包的入口,通过output节点指定打包的出口文件夹和出口文件。

// 使用node.js的导出语法向外导出一个webpack的配置对象 const path = require("path"); module.exports = { mode: 'development', entry: path.join(__dirname, 'src/index.js'), //设置打包输出路径,以及输入文件名称 output: { //指定存放目录 path: path.join(__dirname, 'dist1'), filename: 'new.js' } }  
        
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

生成的文件就变了。
在这里插入图片描述

webpack中的插件

当我们修改js文件之后,需要重新打包才能有效,每修改一次都要重新打包一次,这就很麻烦我们可以 通过安装和配置第三方的插件,可以扩展webpack的能力,从而让webpack用起来更方便,常用的webpack插件有如下两个:

  1. webpack-dev-server
    • 类似于node.js阶段用到的nodemon工具。
    • 每当修改了源代码,webpack会自动进行项目的打包和构建。
  2. html-webpack-plugin
    • webpack中的html插件(“类似于一个模板引擎插件”),
    • 可以通过此插件自定制index.html页面的内容。

webpack-dev-server

安装webpack-dev-server

安装命令
npm install webpack-dev-server@3.11.2 -D  
        
  • 1
  • 2

配置webpack-dev-server

  1. 重新配置package.json中的script里的dev内容
    在这里插入图片描述
  2. 再次运行 npm run dev命令,重新进行项目打包
  3. 在浏览器中访问本地8080端口,查看自动打包效果。

注意:webpack-dev-server会启动一个实时打包的http服务器。
在这里插入图片描述
这样当我们每次修改index.js文件时,保存后就会自动打包,摁两次ctrl+c就可以终止运行。

这种打包实际上时虚拟打包,并不是每次保存打包之后将main.js进行了修改,当我们修改代码保存自动打包之后,我们发现页面UI并没有变化,那是因为main.js实际上没有修改,访问自动打包修改后的页面需要访问本地8080端口在这里插入图片描述
在这个http服务器内才能访问到修改后的内容,我们前面说了修改后的js并没有保存到main.js中,那它保存到哪里去了?它其实被保存到了根目录中,以内存的形式进行了保存。在这里插入图片描述
文件名跟你前面设置的打包文件名一样,虽然看不到这个文件但是可以进行访问,我们需要把页面引入链接从 new.js改成新生成的保存到内存中的new.js,完成这两个步骤就可以真正的实现自动打包并实时演示了。在这里插入图片描述

html-webpack-plugin

当我们开启了自动打包服务功能,访问服务器后,显示的是根目录,需要点击一下文件夹,才能显示页面文件index.html,我们只需要把页面文件copy一份儿到根目录,这样点开网页就能直接显示,这个webpack插件就可以实现相应的功能。

安装

npm install html-webpack-plugin@5.3.2 -D  
        
  • 1

使用代码

//导入相应模块 const HtmlPluginConfig = require('html-webpack-plugin') //实例化 const HtmlPlugin = new HtmlPluginConfig(); //实例化 const HtmlPlugin = new HtmlPluginConfig({ //被复制文件的路径 template: './src/index.html', //复制到哪 filename: './index.html' });  
        
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

最后再向外暴露对象

 //插件的数组,将来webpack在运行时,会加载并调用这些插件 plugins: [HtmlPlugin] //将实例化对象写入。  
        
  • 1
  • 2

执行 npm run dev命令,进行自动打包,然后进入本地8080端口网页,就可以直接看到页面了。
在这里插入图片描述
当你修改js之后也会实时更新。

注意点以及个人建议和理解
我们可以在scripts里设置两个属性,dev是用来开发实时浏览观看内容的,dev2是用来进行物理打包的(当你完成项目需要打包的时候)。
在这里插入图片描述
这里我需要说一下html-webpack-plugin这个插件,上面我们可以直接看到页面是因为这个插件复制了一份儿index.html到根目录所以可以直接访问。
这个插件里面 有个属性叫filename,就是你将文件复制到什么位置。
在这里插入图片描述
两个注意点

第一个就是它的值,属性值写的相对路径是根据你打包文件的位置为基准的,并不是webpack.config.js的文件位置,./就跟你的new.js文件在同一个文件夹里,…/就在new.js的上级文件夹里,所以当你打包的时候会发现除了new.js之外还有index.html

第二个就是输出方式,如果执行的是dev2,那么就跟new.js进行物理复制,如果执行的是dev那么就跟new.js一样,以内村存储的方式进行保存。

生成的html文件里会自动导入同时打包的js文件
在这里插入图片描述

devServer节点

在webpack.config.js配置文件中,可以通过devServer节点对webpack-dev-server插件进行更多配置。
其中有一些属性设置可以更方便我们进行开发。

 devServer: { open: true, //打包完成后默认打开浏览器 port: 8080,//修改端口号 host: '127.0.0.1' //修改主机地址 }  
        
  • 1
  • 2
  • 3
  • 4
  • 5
文章已被收录至官方知识档案







转自 csdn



蓝蓝设计建立了UI设计分享群,每天会分享国内外的一些优秀设计,如果有兴趣的话,可以进入一起成长学习,请加蓝小助,微信号:ben_lanlan,报下信息,蓝小助会请您入群。欢迎您加入噢~~希望得到建议咨询、商务合作,也请与我们联系01063334945。


分享此文一切功德,皆悉回向给文章原作者及众读者.
免责声明:蓝蓝设计尊重原作者,文章的版权归原作者。如涉及版权问题,请及时与我们取得联系,我们立即更正或删除。


蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务UI设计公司、界面设计公司、UI设计服务公司、数据可视化设计公司、UI交互设计公司、高端网站设计公司、UI咨询、用户体验公司、软件界面设计公司

网站都变成灰色了,它是怎么实现的?

前端达人

大家好,我是二哥呀。

想必大家都感受到了,很多网站、APP 在昨天都变灰了。

先来感受一下变灰后的效果。

这是 CSDN 的

这是 B站的

这种灰色的效果怎么实现的呢?如何做到图片、文字、按钮都变灰的效果呢?

方案 1,换一套灰色的 UI,那显然成本太大了,用脚指头想一想就知道不太可能。

方案 2,用魔法!

不好意思,还真被你猜中了!在网页端按下 F12,打开开发者模式,用元素选择器定位到 HTML 标签上,在「样式」的面板中往下翻,就可以看到这样一段代码。

我把它复制过来大家看一下。

-webkit-filter: grayscale(100%);
-moz-filter: grayscale(100%);
-ms-filter: grayscale(100%);
-o-filter: grayscale(100%);
filter: grayscale(100%);
filter: progid:DXImageTransform.Microsoft.BasicImage(grayscale=1);  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

打开二哥的网站《Java 程序员进阶之路》,定位到 HTML 标签,此时可以看到页面是正常的颜色。

然后把之前的代码添加到 HTML 上,然后就可以看到色系变成灰色了。

那这段代码是什么意思呢?

直接把 filter grayscale 复制到搜索引擎里看一下。

当参数为 0 的时候,颜色是正常的。

然后依次试一下 60%:

100%:

MDN 是怎么解释 grayscale() 函数呢?

The grayscale() CSS function converts the input image to grayscale. Its result is a .

大致的意思就是,grayscale 是一个 CSS 函数,可以把图像转成灰色,参数是个百分比,结果返回一个 filter 函数。

The CSS data type represents a graphical effect that can change the appearance of an input image. It is used in the filter and backdrop-filter properties.

filter 函数可以用来改变图像的显示效果,用于 CSS 的 filter 属性。 除了 grayscale 函数,可选项还有以下这些:

可以看到,目前的主流浏览器版本都支持 grayscale 函数,比如说 PC 端的 Chrome、edge、Firefox、Opera、Safari 等等,除了 IE。


没有什么使我停留——除了目的,纵然岸旁有玫瑰、有绿荫、有宁静的港湾,我是不系之舟。

转自 csdn

蓝蓝设计建立了UI设计分享群,每天会分享国内外的一些优秀设计,如果有兴趣的话,可以进入一起成长学习,请加蓝小助,微信号:ben_lanlan,报下信息,蓝小助会请您入群。欢迎您加入噢~~希望得到建议咨询、商务合作,也请与我们联系01063334945。


分享此文一切功德,皆悉回向给文章原作者及众读者.
免责声明:蓝蓝设计尊重原作者,文章的版权归原作者。如涉及版权问题,请及时与我们取得联系,我们立即更正或删除。


蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务UI设计公司、界面设计公司、UI设计服务公司、数据可视化设计公司、UI交互设计公司、高端网站设计公司、UI咨询、用户体验公司、软件界面设计公司



还不懂什么是SaaS?一篇最专业的扫盲科普文

纯纯

有了解和学习 B 端的同学必然都听说过 SaaS 这个词,这在 B 端行业是个非常重要的产品形式和分支。

虽然它重要,但新手对这东西的理解充满了让人遗憾的扭曲。比如常见的误解式提问,Saas 应该怎么设计?适用哪些设计风格?

……

所以我从最底层的技术层面,来解析 Saas 到底是什么,在未来你再也不用担心对这个词汇一知半解,无法正常参与业务讨论了。




讲解什么是 Saas,或者刚刚图例出现的 Paas、laas 是什么,首先要认识一个问题,一个需要联网的软件,是如何落地的,需要哪些前提条件。

通常,我们可以把一个普通的联网产品要正式上线并使用,需要满足 9 个层级的条件,我们简称 “9层塔”,分别是:

下面,我们根据每个大层级来解释一下,它们分别都是什么。



1.1 基础设施层

基础设施层是一切网络服务的根基,由现实世界的硬件组成,是所有技术、代码、数据的运行基础。


层1:网络(Networking)

即基础的互联网电信宽带服务,通过电信运营商在各地搭建联网用的设备,并使用线缆相互连接,满足数据的物理传输可能。

比如你想要在家上网冲浪(非移动上网),最基础的条件是就是购买和开通宽带服务,通过接入光纤的形式,实现从家中连接到互联网世界的可能。


层2:服务器(Serves)

服务器,本质上也是一台电脑。有了联网的条件,我们就要把网络接入到这台 “电脑” 上,让它来完成各种数据的处理和存储。

但不管它能做什么,要做什么,首先你得先有这台设备,不然后续的工作都无从谈起,所以服务器指的就是用来完成后续工作的电脑设备。


层3:存储(Storage)

存储就是硬盘,你想要运行的任何程序、代码,还是想要收集的数据,都需要容纳的地方,那就是硬盘空间。存储就是关联到服务器的硬盘,是数据存储的物理环境。

之所以硬盘被独立出出来,而没有把 CPU 内存这些拿出来,是因为数据的存储和安全(物理上)是网络服务的重中之重。CPU、内存、电源坏了,替换就可以,硬盘损坏导致数据的丢失是无论如何不可能接受的。

所以,工程师们开发了非常多特殊的技术来保障存储的稳定和安全。



1.2 技术应用层

技术应用层,就是具备了网络、服务器、硬盘以后,让这些基础设施充分发挥作用和能效的相关技术。


层4:虚拟化(Virtualization)

虚拟化是个比较抽象的概念,它是一种资源利用的技术,让服务器最大化的利用和分配自己的资源。

比如一台服务器,有8核心、8G内存、8G存储,如果卖个一个客户运行一个程序,那么很可能这个这个程序日常只使用一个核心的算力,1GB内存,1G不到的存储,剩下的算力资源不就浪费了嘛?

于是,虚拟技术就可以把这台服务器切割成 8 台 “虚拟机” 卖给 8 个这样的客户。让他们在这台设备上运行 8 个不同的程序,并根据它们各自使用的消耗灵活分配 CPU 和内存资源。

所以,今天如果你想要搭建一个网站,云服务商出售的 “虚拟主机”,就是在实体服务器主机上切割出来的一部分。这样客户省钱了,商家利润率也更高了!


层5:操作系统(OS)

每台电脑都有自己的操作系统,我们熟知的 Windows、Mac OS等等。如果硬件没有搭载操作系统,那它们就只是一堆工艺精密的废铁。

对于服务器来说也是,任何服务器想要正常运行,都必须搭载相关的服务器操作系统,有了基本的系统,我们才能创建程序,让服务器去运行我们想要的功能。

前面提到的虚拟机,就允许同一台服务器通过虚拟技术运行多个系统。


层6:中间件

中间件也是个比较复杂的技术概念,它是个独立系统软件服务程序,是软件的直接面向对象(而不是服务器),是一种支撑软件。

举个不太严谨的例子,我们常规的逻辑是一个程序对应一台服务器(或虚拟机),但真实情况往往是一个程序会关联好几个服务器和不同的系统,来完成不同的网络服务。正常情况下,你需要对每个服务器和系统进行适配。

而中间件的作用就是帮助你省掉这个麻烦的步骤,让你只需要对接唯一的翻译和话事人,他会帮你向不同的任务对象传达你的要求。


层7:程序环境(Rumtime)

程序环境,就是编译代码用的环境。我们常听说的 C 语言、C++、PHP、Java、.Net 等编程语言,都需要安装一个对应的运行环境。

许多热衷电脑游戏的同学一定很熟悉游戏第一次启动触发的 Java 安装界面,那就证明这个游戏中运用到了 Java 的代码,如果你没有 Java 的运行环境,那么它们就无法生效。



1.3 产品表现层


层8:应用(Application)

在这个系统下,应用程序指的不是你在自己电脑手机上安装的程序。而是安装在服务器上运行的程序,不管是后端程序还是前端程序。

它们需要使用某些特定的程序语言来编写,并运行在上面所说的对应环境中。我们所说的后端开发,通常就是开发服务器所运行的程序的程序员。


层9:数据(Data)

这个词放在这里可能有比较大的歧义,数据实际上就是使用这个程序所产生出来的数据,而不是单指数据库(数据库也是环境的一部分)。

比如你打开一个网站注册了账号,上传了头像,那么这些信息就是使用程序所额外产生的数据,它是项目正常运作的必然产品。



1.4 SaaS 到底是什么

理解上面的9个层级的内容是什么,我们就可以看下面这张图表了。

SaaS 全程 Software-as-a-Service,翻译叫 “软件即服务”,讲人话就是 “卖联网软件” 的。

前面提的 9 个层级,除了最后一层数据是我们普通人可以负责的,其它每个层级都需要对应的开发和工程师来负责对吧,那么我们普通人还是企业就不能使用网络软件服务了嘛?

这肯定是不符合事物发展规律的。

SaaS 的存在,就是让用户不用管什么服务器、代码、中间件这些有的没的高深玩意,直接让你在浏览器或本地客户端上直接使用这款联网软件,并创建对应的数据信息。

换句话讲,只要这个软件是联网的,且软件本身的功能就是服务的核心(划重点:社区电商类软件的服务显然不是软件功能本身),它就是 SaaS。SaaS 既可以免费,也可以是通过批量出售软件功能的使用权来赚取收益。


免费情景:

微软:如果你使用了基于 Web 的电子邮件服务(例如 Outlook、Hotmail 或 Yahoo!Mail),那么你已经使用一种形式的 SaaS。

https://azure.microsoft.com/zh-cn/overview/what-is-saas/


付费情景:

在 B 端的语境下,SaaS 通常就是指制作一个面向商业用户的联网软件,然后批量出售这个软件的使用权。它并没有特指这个软件必须是 CRM、ERP、HRM 还是商用 HMI……

所以明白了嘛,SaaS 只是一个商业形式或技术形式的统称,它根本没有具体的设计规范或者学习方法,完全根据业务的实际需求和场景决定。

最后,再问你们一个问题,你们现在负责的项目是 SaaS 嘛?




在 9 层塔中,SaaS 是完全制作好软件让用户直接上手使用的软件,而 PaaS 和 IaaS 就不一样。



2.1 PaaS

PaaS 全文 Platform as a Service,是平台即服务的简称。这属于完全技术化的服务,是非程序员的一般用户难以参与到的业务类型了。

即服务商提供了基础的 7 层服务,只要用户购买了这些使用权,那么就可以直接在这个基础上编写或安装运行的程序进行使用了。

比如全球最大的开源 CMS 博客程序 WordPress,是由 PHP+MySQL 编写的,如果要创建这样的网站,就可以直接购买符合程序对应环境的服务器,再进行安装部署即可。



2.2 IaaS

IaaS 全文 Infrastructure as a Service,就是用户只购买一个完全空白的虚拟主机,类似你购买了一台硬盘格式化后完全空白的虚拟电脑。

用户可以自己选择安装什么样的系统,编写什么样的中间件,最后再搭建自己的框架。这适合定自定义要求更高的用户,完全根据自己的需要 DIY 项目的服务器功能。



2.3 Hosting

Hosting 则是比 IaaS 更进一步的服务,从原本的虚拟服务器升级到了完整的服务器。

也就是说,在一些特定业务环境下(比如特殊的数据安全要求),用户需要购买完整的服务器硬件使用权,从原本的合租换成整租。

所以,Hosting 就是服务器托管的意思,用户向一些服务商购买了完整的服务器硬件使用权和联网功能,然后远程进行控制和使用。而商家负责硬件层面运维,防止服务器断电、断网、损坏、过热、故障等一系列硬件问题。



2.4 Co-location

九层塔中,我们其实还省略了一个更底层的环节 —— 数据中心。

数据中心是一个物理名词,在今天指的是大规模的服务器数据设备安置和运行的空间。比如苹果的云上贵州,就是典型的数据中心。

Co-location 的服务也叫场地出租,就是数据中心的商家,把数据中心的物理空间使用权租用给用户,用户自己购买服务器或商家的(不是临时租用)放进去,再借助数据中心的网络和其它基础服务实现服务器的正常运转。

这个概念大家简单理解就可以,我就不多做介绍了。

所以,九层塔中包揽了不同层级数量的技术,就可以形成不同的服务,每一级服务有各自的优缺点,是由项目的实际情况决定的。




相信看完前面的介绍大家已经知道,SaaS 等服务是建立在联网的基础之上的,也就是说,除了可以独立运行在你客户端里的本地软件,还包含更多需要联网的软件,或者干脆运行在远程服务器主机上的软件。

这是一个发展的过程……

最早的软件安装是我们到软件店里购买软盘、光盘,回到家里的电脑安装,这些软件往往只在本地运行,是不需要联网的孤岛。

随着互联网行业的发展,孤岛渐渐被消除,联网上传和获取数据越来越普及,甚至,软件都不需要再下载和安装,直接用浏览器就可以访问使用。

这种模式,就催生了软件的开发维护与服务器、网络的硬件运行进行了分工,一般的产品开发团队专注在软件应用层面的开发工作,而把网络、远程服务交给其它商家,并付费购买。

这样不仅带来更高的效率,而且降低了各自的成本,实现了多方的共赢。

所以,我们再来理解云服务这个词就很容易了,云就是网络,云服务就是基于联网实现的各种软硬件服务的总和。

除了远程的虚拟机、中间件、数据库外,还有远程计算、渲染、CND加速、直播分流等等。

这也是为什么云服务会成为互联网发展的基础,因为它实在太重要了,几乎所有互联网公司都无法脱离云服务带来的支持。

这也是为什么各个大厂纷纷投入云服务的赛道中,因为这是互联网的基建和命脉之一,拥有非常广阔的前景与市场。而在马太效应强者越强的现实环境下,头部的厂商拥有更好的机群、技术、人员,可以大幅度降低运作成本,提供更优质但价格更低廉的服务。

虽然云服务在今天不可或缺,价格也越来越有优势。但是,并不是所有企业都一定要选择购买外部的云服务,这就是我们要理解的另一个课题 —— 私有化部署。

云服务再怎么便捷,也有一个缺陷,那就是数据是存储在别的商家、企业的服务器中,有一定的数据安全隐患。

虽然数据安全是云服务的最基本保障,但很多对数据隐私、安全极度重视的企业,是不愿意承担任何外部风险的。所以他们就会通过自建本地服务器(私有云)的方式,实现从网络、硬件到软件全局私有化的部署。

也就是说,服务器机房是自己公司的,网络是自己迁进机房的,服务器自己买的,环境、虚拟化、数据库自己搭建的,后端程序也是自己写的,最后电脑手机上运行的客户端,是连接这些服务器的。

哦对了,当然这些硬件日常的维护也要由自己公司的运维负责……

这样的成本高嘛?非常高。但类似国企、银行、证券、国防、政府机关等机构,对数据的安全性是异乎寻常的执着的,他们是有足够的动力划出预算来确保数据的私密与安全,用来运行自己内部的 B 端系统。

这也是为什么这些机构从一开始就拒绝使用 Figma 这种公有云端软件,尤其是服务器在国外的。

再问下一个问题,私有化部署,就意味着这个环节中所有步骤全是自己搞定嘛?

当然不可能,因为应用这个层面,有时候不是想开发就开发得出来,或者成本实在超出了预算。因为私有化的主要目标是数据安全,但不是应用的工具一定得个性化定制。

比如在即时设计官网的价格页面,就可以看到 “私有部署” 这个选项。它的实际作用,就是允许客户在自己的服务器上安装它,让内部的员工使用设计软件时是同步到公司指定的服务器而不是官方的公共服务器中,满足客户的数据隐私需求

注:这例子大家讨论最多适合理解,非恰饭

所以,了解完上面的概念,你也就大概能明白什么是云服务,什么是私有化。如果需要在工作中碰到更细节的名词还是概念,可以再进一步做理解。

文章来源:UI中国    作者:超人的电话亭
分享此文一切功德,皆悉回向给文章原作者及众读者.

免责声明:蓝蓝设计尊重原作者,文章的版权归原作者。如涉及版权问题,请及时与我们取得联系,我们立即更正或删除。

蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务



echarts设置柱状图柱状图粗细大小

前端达人

主要属性:

 //设置柱状图大小
                    barWidth: 20, 
            
  • 1
  • 2

demo:

<!DOCTYPE html>
<html>

    <head>
        <meta charset="utf-8">
        <title>柱状图大小</title>
        <!-- 引入 echarts.js -->
        <script src="https://cdn.bootcss.com/echarts/4.2.1-rc1/echarts.min.js" type="text/javascript"></script>
        <script src="http://code.jquery.com/jquery-1.8.0.min.js"></script>
    </head>

    <body>
        <!-- 为ECharts准备一个具备大小(宽高)的Dom -->
        <div id="main" style="width: 600px;height:400px;"></div>
        <script type="text/javascript">
            // 基于准备好的dom,初始化echarts实例
            var myChart = echarts.init(document.getElementById('main'));
            // 指定图表的配置项和数据
            myChart.setOption({
                title: {
                    text: '柱状图'
                },
                tooltip: {},
                legend: {
                    data: ['销量']
                },
                xAxis: {
                    data: ["1", "2", "3", "4", "5", "6", "7", "8", "9"]
                },
                yAxis: {},
                series: [{
                    name: '销量',
                    type: 'bar',
                      //设置柱状图大小
                    barWidth: 20,
                    //设置柱状图渐变颜色
                    itemStyle: {
                        normal: {
                            color: new echarts.graphic.LinearGradient(0, 1, 0, 0, [{
                                offset: 0,
                                color: "#1268f3" // 0% 处的颜色
                            }, {
                                offset: 0.6,
                                color: "#08a4fa" // 60% 处的颜色
                            }, {
                                offset: 1,
                                color: "#01ccfe" // 100% 处的颜色
                            }], false)
                        }
                    },
                    data: ["1", "2", "3", "4", "5", "2", "3", "4", "3"]
                }]
            });
        </script>
    </body>

</html> 
            
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57

css 设置tr的边框

前端达人

有时候有设置tr边框的需求,写下如下css

tr{

border-bottom: 1px solid red;

}

发现不起作用,后来在w3c上查了查,原来只有table,th和td有独立的边框,tr并无边框。

但我想实现每一行都存在下边框,其他边框不存在,该怎么办呢?


有两种实现方法:

方法1:

table{

border-collapse: collapse;

}

tr{

border-bottom: 1px solid red;

}

解释,border-collapse: collapse; 将table,th和td的边框合成单一的边框,此时在使用tr就可以达到目的。


方法2:

先在table标签里面设置cellspacing等于0,

<table cellspacing="0">

然后,

td{

border-bottom: 1px solid red;

}

解释,如何不设置cellspacing等于0,直接设置td的下边框,则下边框会不连续,因为cellspacing不为零,单元格于单元格之间存在间隙。




转自:csdn

蓝蓝设计建立了UI设计分享群,每天会分享国内外的一些优秀设计,如果有兴趣的话,可以进入一起成长学习,请扫码蓝小助,报下信息,蓝小助会请您入群。欢迎您加入噢~~希望得到建议咨询、商务合作,也请与我们联系。

截屏2021-05-13 上午11.41.03.png

分享此文一切功德,皆悉回向给文章原作者及众读者.
免责声明:蓝蓝设计尊重原作者,文章的版权归原作者。如涉及版权问题,请及时与我们取得联系,我们立即更正或删除。

蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务

UI设计公司、界面设计公司、UI设计服务公司、数据可视化设计公司、UI交互设计公司、高端网站设计公司、UI咨询、用户体验公司、软件界面设计公司

JavaScript制作贪吃蛇小游戏

前端达人

目录

效果展示

原理分析

 Game.js文档

Snake.js文档

Food.js文档

附上源代码


写了这么久的代码

是否你和我一样感到枯燥乏味了呢?

是否没有前进的动力了呢?

别忘了当时的你踌躇满志将前端Web一举拿下的斗志啊!


今天博主要给大家展现一个好玩的游戏

贪吃蛇小游戏!

嘿,你可别小瞧这东西!

制作过程是从无到有

等做完它

你就能从中体会到比玩游戏还快乐的居然是打代码!


效果展示

原理分析

我们制作前为了代码更清晰就分成几个js文档来编写。

其中Game.js可以看作是一个媒介的作用;Snake.js是当蛇初始化时在最左边向右走的状态;

 贪吃蛇在游戏中的运动可以想象成这条蛇是在一张25*25的表格中运动:

 如图所示

 Game.js文档

所以我们在Game.js中添加表格节点

 
  1. function Game() {
  2. this.row = 25;
  3. this.col = 25;
  4. }
  5. Game.prototype.init = function() {
  6. this.dom = document.createElement('table');
  7. // 创建表格--父元素为document(页面中创建表格)
  8. // var tr, td;
  9. for (var i = 0; i < this.row; i++) { //追加行
  10. var tr = document.createElement('tr');
  11. for (var j = 0; j < this.td; j++) { //追加列
  12. var td = document.createElement('col');
  13. td.appendChild(tr);
  14. }
  15. }
  16. };

Snake.js文档






Snake.js中当蛇初始化时最左边向右走的状态

如图所示

 
  1. function Snake() {
  2. // 蛇的初始化身体
  3. this.body = [
  4. { 'row': 3, 'col': 5 },
  5. { 'row': 3, 'col': 4 },
  6. { 'row': 3, 'col': 3 },
  7. { 'row': 3, 'col': 2 }
  8. ];
  9. }
  10. Snake.prototype.render = function() {
  11. // 蛇头的渲染
  12. game.setColorHead(this.body[0].row, this.body[0].col.'pink');
  13. // 蛇身的渲染
  14. for (var i = 1; i < this.body.length; i++) {
  15. game.setColor(this.body[i].row, this.body[i].col, 'cyan')
  16. }
  17. }

蛇在运动的时候它的原理是“头增尾删”。

因为蛇的长度先是不变的,而我们改变的也是改变这个四个格子的颜色,走一格头部那一格颜色变为粉色,尾巴那一格的颜色变为白色。


接下来让蛇通过我们按键来进行运动:放在一个监听事件内

 
  1. // 设置键盘的事件监听
  2. Game.prototype.bindEvent = function() {
  3. var self = this;
  4. document.addEventListener('keydown', function(e) {
  5. // 用ASCII码值判断键盘方向
  6. switch (e.keyCode) {
  7. case 37: //左
  8. if (self.snake.direction == 'R') return; // 先进行判断,如果当前的方向是向右移动,此时我们不能按左键
  9. self.snake.changeDirection('L');
  10. self.d = 'L';
  11. break;
  12. case 38: //上
  13. if (self.snake.direction == 'D') return; // 先进行判断,如果当前的方向是向下移动,此时我们不能按上键
  14. self.snake.changeDirection('U');
  15. self.d = 'U';
  16. break;
  17. case 39: //右
  18. if (self.snake.direction == 'L') return; // 先进行判断,如果当前的方向是向左移动,此时我们不能按右键
  19. self.snake.changeDirection('R');
  20. self.d = 'R';
  21. break;
  22. case 40: //下
  23. if (self.snake.direction == 'U') return; // 先进行判断,如果当前的方向是向上移动,此时我们不能按下键
  24. self.snake.changeDirection('D');
  25. self.d = 'D';
  26. break;
  27. }
  28. })
  29. }

接下来我们判定蛇是否撞到墙而结束

 
  1. // 死亡的判断,超出了表格边缘的部分
  2. if (this.body[0].col > game.col - 1 || this.body[0].col < 0 || this.body[0].row > game.row - 1 || this.body[0].row < 0) {
  3. alert('撞到墙了哦,一共吃掉了' + game.score + '颗草莓');
  4. this.body.shift();
  5. clearInterval(game.timer);
  6. location.reload();
  7. }


接下来我们判定蛇是否撞到自己而结束

 
  1. // 自己撞到自己的时候会判定死亡
  2. for (var i = 1; i < this.body.length; i++) {
  3. // 如果当前蛇的头部和身体的某一个部位的 row 和 col 完全重合的时候
  4. if (this.body[0].row == this.body[i].row && this.body[0].col == this.body[i].col) {
  5. alert('撞到自己了,吃掉了' + game.score + '颗草莓');
  6. this.body.shift();
  7. clearInterval(game.timer);
  8. location.reload();
  9. }
  10. }

Food.js文档


食物food类,用来产生食物

 
  1. function Food(gameSnake) {
  2. // 食物的位置
  3. this.row = parseInt(Math.random() * gameSnake.row)
  4. this.col = parseInt(Math.random() * gameSnake.col)
  5. }
  6. Food.prototype.render = function() {
  7. game.setHTML(this.row, this.col);
  8. }

食物随机生成在单元格中,利用do...while来实现

 
  1. function Food(gameSnake) {
  2. var self = this;
  3. // 下面的 do-while 循环语句作用是先创建一个 row 和 col
  4. 然后判断这个 row 和 col 是否在蛇的身上
  5. //do...while来创建食物
  6. do {
  7. // 食物的位置
  8. this.row = parseInt(Math.random() * gameSnake.row)
  9. this.col = parseInt(Math.random() * gameSnake.col)
  10. } while ((function() {
  11. // 遍历蛇的 row col 然后和 food 新随机出来的 row col 进行判断,是否重合
  12. for (var i = 0; i < gameSnake.snake.body.length; i++) {
  13. if (self.row == gameSnake.snake.body[i].row && self.col == gameSnake.snake.body[i].col) {
  14. return true;
  15. }
  16. }
  17. return false;
  18. })());
  19. }

文章来源:csdn   作者:

分享此文一切功德,皆悉回向给文章原作者及众读者.

免责声明:蓝蓝设计尊重原作者,文章的版权归原作者。如涉及版权问题,请及时与我们取得联系,我们立即更正或删除。

蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务



Vue按需引入Echarts,并从V4版本升级到V5版本

前端达人

一、原本的V4版本按需引入: main.js页面

import Echarts from 'echarts/lib/echarts' import 'echarts/lib/chart/pie' import 'echarts/lib/chart/bar' import 'echarts/lib/chart/line' Vue.prototype.echarts = Echarts 
  • 1
  • 2
  • 3
  • 4
  • 5

二、升级版本

!!!注意:要先删除插件,再重新安装插件,要不然是没效果的(我就说咋没效果)

  • 删除echarts
npm uninstall echarts --save 
  • 1
  • 再重新安装echarts
npm install echarts --save 
  • 1

三、按需处理

  • 在main.js页面

参考官方:https://echarts.apache.org/zh/tutorial.html#%E5%9C%A8%E6%89%93%E5%8C%85%E7%8E%AF%E5%A2%83%E4%B8%AD%E4%BD%BF%E7%94%A8%20ECharts

import * as Echarts from 'echarts/core'; import { BarChart, PieChart, LineChart } from 'echarts/charts'; import { TitleComponent, TooltipComponent, GridComponent, LegendComponent } from 'echarts/components'; // 引入 Canvas 渲染器,注意引入 CanvasRenderer 或者 SVGRenderer 是必须的一步 import { CanvasRenderer } from 'echarts/renderers'; Echarts.use([BarChart, PieChart, LineChart, TitleComponent, TooltipComponent, GridComponent, CanvasRenderer, LegendComponent]) Vue.prototype.echarts = Echarts 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

四、成功




文章来源:csdn   作者:

分享此文一切功德,皆悉回向给文章原作者及众读者.

免责声明:蓝蓝设计尊重原作者,文章的版权归原作者。如涉及版权问题,请及时与我们取得联系,我们立即更正或删除。

蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务

几个超火的在线编程网站,别错过

前端达人

大家好,我是鱼皮,今天给大家推荐几个最近非常流行的编程网站,相信能够帮助大家提高编程效率、更好地学习编程。

热门编程网站推荐

Codepen

演示视频:https://www.bilibili.com/video/BV1im4y1X7zb/

国外的在线前端编程网站,在这里你可以发现很多国外大神编写的前端代码,除了各种网页布局代码外,更多的是各式各样好玩的、炫酷的、新颖的前端动画和特效。

比如圣诞节快到了,很多小伙伴问我能不能用代码画颗圣诞树。

我是不会,但是在这个网站中,输入 “Christmas Tree” 搜索,就能看到各种不同风格的圣诞树网页啦!

Codepen 好玩的网页

点击你看中的网页,就能进到代码编辑页面,在这里,你可以任意修改 HTML、CSS、JavaScript 前端代码,并且在底部的区域实时浏览运行效果,非常地方便!

在线编辑

编辑好网页后,可以在网页右下角的菜单中进行全屏浏览、收藏、克隆、分享等,还能直接将网页内嵌到我们自己的项目中,或者下载完整代码包到本地。

网页操作

得益于前端技术的发展,这个网站为开发者提供了搜索项目、在线编辑、分享导出的一条龙服务,使得我们能够以自主练习的方式轻松学习别人优秀的代码。

下面再分享几个类似的网站。

CodeSandbox

代码沙箱,顾名思义,可以帮助你在隔离的环境中运行前端项目。

在这里你可以基于丰富的模板来创建自己的沙箱(项目),比如 React、Vue、Angular、VuePress、Svelte 等常见的前端框架:

创建好沙箱后,你就可以在线编辑代码、实时查看效果,或者分享沙箱给其他小伙伴啦~

在线编辑

JSFiddle

前端开发的练习场,也可以在线编写代码、实时浏览效果。相对于 Codepen,个人感觉这个网站的编辑体验更好:

在线编辑

当你在网上看到了一段不错的 JS 代码或者插件,不必再下载到本地了。直接把代码粘贴到 JSFiddle 中,就能以最快的方式查看运行效果了。现在很多前端组件库也用到了这种平台,给开发者所见即所得的体验。

JSRUN

国内的在线编程网站,除了前端外,甚至支持多达 30 多种编程语言的在线调试和运行!

同 Codepen 一样,你可以在这里看到很多别人编写的代码片段,直接下载。还可以保存和分享你的代码,建立自己的小代码合集。

下载代码

不得不说,在国内,这个网站算是做的相当出色的了,访问速度和功能体验都很棒!

Gitpod

这个平台要比上面提到的网站更高级一些,它是一个强大的在线 IDE(集成编程环境),提供了 VSCode 风格的编辑器,允许你在线编写代码完成开发。

在线 IDE

Gitpod 基于容器技术,可以帮助你一键编译、构建、运行任何 GitHub 项目,不止前端!而且每个项目的运行都是互相隔离的,随用随创建、用完可随时回收,非常灵活。

如果你看中了一个 GitHub 项目,又不想在本地去搭建各种环境去查看它的运行效果,那么最好的方式就是使用 Gitpod 来在线构建和执行。现在也有越来越多的 GitHub 项目接入了 Gitpod,大家只要看到下图的按钮,都是可以一键部署运行的,大大提高效率!


以上就是本期分享,有帮助的话帮忙点个  吧,谢谢大家!


文章来源:csdn   作者:

分享此文一切功德,皆悉回向给文章原作者及众读者.

免责声明:蓝蓝设计尊重原作者,文章的版权归原作者。如涉及版权问题,请及时与我们取得联系,我们立即更正或删除。

蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务

日历

链接

个人资料

蓝蓝设计的小编 http://www.lanlanwork.com

存档