首页

【前端】参考C站动态发红包界面,高度还原布局和交互

前端达人

目录

1、界面效果

2、界面分析

2.1、整体结构

2.2、标题

2.3、表单

2.4、按钮

3、代码实现

3.1、标题区域布局

3.2、表单区域

3.2.1、祝福语

3.2.2、红包数量

3.2.3、红包总金额

3.2.4、余额支付

3.3、确认按钮区域

4、完整代码

5、基础知识点


1、界面效果

  • 完成效果

  • C站发红包界面 

2、界面分析

2.1、整体结构

上部分为标题、中间为表单、底部为确定按钮

2.2、标题

底部背景、标题文本、右上角关闭按钮

2.3、表单

祝福语文本、红包数量文本、红包总金额、当前余额文本显示、以及前往充值按钮

2.4、按钮

左边为需支付金额显示,右边为取消和确定按钮

3、代码实现

3.1、标题区域布局

1)背景图片

图片宽度380px像素,高度56px像素

2)背景图片自动填充

布局一个div,宽度为400px像素,高度为56px像素,然后再设置背景图片样式,由于图片本身宽度小于div宽度,div会多出20px像素,图片会自动填充,默认效果如下


  1. <div style="width:400px;height:56px;background:url(/1674461966454.jpg);background-size: 100%;">
  2. </div>

 

 3)图片百分比显示

再给div设置背景百分比缩放显示,效果如下

background-size: 100%;

 4)文本

布局一个span标签,显示"添加红包"文本,白色黑体,18号字体,加粗,左对齐,且左边距20px像素。并设置div标签56px像素垂直居中样式,效果如下

5)关闭按钮

在右上角添加一个关闭按钮,一般可以设置一个svg标签图标,设置高28px,宽36px

  • base64编码图标
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEgAAAA4CAYAAABez76GAAAAAXNSR0IArs4c6QAAAtVJREFUeF7tm2FO3DAQhR+0BVZt2QIFujfrQXqMHqQ3W4kflRYJrZBArV6EUTa7jj0ee0yILUUIZcb2fJnMsx3tEYAfAI4x3/YPwDOARwAPAJ76KI4AfAdwMl8+e5ET0j0AggMBXQBYNEA7BJhNfwmJgL6+XI3RLgFm0oaAmD3Motb2CdwREOsP61Br+wQeCIgKRiVrbZ/AEwGxzV3qfcnRFWm2JvUeRA5Qk/oAoCb1AUBN6gOAmtQHADWpDwBqUh8BqEn9AUhO5nmrSX0AkLnULxaL7gFtt9vu7EXatP4x4/UzyFTqGdx6vf7NSa5Wq19SSFr/GDi06QMyk3oX3HK5/MlJbDabPxJIWv9YOENAZlI/DFACSeMrAeNs+xlkKvUpgab4pEDp+wwBmUq9JGCJrRbKGCBzqY8JPMYmJ5QxQOZSz8mMAeB9qp0r6JJ6lQPa8BUzlfp+AD5ItKkFZ6hi/N9M6g893UOQ+nbS5UCJDDKTet/kfZBqwDmUQaZSL8mitwToCsBpjvSU9jGFV4wxnQP4Ig1Oaz+VIt2prvWn6CnJPAGZFuqYRWCMjTaDff7DdZCzM9lySAKX2OaE5QPEGsRaVKylBJziow3AB4iv2e3gvEg71qu/JlCNb0oAPkDdCh/A55ROQz7aAy+tf2h+/ftjgD4CuJF0JrHVHplq/WPnOgaIfVwCOIvtTGqnPXTX+sfMNwSo6uY1JoDSNiFARWtR6eBy9B8DiDbXAFiTZtdiABHKbF+1WECEVGUTWztlJYBoS1WrchRSC5QEEOdIe54Xzea3HVJAs4OUAoiQuFdjJn2qlfpW46YCcpC+lVxpW0EYG0cDyPXLDS0VLkdfb4HJzhxyBcVFJBXu3S0mcwFyxZufrplROfutmlUlAmEBJyRek/8tbAlA7om/C1AlATlQHIMLS35O4tnSpLLKAtCwhrCQExj/8vrwAo3gasxntMb9B9PXrmqWhf+yAAAAAElFTkSuQmCC
  • 错位布局

设置相对定位position样式,位于右上角。它所在的父级就要设置绝对定位relative。这样关闭按钮图标就会以它所在的父级定位,否则可能会布局错位,比如下面错位效果

  •  正确布局

  • 样式代码

  1. <style type="text/css">
  2. .title { width: 400px; height: 56px; background: url(/1674461966454.jpg); background-size: 100%; line-height: 56px;position:relative; }
  3. .title-text { font-size: 18px; font-weight: bold; color: #fff; font-family: 黑体; margin-left: 20px; }
  4. .close { position: absolute; top: 0px; right: 0px; width: 36px; height: 28px; }
  5. </style>
  6. <div class="title">
  7. <span class="title-text">添加红包</span>
  8. <img class="close" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEgAAAA4CAYAAABez76GAAAAAXNSR0IArs4c6QAAAtVJREFUeF7tm2FO3DAQhR+0BVZt2QIFujfrQXqMHqQ3W4kflRYJrZBArV6EUTa7jj0ee0yILUUIZcb2fJnMsx3tEYAfAI4x3/YPwDOARwAPAJ76KI4AfAdwMl8+e5ET0j0AggMBXQBYNEA7BJhNfwmJgL6+XI3RLgFm0oaAmD3Motb2CdwREOsP61Br+wQeCIgKRiVrbZ/AEwGxzV3qfcnRFWm2JvUeRA5Qk/oAoCb1AUBN6gOAmtQHADWpDwBqUh8BqEn9AUhO5nmrSX0AkLnULxaL7gFtt9vu7EXatP4x4/UzyFTqGdx6vf7NSa5Wq19SSFr/GDi06QMyk3oX3HK5/MlJbDabPxJIWv9YOENAZlI/DFACSeMrAeNs+xlkKvUpgab4pEDp+wwBmUq9JGCJrRbKGCBzqY8JPMYmJ5QxQOZSz8mMAeB9qp0r6JJ6lQPa8BUzlfp+AD5ItKkFZ6hi/N9M6g893UOQ+nbS5UCJDDKTet/kfZBqwDmUQaZSL8mitwToCsBpjvSU9jGFV4wxnQP4Ig1Oaz+VIt2prvWn6CnJPAGZFuqYRWCMjTaDff7DdZCzM9lySAKX2OaE5QPEGsRaVKylBJziow3AB4iv2e3gvEg71qu/JlCNb0oAPkDdCh/A55ROQz7aAy+tf2h+/ftjgD4CuJF0JrHVHplq/WPnOgaIfVwCOIvtTGqnPXTX+sfMNwSo6uY1JoDSNiFARWtR6eBy9B8DiDbXAFiTZtdiABHKbF+1WECEVGUTWztlJYBoS1WrchRSC5QEEOdIe54Xzea3HVJAs4OUAoiQuFdjJn2qlfpW46YCcpC+lVxpW0EYG0cDyPXLDS0VLkdfb4HJzhxyBcVFJBXu3S0mcwFyxZufrplROfutmlUlAmEBJyRek/8tbAlA7om/C1AlATlQHIMLS35O4tnSpLLKAtCwhrCQExj/8vrwAo3gasxntMb9B9PXrmqWhf+yAAAAAElFTkSuQmCC" alt="">
  9. </div>

3.2、表单区域

3.2.1、祝福语

1)组成元素

红色星号、文本、输入文本框、刷新文本按钮

2)calc函数

它属于css3的功能,calc() 函数用于动态计算长度值。对于布局非常有作用。

需要特别注意,函数内的参数值前后都需要保留一个空格,例如:width: calc(100% - 40px);

3)刷新小图标

样式设置16x16高宽度

data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAA3NJREFUSEu1lX+IVFUUx7/nPpV1N1zbzNQsXFkUoZBCqH+KNhJikKid14QpsjLv3Uc/yCQpCcISot+yJZHz3qxj2xIxzozJYCCuWiREfxQZJIT9IgjKoq0l3WZ33v3GvN3ZdczdmWXr/vfePef7uefce84R/M9LGtVPFYvN+Lm0H8SVIhwi5BcFc7i1FScSiUQ4lU7DgN7e3MpyyLMAVK2YnBOoXVp37bscJAKk3i0uwvnRByFsmjQKv/KcxJGLnVJvZ69XI1hNkasAWUXCAXldxUYgAy0tTYlNmzYMXuwzBgjyu0HzzCUnMPObrKVbtnSdmyr8bDZrDQ7hAaHsJdEmIh8vv7Z5fSwWK1V9IkAQ5JeTdAEsJrAZ4BWRwbw5HV73fd/Wu6dM5tCKkdHwJMAVEHnTc+1HawCVj76+oy3DpaHPQKwG5ALA5kYBFf90unBDaMLPRaAEcrPr2l+OpW58pYL8E6B5FcAZAPMBtM8EUJHx/dwegtsF6j2t4xsnAJnMyaaR8m/fg1giFmI0shPELVhorvESiT/rpai6H6Ua5gdSypYyyxwn8XsUgd+bu4shjwH4Ubt2+4ED7y8wJmxLJu3vGhWv2vnBweMk7lSCe133/sNjAL/wFBG+CJE3PNfeNlPRmqcc5J8HzdMQ9Zznxp+tPtMANI4oeVw79uuzAfjp3DYa9kBUj+fGt49HMHE5j2kd3zsbQCqdfxLGvARRr3lufEdNikRkn3bth2YFCPL7QbMVIg97rv3WeKEV1hiGZ0Tw68JWLp2ueU0HJ6n8dO6nymtUImsrtTBZB37uC4BrxZL1OmkPNBpFJpNdMlpWAxTpEeEgQ+YAOetpe9UlhZbbCfIFERxzHftuETGNQHz/4AYCRVHqCMiVJNcILK11V1AD6OsrLB4uhaejYlOySzv27hkBRL4h2QHB17ip/UZv3brRGsBYP8nfHhoeB6hEsVs7iXfqQSYiEERDh2KSmDPvVLVJ/mvg+OnCDprwlYgucpRzrUem66hBkIsZsmZuVHwtJfc4jl287EQLgkObifIeElcDUoLgFCAfKZgPOzoWfdLZ2VmuRtbf/8GC88MX+gVcVv1HyB+Ya3mVg005MtPpbJuhehlgNwlrMlXyqaftW+ulrrpfdyZHJ/z7r9tAq1Ng7gDltNZ28j8DNCo0ld0/bOx/KATgarIAAAAASUVORK5CYII=

4)文本框默认高亮

input输入文本框默认点击选中会有一个高亮的效果,可以设置样式去掉

outline:none;

5)随机文本

设置随机祝福语文本值,可设置js全局数组参数变量保存。

并且给右边的刷新按钮绑定点击事件,然后在事件内使用随机函数进行随机显示

  • 交互代码

  1. <script type="text/javascript">
  2. $(function () {
  3. // 祝福语
  4. var labelText = ['成就一亿技术人!', '节日快乐', 'Hello World', '新春大吉!', '大吉大利', 'Bug Free'];
  5. $('.cl-input img').click(function () {
  6. // Math.random() - 随机函数会产生0~1之间的值
  7. var index = parseInt(Math.random() * labelText.length);
  8. var text = labelText[index];
  9. $('.cl-input input').val(text);
  10. });
  11. });
  12. </script>
  • 效果如下

  • 布局代码

  1. <div class="content-label">
  2. <div class="cl-text">
  3. <span style="color:#f00;">*</span>
  4. <span>祝福语</span>
  5. </div>
  6. <div class="cl-input">
  7. <input placeholder="请填写红包祝福语或标题" value="成就一亿技术人!" />
  8. <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAA3NJREFUSEu1lX+IVFUUx7/nPpV1N1zbzNQsXFkUoZBCqH+KNhJikKid14QpsjLv3Uc/yCQpCcISot+yJZHz3qxj2xIxzozJYCCuWiREfxQZJIT9IgjKoq0l3WZ33v3GvN3ZdczdmWXr/vfePef7uefce84R/M9LGtVPFYvN+Lm0H8SVIhwi5BcFc7i1FScSiUQ4lU7DgN7e3MpyyLMAVK2YnBOoXVp37bscJAKk3i0uwvnRByFsmjQKv/KcxJGLnVJvZ69XI1hNkasAWUXCAXldxUYgAy0tTYlNmzYMXuwzBgjyu0HzzCUnMPObrKVbtnSdmyr8bDZrDQ7hAaHsJdEmIh8vv7Z5fSwWK1V9IkAQ5JeTdAEsJrAZ4BWRwbw5HV73fd/Wu6dM5tCKkdHwJMAVEHnTc+1HawCVj76+oy3DpaHPQKwG5ALA5kYBFf90unBDaMLPRaAEcrPr2l+OpW58pYL8E6B5FcAZAPMBtM8EUJHx/dwegtsF6j2t4xsnAJnMyaaR8m/fg1giFmI0shPELVhorvESiT/rpai6H6Ua5gdSypYyyxwn8XsUgd+bu4shjwH4Ubt2+4ED7y8wJmxLJu3vGhWv2vnBweMk7lSCe133/sNjAL/wFBG+CJE3PNfeNlPRmqcc5J8HzdMQ9Zznxp+tPtMANI4oeVw79uuzAfjp3DYa9kBUj+fGt49HMHE5j2kd3zsbQCqdfxLGvARRr3lufEdNikRkn3bth2YFCPL7QbMVIg97rv3WeKEV1hiGZ0Tw68JWLp2ueU0HJ6n8dO6nymtUImsrtTBZB37uC4BrxZL1OmkPNBpFJpNdMlpWAxTpEeEgQ+YAOetpe9UlhZbbCfIFERxzHftuETGNQHz/4AYCRVHqCMiVJNcILK11V1AD6OsrLB4uhaejYlOySzv27hkBRL4h2QHB17ip/UZv3brRGsBYP8nfHhoeB6hEsVs7iXfqQSYiEERDh2KSmDPvVLVJ/mvg+OnCDprwlYgucpRzrUem66hBkIsZsmZuVHwtJfc4jl287EQLgkObifIeElcDUoLgFCAfKZgPOzoWfdLZ2VmuRtbf/8GC88MX+gVcVv1HyB+Ya3mVg005MtPpbJuhehlgNwlrMlXyqaftW+ulrrpfdyZHJ/z7r9tAq1Ng7gDltNZ28j8DNCo0ld0/bOx/KATgarIAAAAASUVORK5CYII=" alt="">
  9. </div>
  10. </div>

3.2.2、红包数量

布局和祝福语一样,刷新按钮换成了单位文本。

这里文本框有个离开焦点事件,如果判断没有输入值,那么提示”请输入数量",并且红包数量只能是正整数,文本框也变为红色边框,默认则为蓝色边框

  • 布局效果

  • 布局代码

  1. <div class="content-label">
  2. <div class="cl-text">
  3. <span style="color:#f00;">*</span>
  4. <span>红包数量</span>
  5. </div>
  6. <div class="cl-input">
  7. <input placeholder="请填写红包数量" value="" />
  8. <span></span>
  9. </div>
  10. </div>
  •  交互效果

  • 交互代码 

  1. $("#txtCount").blur(function () {
  2. txtCount = $(this).val();
  3. if (txtCount == undefined || txtCount == null || txtCount == '' || txtCount.trim() == '') {
  4. $("i", $(this).parent()).show().html('请输入数字!');
  5. $(this).parent().addClass('red-border');
  6. }
  7. else {
  8. if (txtCount <= 0) {
  9. $("i", $(this).parent()).show().html('请输入有效数字格式!');
  10. $(this).parent().addClass('red-border');
  11. }
  12. else if (!isNaN(txtCount)) {
  13. $("i", $(this).parent()).hide();
  14. $(this).parent().removeClass('red-border');
  15. }
  16. else {
  17. }
  18. }
  19. });

3.2.3、红包总金额

布局和前面一样,这就是前端布局的魅力,有很多可以重用的东西

  • 布局效果

  • 布局代码 

  1. <div class="content-label">
  2. <div class="cl-text">
  3. <span style="color:#f00;">*</span>
  4. <span>红包总金额</span>
  5. </div>
  6. <div class="cl-input">
  7. <input placeholder="请填写红包总金额" value="" />
  8. <span></span>
  9. </div>
  10. </div>

3.2.4、余额支付

这里的布局和前面稍微多点东西,布局差不多。

这里只做读取展示用,也可以用input输入文本框,设置默认只读即可

  • 布局效果

  • 布局代码 

  1. <div class="content-label">
  2. <div class="cl-text">
  3. <span style="color:#f00;">*</span>
  4. <span>余额支付</span>
  5. </div>
  6. <div class="cl-input">
  7. <label>当前余额:<b>51.25</b></label>
  8. <span class="span">前往充值 > </span>
  9. </div>
  10. </div>

3.2.5、文本边框交互逻辑

当点击文本框时,先判断是否已经提示无效信息,也就是已经有红色边框,有则不显示蓝色边框,没有则显示蓝色边框。当离开文本框焦点,那么则移除蓝色边框

  • 交互效果

  • 交互代码

  1. // 文本框点击事件
  2. $('.cl-input input').click(function () {
  3. var className = $(this).parent().attr('class');
  4. if (className.indexOf('red-border') < 0) {
  5. $(this).parent().addClass('blue-border');
  6. }
  7. }).blur(function () {
  8. $(this).parent().removeClass('blue-border');
  9. });

3.3、确认按钮区域

1)支付额文本

这里布局左定位,金额数字加红色字体

2)取消和确认按钮

取消按钮鼠标移动上去边框变深,直接使用css的hover属性即可完成。

确认按钮的效果使用同样的方式

3)布局效果

 

 4)布局代码


  1. <!--按钮-->
  2. <div class="button">
  3. <div class="price">
  4. <span>需支付:</span>
  5. <span id="priceSpan" style="font-size:20px;color:#f00;">0.00</span>
  6. <span></span>
  7. </div>
  8. <div class="btn">
  9. <div class="btnCancel">
  10. <span>取消</span>
  11. </div>
  12. <div class="btnOk not-allowed">
  13. <span>确定</span>
  14. </div>
  15. </div>
  16. </div>

5)交互代码


  1. // 红包个数
  2. var txtCount = 0;
  3. var txtPrice = 0;
  4. $("#txtCount").keyup(function () {
  5. txtCount = $(this).val();
  6. $("#priceSpan").html(txtCount * txtPrice);
  7. });
  8. // 红包总金额
  9. $("#txtPrice").keyup(function () {
  10. txtPrice = $(this).val();
  11. $("#priceSpan").html(txtPrice);
  12. });

4、完整代码

红包数量和红包金额那里还有几个交互和逻辑判断,有兴趣的小伙伴可以自己实现下,有疑问的可咨询了解

完整代码可以查看gitCode:小5聊 / Csdn Red Bag Html · GitCode

 

5、基础知识点

calc()函数 可用于高宽度精准布局,更加合理布局
position和relative 相对和绝对定位,同样有助于合理定位和布局
Math.random()        随机函数,随机产生0~1的值
keyup() 键盘弹上事件
click() 元素点击事件
blur() 离开焦点事件

总结:前端布局,要玩出花样和效果,还是需要点艺术天赋。总之,挺有趣的,刚入门可能会觉得比较难,当你熟练之后,还是挺有趣的!

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


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


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




vue可视化拖拽组件模板,vue组件拖拽自定义界面

前端达人

前端可视化开发平台哪个好用?

ThingJS 基于 HTML5 和 WebGL 技术,可方便地在主流浏览器上进行浏览和调试,支持 PC 和移动设备。

ThingJS 为可视化应用提供了简单、丰富的功能,只需要具有基本的 Javascript 开发经验即可上手。

ThingJS 提供了场景加载、分层级浏览,对象访问、搜索、以及对象的多种控制方式和丰富的效果展示,可以通过绑定事件进行各种交互操作,还提供了摄像机视角控制、点线面效果、温湿度云图、界面数据展示、粒子效果等各种可视化功能网页链接。

谷歌人工智能写作项目:小发猫

可视化快速开发平台的难度太高了,有没有简单的?

如果可视化平台还觉得太难了,那真的没有简单的了,程序员还得写代码,全靠经验判定呢typescript是用来干什么的,为什么要用typescript

软件是由程序员编写的代码出现的,一般开发软件需要有UI前端,后台程序员,还有数据库人员等来一起完成一个项目,一般没有专业知识的是没有办法去独立开发一个软件平台的哦。首先要开发软件,需要知道要什么功能?

达到什么效果?最终实现目的。这几个问题搞清楚之后,就可以考虑自己的预算,考虑好了预算之后,才好结合自己的需求,提供给软件开发公司进行沟通,沟通之后,确定价格,这样就可以签合同开始制作啦。

如果有疑问,可以在下面补充,我们一起讨论吧。

hec-dssvue是什么软件

HEC-DSSVue是一个基于Java的可视化实用程序,允许用户在HEC-DSS数据库文件中绘制,制表,编辑和操作数据。

HEC-DSSVue生成的图形是高度可定制的,可以以各种格式保存,包括“jpeg”和“png”(便携式网络图形),或者打印或复制到剪贴板以包含在报告中。HEC-DSSVue包含六十多个数学函数。

除了这些函数之外,HEC-DSSVue还提供了几个实用程序函数,这些函数提供了一种将数据集输入到HEC-DSS数据库中、重命名数据集名称、将数据集复制到其他HEC-DSS数据库文件以及删除数据集的方法。

MongoVUE可视化工具怎么写js代码

一、AdobeEdge目前还处于预览阶段的AdobeEdge是用HTML5、CSS、JavaScript开发动态互动内容的设计工具。内容可以同时兼容移动设备和桌面电脑。

Edge的一个重要功能是Web工具包界面,方便确保页面在不同浏览器中的架构一致性,此外Edge还将整合T...。

前端开发需要掌握什么技术

前端需要掌握的技术还是很多的1.熟练掌握前端开发技术(HTML5、CSS3、JS、JSON、XHTML),了解各项技术的相关标准;2.掌握Ajax异步编程,能够写出高性能、可复用的前端组件;3.对OO、MVC、MVVM等编程思想、前端框架有深刻理解,熟练掌握至少一个前端框架了解其原理(常用前端框架Vuejs,AngularJS,React,Bootstrap,QUICKUI,移动端有:FrozenUI,weUI,SUI,MUI,AUI);4.善于Web性能优化,可访问性、对SEO等有良好的体验;理解表现层与数据层分离的概念、Web语义化;5.了解前端安全机制,熟悉HTTP协议以及浏览器缓存策略;6.熟悉常见JS开发框架源码实现(如:prototype、jQuery、Mootools,Ext,Dojo,underscore、YUI、Kissy);7.拥有良好的代码编写,设计文档撰写的经验,熟练使用Git等版本控制工具;8.对常见的浏览器兼容问题有清晰的理解,并有可靠的解决方案;如IE6/7/8/9、Firefox、Safari、Chrome。

Web前端开发(可视化方向)是什么职位

可往3D开发工程师转型,前提要熟练掌握js,熟悉webgl,这里你可以练练手网页链接ThingJS基于HTML5和WebGL技术,可方便地在主流浏览器上进行浏览和调试,支持PC和移动设备。

ThingJS为可视化应用提供了简单、丰富的功能,只需要具有基本的Javascript开发经验即可上手。

ThingJS提供了场景加载、分层级浏览,对象访问、搜索、以及对象的多种控制方式和丰富的效果展示,可以通过绑定事件进行各种交互操作,还提供了摄像机视角控制、点线面效果、温湿度云图、界面数据展示、粒子效果等各种可视化功能。

ThingJS提供如下相关组件和工具供用户使用:CityBuilder:聚焦城市的3D地图搭建工具,打造你的3D城市地图。CamBuilder:简单、好用、免费的3D场景搭建工具。

ThingPano:全景图制作工具,轻松制作并开发全景图应用,实现3D宏观场景和全景微观场景的无缝融合。ThingDepot:上万种模型,数十个行业,自主挑选,一次制作多次复用。

现在做网页前端的学习路线是什么

初学者必看干货web前端学习路线图,随着移动互联网的发展,web前端逐渐受到企业的重视,前端开发人员的薪资也水涨船高,越来越多的人看好前端行业的发展,想要转行加入。

下面,给大家分享一份web前端学习路线图,希望对初学者有所帮助。Web前端行业的发展,让前端人员能完成比以前更多的职责范围,所以未来前端可以宽口径就业,前景非常好。

除此之外,目前web前端工程师日均岗位缺口超50000,平均薪资10820元/月。对于零基础的人而言,要怎么学习web前端呢?1、前端页面重构。

主要内容为PC端网站布局、Photoshop工具及切图、H5移动端网页布局、HTML5+CSS3新特性与交互。学习目标是完成PC端网站布局,可实现响应式布局,一套代码适配PC端、移动端、平板设备等。

2、前后端网页交互。

主要内容为JavaScript语法全面进阶、ES6到ES10新语法实践、jQuery应用及插件使用、设计模式及插件编写、封装JS工具库及WebAPIS、AJAX+PHP+MySQL前后端交互、前端工程化与模块化应用以及PC端全栈开发项目等。

学习目标是可以掌握前端工程化工具,如git、gulp、webpack等,搭建项目及开发项目。3、+前端框架。

主要内容为全面进阶、Koa2+MongoDB搭建服务、框架、框架、小程序云开发与小程序框架、原生APP与混合APP、数据可视化与桌面应用等。

学习目标是掌握桌面应用及可视化大数据,实现复杂数据展示类项目,能够独立完成前后台相关功能,胜任HTML5全栈开发工程师职位。

很多学习web前端的朋友都希望在学成后能找到一份满意的工作,所以我们在学习过程中一定要注意实战经验的积累,如果你所学的东西对企业没有用,那你所做的一切都是无用功。




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


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


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

Vue/Node.js—时间处理器—silly-datetime

前端达人

一、在Vue框架中使用

1、安装插件—时间格式化插件

npm i silly-datetime --save 

2、Main.js文件引用


        
  1. import Time from "silly-datetime"; //时间格式化处理插件
  2. Vue.prototype.$Time = Time; //全局使用

3、页面中使用

this.$Time.format(new Date(), 'YYYY-MM-DD HH:mm:ss'); 

二、在Node框架中使用

1.安装插件

npm i silly-datetime --save 

2.在node中引入

const timeQs = require('silly-datetime'); // 事件格式化控件

3.在后端路由中

obj.time = timeQs.format(new Date(), 'YYYY-MM-DD HH:mm:ss');

4、参数说明

格式 类型 说明 实例
YYYY 年份 YYYY :2019
MM 月份,补0 MM:07
M 月份,不补0 M:7
DD 日,补0 DD:07
D 日,不补0 D:7
HH 小时 24小时,补0 HH:07
H 小时 24小时,不补0 H:7
hh 小时 12小时,补0 hh:07
h 小时 12小时,不补0 h:7
A am 上午 mm:07
a pm 下午 m:7
mm 分钟 分钟,不补00 mm:07
m 分钟 分钟,不补0补0 m:7
s 秒钟 秒钟,不补00 s:07
s 秒钟 秒钟,不补0补0 s:7
文章知识点与官方知识档案匹配,可进一步学习相关知识


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


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


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

如何使用 Node.js 列出目录中的所有文件

前端达人

在 Node.js 中,您可以使用该fs.readdir()方法列出目录中的所有可用文件。.此方法异步工作以读取给定目录的内容,并返回目录中不包括和的文件名数组..

这是一个读取目录中所有可用文件并在控制台上打印它们的名称的示例:


  1. const fs = require('fs');
  2. // directory path
  3. const dir = './node_modules/';
  4. // list all files in the directory
  5. fs.readdir(dir, (err, files) => {
  6. if (err) {
  7. throw err;
  8. }
  9. // files object contains all files names
  10. // log them on console
  11. files.forEach(file => {
  12. console.log(file);
  13. });
  14. });

fs.readdir()如果给定目录不存在,该方法将抛出错误。

fs模块还提供了 call 的同步变体,readdir()readdirSync()同步工作并返回文件名数组:


  1. const fs = require('fs');
  2. // directory path
  3. const dir = './node_modules/';
  4. // list all files in the directory
  5. try {
  6. const files = fs.readdirSync(dir);
  7. // files object contains all files names
  8. // log them on console
  9. files.forEach(file => {
  10. console.log(file);
  11. });
  12. } catch (err) {
  13. console.log(err);
  14. }

查看本指南以了解有关在 Node.js 应用程序中读取和写入文件的更多信息


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


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


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

web自动化测试入门篇03——selenium使用教程

前端达人

1. 目的

web自动化测试作为软件自动化测试领域中绕不过去的一个“香饽饽”,通常都会作为广大测试从业者的首选学习对象,相较于C/S架构的自动化来说,B/S有着其无法忽视的诸多优势,从行业发展趋、研发模式特点、测试工具支持,其整体的完整生态已经远远超过了C/S架构方面的测试价值。接上一篇文章,我们将继续深入探讨Selenium的相关使用方法与技巧。

 
 

2. 说明

此篇中所用的技术栈为Selenium+Python,因其本身编程难度不高,总体思想都是基于面向对象的编程理念,故只要大家的编码语言基础不弱,就完全可以做到平替。

 
 

3. 关于解答上一篇的问题

在正式启动浏览器之前,这里还需要说说上一篇没有提及的一个问题,后台有同学私信说在对应驱动网站上完全找不到自己浏览器对应版本的驱动,关于浏览器驱动的版本,大家都知道驱动的版本应该是要与浏览器的版本完全对应上的。但往往日常工作中因为环境或者其他客观因素会导致浏览器的版本五花八门,也会出现驱动网站上完全没有你目前工作环境中对应的浏览器版本,这里我们大可使用中版本号一致的驱动来进行尝试,没有必要将版本进行完全的匹配。比如你的Chrome浏览器的版本号为107.0.5304.107,如果这时对应网站只有107.0.5304.62108.0.5359.22的前后两个版本的驱动比较相近,这里就有两个选择,第一就是卸掉原有的浏览器,安装对应的版本;第二则是选择107.0.5304.62来进行尝试;相信大家在成本耗时的判断下,一般都会选择第二个选项来进行尝试对吧?那么我可以很负责任的告诉你,第二个判断是完全行的通的。不必太过纠结驱动的小版本号是否完全匹配。

 
 

4. 启动

我们将一切准备就绪后就可以开始我们的selenium之旅了,首先我们需要将使用selenium进行浏览器的启动(访问百度)。

from selenium import webdriver

browser = webdriver.Chrome() browser.get('https://www.baidu.com') 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

 

如果对应的浏览器驱动没有进行环境变量的设置,可以在代码中直接进行程序的路径指定来进行后续的浏览器操作。

from selenium import webdriver

path = r'C:\Program Files\Google\Chrome\Application\chromedriver.exe' browser = webdriver.Chrome(path) browser.get('https://www.baidu.com') 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

 

使用Selenium打开后的浏览器都会标识出正在受到自动化测试软件控制的相关提示。

在这里插入图片描述

 
 

5. 浏览器基础操作

Selenium本身提供给了我们非常多的各类浏览器与页面的操作函数,方便我们根据所需测试业务来进行自由搭配使用甚至是二开。

 

5.1 浏览器窗口操作

对于浏览器窗口的尺寸进行控制与获取,如最大化、最小化、指定窗口大小等。

 

窗口全屏

browser.fullscreen_window() 
  • 1

 
窗口最大化

browser.maximize_window() 
  • 1

 
窗口最小化

browser.minimize_window() 
  • 1

 
自定义窗口大小(宽X高)

browser.set_window_size(1080, 720) 
  • 1

 
自定义窗口坐标位置与大小(x坐标,y坐标,宽X高)

browser.set_window_rect(100, 200, 1080, 720) 
  • 1

 
获取窗口的大小(宽X高)

browser.get_window_size() 
  • 1

 
获取窗口的坐标位置,返回一个字典对象

browser.get_window_position() 
  • 1

 
获取窗口的坐标与大小(x坐标,y坐标,宽X高)

browser.get_window_rect() 
  • 1

 
获取当前窗口的句柄

browser.current_window_handle 
  • 1

 
获取当前所有窗口的句柄

browser.window_handles 
  • 1

 
 

5.2 页面基础操作

对于浏览器当前页面的一些操作,如前进、后退、刷新等。

 
前进(下一页面)

browser.forward() 
  • 1

 
后退(上一页面)

browser.back() 
  • 1

 
刷新(当前页面)

browser.refresh() 
  • 1

 
截图并保存为test.png(当前页面)

browser.save_screenshot('test.png') 
  • 1

 
截图并保存为png文件(当前页面)

browser.get_screenshot_as_file('test_02.png') 
  • 1

 
截图并将信息转为base64编码的字符串

browser.get_screenshot_as_base64() 
  • 1

 
 

5.3 信息操作

对于浏览器当前一些信息的获取与操作。

 
获取页面URL(当前页面)

browser.current_url 
  • 1

 
获取日志类型,会返回一个列表对象

browser.log_types 
  • 1

 
获取浏览器操作日志,注意函数内的参数为固定值类型’browser’

browser.get_log('browser') 
  • 1

 
获取设备操作日志,参数原理同上

browser.get_log('driver') 
  • 1

 
获取当前页面标题

browser.title 
  • 1

 
获取当前浏览器的名字

browser.name 
  • 1

 
 

5.4 元素操作

Selenium中最基础也是最重要的一环,基本上对于页面的业务操作大多数都集中与此。另外需要注意的是元素定位所使用的find_element_by的方法在很早之前就已经被废弃,这里同样也会使用最新的find_element方法进行讲解。
如何查看页面中的元素与其相关属性,这里以Chrome为例,我们只需按F12或者右键页面选择“检查”,再点击调试窗口的左上角的箭头标志或者使用快捷键Ctrl+Shift+C来进行元素的选取,此时Elements标签页中会将焦点对应跳转至该元素的html代码行中,接下来我们就可以针对不同的元素和不同的属性来进行定位操作。

 
在这里插入图片描述

 

5.4.1 name定位

通过一个元素的name属性来进行定位。

 

比如定位百度中的搜索栏,我们通过name属性来进行定位。该元素的html构造如下:

<input type="text" class="s_ipt" name="wd" id="kw" maxlength="100" autocomplete="off"> 
  • 1

 
我们只需将name属性后面的值拿出,赋予给find_element方法即可。新的By方法我们只需要导入selenium.webdriver.common.by下的By方法即可。

from selenium import webdriver from selenium.webdriver.common.by import By from time import sleep

browser = webdriver.Chrome() browser.get('https://www.baidu.com') sleep(2) browser.find_element(By.NAME, 'wd') 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

 

5.4.2 class name定位

通过一个元素的class属性来进行定位。

from selenium import webdriver from selenium.webdriver.common.by import By from time import sleep

browser = webdriver.Chrome() browser.get('https://www.baidu.com') sleep(2) browser.find_element(By.CLASS_NAME, 's_ipt') 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

 

5.4.3 id定位

通过一个元素的id属性来进行定位。

from selenium import webdriver from selenium.webdriver.common.by import By from time import sleep

browser = webdriver.Chrome() browser.get('https://www.baidu.com') sleep(2) browser.find_element(By.ID, 'kw') 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

 

5.4.4 css定位

css selector也被成为选择器定位,它通过页面内的元素的id、name、tag三个属性来进行定位,根据元素属性的重复程度,可以单独属性定位也可组合属性来进行定位。而且相较于xpath定位方式来说,博主更推荐使用此方法来进行定位,无论是易用度还是维护性来说比xpath定位好的多。

 
单属性定位–tag属性

from selenium import webdriver from selenium.webdriver.common.by import By from time import sleep

browser = webdriver.Chrome() browser.get('https://www.baidu.com') sleep(2) browser.find_element(By.CSS_SELECTOR, 'input') 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

 
单属性定位–id属性

from selenium import webdriver from selenium.webdriver.common.by import By from time import sleep

browser = webdriver.Chrome() browser.get('https://www.baidu.com') sleep(2) browser.find_element(By.CSS_SELECTOR, '#kw') 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

 
单属性定位–class属性

from selenium import webdriver from selenium.webdriver.common.by import By from time import sleep

browser = webdriver.Chrome() browser.get('https://www.baidu.com') sleep(2) browser.find_element(By.CSS_SELECTOR, '.s_ipt') 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

 
多属性定位–tag+id属性

from selenium import webdriver from selenium.webdriver.common.by import By from time import sleep

browser = webdriver.Chrome() browser.get('https://www.baidu.com') sleep(2) browser.find_element(By.CSS_SELECTOR, 'input#kw') 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

 
多属性定位–tag+class属性

from selenium import webdriver from selenium.webdriver.common.by import By from time import sleep

browser = webdriver.Chrome() browser.get('https://www.baidu.com') sleep(2) browser.find_element(By.CSS_SELECTOR, 'input.s_ipt') 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

 
同样的,其他的组合方式大家可以举一反三,不断尝试,比如模糊匹配input[class ~= "局部关键字"]、层级定位#form > span > input等等等等。

 

5.4.5 link text定位

这种定位方式适用于页面中带有超链接的元素,直接通过超链接标签内的文字进行元素定位。

我们以百度首页为例,可以看到该页面中有很多的超链接标签,如果我们想模拟点击跳转至新闻对应页面的操作,就可以用link text的元素定位方法来进行实现。

在这里插入图片描述
 
使用超链接标签对中的“新闻”一词来进行定位。

from selenium import webdriver from selenium.webdriver.common.by import By from time import sleep

browser = webdriver.Chrome() browser.get('https://www.baidu.com') sleep(2) browser.find_element(By.LINK_TEXT, '新闻').click() 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

 

5.4.6 partial link text定位

这个定位方式与link text定位十分相像,实际上也就是link text的模糊查找定位方式,对象也是超链接内的文字,只不过他匹配的不是全部文字而是局部。

from selenium import webdriver from selenium.webdriver.common.by import By from time import sleep

browser = webdriver.Chrome() browser.get('https://www.baidu.com') sleep(2) browser.find_element(By.PARTIAL_LINK_TEXT, '新').click() 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

 

5.4.7 tag定位

tag定位的效率总体来说不高,也不太推荐单独使用,html页面中一般也是由很多相同或不同的标签对组成。就tag而言标签重复的越多,定位的效率其实也就越低。

比如我们想在百度的搜索栏中输入“selenium”关键字,那么光使用tag其实就很难达到我们的目的,甚至无法准确定位到我们想要的元素。如果运气好,搜索栏的input标签在html页面中排在第一位那还好,只要不是第一位,我们就需要编写其他的代码逻辑来辅助我们继续定位这个元素。
 

所以下面的代码实在是不能称之为高效的执行代码

from selenium import webdriver from selenium.webdriver.common.by import By from time import sleep

browser = webdriver.Chrome() browser.get('https://www.baidu.com') sleep(2) browser.find_element(By.TAG_NAME, 'input').send_keys('selenium') 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

 

5.4.8 xpath定位

一般来说无法通过以上的这些元素定位方法定位的情况下,我们会使用xpath定位方法。但这里需要特别注意,xpath方法分为绝对路径和相对路径两种定位方式,博主只推荐如果真要使用xpath就使用相对路径+正则表达式的方式来进行元素定位。不推荐绝对路径的原因就不用博主多说了吧,只要你敢用,后期的脚本维护与复用绝对会让你抓狂的。

 

还是老样子,我们使用xpath的相对路径写法来定位百度首页的搜索栏。

from selenium import webdriver from selenium.webdriver.common.by import By from time import sleep

browser = webdriver.Chrome() browser.get('https://www.baidu.com') sleep(2) browser.find_element(By.XPATH, '//*[@id="kw"]').send_keys('selenium') 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

 
另外与find_element方法相对应的find_elements方法这里就不多做介绍了,该种方法是将当前页面中所有能匹配上对应元素定位方法的元素全部获取。大家可以根据自己的需求来进行选取和使用。

 
 

5.5 延时方式

我们加载页面时通常会因为网络环境等各方面的客观因素而导致元素加载的速度各不相同,如果此时我们没有对业务操作进行一定的延时执行,那么大概率业务操作会出现各类的no such element报错。
那么我们就需要在页面元素加载完成之后再对相应的元素进行业务操作来规避上面说的这个问题。Selenium内可以使用三种延时的函数来进行对应的延时业务操作。

 

5.5.1 隐式等待

隐式等待的作用是在页面加载是隐性的进行特定时长的等待,如果在规定的等待时长内页面加载完毕,则会继续进入下一个业务操作,如果没有加载完毕,则会抛出一个超时的异常。这里其实有两个问题,第一,隐式等待是全局性质的,也就是说一旦你设置了个5秒,那整个程序都会使用这个等待时间类进行配置,灵活性较低;第二,如果碰到了有些页面中的元素是局部加载的话,那整个页面的加载是否完成也就没有了其意义,隐式加载无法针对这样的情况作出调整,智能度较低。所以一般来说只要是对于页面的整体加载要求不高或者元素的加载比较稳定的程序,都可以使用隐式等待来进行延时操作。

 

from selenium import webdriver from selenium.webdriver.common.by import By

browser = webdriver.Chrome() browser.get('https://www.baidu.com') browser.implicitly_wait(5) browser.find_element(By.XPATH, '//*[@id="kw"]').send_keys('selenium') 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

 

5.5.2 显式等待

显式等待的作用则是使用特定的等待时长来进行某些业务逻辑判断,如果判断(比如元素是或否加被定位)在时间完成那继续执行下一个业务操作,如果判断失败也会抛出no such element的异常,而显式等待的默认检查元素周期为0.5秒。乍一看好像与隐式等待差不多,其实不然,首先显式等待是针对页面中某个或某组特定元素而执行的,隐式则是全局,对所有的元素都生效;其二,显式等待可以通过自定义条件来进行元素的定位和选取,隐式则不行。

 

from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.wait import WebDriverWait from selenium.webdriver.support import expected_conditions as EC

browser = webdriver.Chrome() browser.get('https://www.baidu.com') ele = WebDriverWait(browser, 10, 0.5).until(EC.presence_of_element_located((By.XPATH, '//*[@id="kw"]'))) ele.send_keys('selenium') 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

 

5.5.3 强制等待

这个应该是平时大家代码中用的最多的等待方式了吧,sleep是针对线程进行挂起的一种等待方式,等待时长根据指定的参数来进行决定。最大的好处就是简单粗暴,无任何逻辑在里面,所以也被称为强制等待。

 

from selenium import webdriver from selenium.webdriver.common.by import By from time import sleep

browser = webdriver.Chrome() browser.get('https://www.baidu.com') sleep(2) browser.find_element(By.XPATH, '//*[@id="kw"]').send_keys('selenium') 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

 
那么以上的三种等待方式其实各有各的特点与缺点,三者之间没有绝对的好用和不好用,而在我们的日常工作场景中也希望大家可以根据实际的情况有选择性的使用。

 
 

5.6 超时等待

元素加载超时我们可以使用以上三种延时方式来进行处理,那么页面超时了又该如何操作呢?selenium也为我们准备了两个函数来对应这样的局面。
 
页面加载超时

browser.set_page_load_timeout(30) 
  • 1

这里推荐将超时的时间有效的拉长,不宜过短。过短的超时时间容易导致整体页面出现未加载html代码情况下直接令驱动无法工作的情况。
 
 
页面异步js或ajax操作超时

browser.set_script_timeout(30) 
  • 1

这个函数是用于execute_async_script()相关的异步js操作超时报错,由于是异步操作,等待时间同理也不易过短。

 
 

5.7 键鼠操作

浏览器中键盘与鼠标的操作也是不可或缺的重要一环,在被测对象的业务要求中往往占有不少的戏份。

 
文字输入

browser.find_element(By.ID, 'kw').send_keys('selenium') 
  • 1

 
点击

browser.find_element(By.ID, 'kw').click() 
  • 1

 
点击并按住不放(左键长按),这些模拟鼠标操作需要导入ActionChains包

from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.common.action_chains import ActionChains

browser = webdriver.Chrome() browser.get('https://www.baidu.com') act = ActionChains(browser) ele = browser.find_element(By.ID, 'kw') act.click_and_hold(ele).perform() 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

 
右键点击

from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.common.action_chains import ActionChains

browser = webdriver.Chrome() browser.get('https://www.baidu.com') act = ActionChains(browser) ele = browser.find_element(By.ID, 'kw') act.context_click(ele).perform() 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

 
双击

from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.common.action_chains import ActionChains

browser = webdriver.Chrome() browser.get('https://www.baidu.com') act = ActionChains(browser) ele = browser.find_element(By.ID, 'kw') act.double_click(ele).perform() 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

 
拖拽元素至另一个元素处,ele_a 为source,ele_b 为target

from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.common.action_chains import ActionChains

browser = webdriver.Chrome() browser.get('https://www.baidu.com') act = ActionChains(browser) ele_a = browser.find_element(By.ID, 'btn_a') ele_b = browser.find_element(By.ID, 'btn_b') act.drag_and_drop(ele_a, ele_b).perform() 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

 
拖拽元素至指定位置后松开,元素后为x,y坐标值

from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.common.action_chains import ActionChains

browser = webdriver.Chrome() browser.get('https://www.baidu.com') act = ActionChains(browser) ele = browser.find_element(By.ID, 'btn_a') act.drag_and_drop_by_offset(ele, 200, 100).perform() 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

 
鼠标移动至指定元素

from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.common.action_chains import ActionChains

browser = webdriver.Chrome() browser.get('https://www.baidu.com') act = ActionChains(browser) ele = browser.find_element(By.ID, 'btn_a') act.move_to_element(ele).perform() 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

 
按下指定的键位(示例代码中是回车键)

from selenium import webdriver from selenium.webdriver.common.keys import Keys from selenium.webdriver.common.by import By from selenium.webdriver.common.action_chains import ActionChains

browser = webdriver.Chrome() browser.get('https://www.baidu.com') act = ActionChains(browser) ele = browser.find_element(By.ID, 'kw').send_keys('selenium') act.key_down(Keys.ENTER).perform() 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

 
松开指定的键位,这里也可以用链式写法

from selenium import webdriver from selenium.webdriver.common.keys import Keys from selenium.webdriver.common.by import By from selenium.webdriver.common.action_chains import ActionChains

browser = webdriver.Chrome() browser.get('https://www.baidu.com') act = ActionChains(browser) ele = browser.find_element(By.ID, 'kw').send_keys('selenium') act.key_down(Keys.ENTER) act.key_up(Keys.ENTER) # 链式写法 act.key_down(Keys.ENTER).act.key_up(Keys.ENTER).perform() 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

 
移动鼠标到指定坐标位置

from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.common.action_chains import ActionChains

browser = webdriver.Chrome() browser.get('https://www.baidu.com') act = ActionChains(browser) ele = browser.find_element(By.ID, 'kw').send_keys('selenium') act.move_by_offset(100, 200).perform() 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

 
移动到距离指定元素多少距离的位置(从左上角0, 0开始计算)

from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.common.action_chains import ActionChains

browser = webdriver.Chrome() browser.get('https://www.baidu.com') act = ActionChains(browser) ele = browser.find_element(By.ID, 'kw').send_keys('selenium') act.move_to_element_with_offset(ele, 100, 200).perform() 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

 
在指定元素位置松开鼠标

from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.common.action_chains import ActionChains

browser = webdriver.Chrome() browser.get('https://www.baidu.com') act = ActionChains(browser) ele = browser.find_element(By.ID, 'kw').send_keys('selenium') act.click_and_hold(ele).release(ele).perform() 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

 
发送指定的键或者内容至指定元素

from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.common.action_chains import ActionChains

browser = webdriver.Chrome() browser.get('https://www.baidu.com') act = ActionChains(browser) ele = browser.find_element(By.ID, 'kw').send_keys('selenium') act.send_keys_to_element(ele, 'selenium').perform() 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

 
暂停所有操作,默认单位为秒

from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.common.action_chains import ActionChains

browser = webdriver.Chrome() browser.get('https://www.baidu.com') act = ActionChains(browser) ele = browser.find_element(By.ID, 'kw').send_keys('selenium') act.context_click(ele).pause(5).double_click(ele).perform() 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

 
 

5.8 组件操作

页面中也存在着很多不同种类的组件,比如单选框、多选框、下拉列表、选项卡等。这些操作也可以通过selenium提供的函数进行实现。

 
清除指定元素中的内容(输入框等)

from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.common.action_chains import ActionChains from time import sleep

browser = webdriver.Chrome() browser.get('https://www.baidu.com') act = ActionChains(browser) ele = browser.find_element(By.ID, 'kw') ele.send_keys('selenium') sleep(2) ele.clear() 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

 
提交确认(类似于Keys.ENTER的效果)

from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.common.action_chains import ActionChains from time import sleep

browser = webdriver.Chrome() browser.get('https://www.baidu.com') act = ActionChains(browser) ele = browser.find_element(By.ID, 'kw') ele.send_keys('selenium') sleep(2) ele.submit() 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

 
下拉列表,我们就可以使用Select方法来实现选取操作
使用Select方法需要从selenium.webdriver.support.select导入该方法
例如下图中某网站的下拉列表对象

在这里插入图片描述

 
html构造如下
在这里插入图片描述

 
select_by_index()方法

from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.select import Select

browser = webdriver.Chrome() browser.get('https://www.xxxx.com') ele = browser.find_element(By.ID, 'input_factor_gj_count') # 需要注意下标要从0开始,选择1%那一项 Select(ele).select_by_index('0') 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

 
select_by_value()方法

from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.select import Select

browser = webdriver.Chrome() browser.get('https://www.xxxx.com') ele = browser.find_element(By.ID, 'input_factor_gj_count') # 指定元素的value属性值,选择1%那一项 Select(ele).select_by_value('0.01') 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

 
select_by_value()方法

from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.select import Select

browser = webdriver.Chrome() browser.get('https://www.xxxx.com') ele = browser.find_element(By.ID, 'input_factor_gj_count') # 指定元素的文本值,选择1%那一项 Select(ele).select_by_visible_text('1%') 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

 
框架切换(Frame)
如果在页面中定位某一个元素失败并检查其属性并没有问题时,就该考虑是否在祖先节点中是否存在frame或者iframe标签。这样的页面就表名存在多层框架嵌套,这时我们就需要进行框架切换的操作,来准确定位到指定元素。

例如某页面存在两层frame嵌套,内部框架的xpath为://*[@id="mainDiv"]/iframe,此时如果定位某个输入框失败之后,我们就应该转而跳入该frame内进行元素定位。
 

from selenium import webdriver from selenium.webdriver.common.by import By

browser = webdriver.Chrome() browser.get('https://www.xxxx.com') # 定位到指定的frame path = browser.find_element(By.XPATH, '//*[@id="mainDiv"]/iframe') # 切换至该frame内 browser.switch_to_frame(path) ele = browser.find_element(By.CLASS_NAME, 'input') ele.send_keys('selenium') 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

 
标签页切换
我们浏览器在使用中一般会打开多个浏览窗口,也就是多个标签页。此时我们就可以通过每个标签页的句柄来进行定位和互相切换。

switch_to_window()
我们利用浏览器窗口的句柄来进行标签页的切换

from selenium import webdriver from selenium.webdriver.common.by import By

browser = webdriver.Chrome() browser.get('https://www.baidu.com') # 第一个窗口的句柄下标为0,打开第二个就是1 browser.switch_to_window(browser.window_handles[1]) # 此时就会使用第二个标签页去访问淘宝 browser.get('https://www.taobao.com') 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

 
弹窗处理
页面中时常也存在着各类的弹窗,比如警告、确认、提示等等,那么对于这些弹窗我们也有着相应的业务处理方法。
 
首先我们需要明确的是每种类型的弹窗中元素也是各不相同,所以我们针对不同的弹窗使用不同的属性来定位和操作。

 
警告弹窗
一般来说就是告知到使用者执行某些操作与页面之后将要注意的事项,这种窗口只需确认。

from time import sleep from selenium import webdriver from selenium.webdriver.common.by import By

browser = webdriver.Chrome() browser.get('https://www.xxxx.com') browser.find_element(By.ID, 'btn_tg_title').click() sleep(1) # 在警告弹窗中点击确认按钮 browser.switch_to_alert().accept() 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

 
确认弹窗
多用于在用户执行提交操作后的动作确认,有确认和取消两个选项。

from time import sleep from selenium import webdriver from selenium.webdriver.common.by import By

browser = webdriver.Chrome() browser.get('https://www.xxxx.com') browser.find_element(By.ID, 'btn_submit').click() sleep(1) #确认二选一 browser.switch_to_alert().accept() #取消二选一 browser.switch_to_alert().dismiss() 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

 
提示弹窗
这个通常用来处理用户信息交互的场景,用户可以通过弹窗输入一些文字信息,来传递与进行后续的业务处理。

from time import sleep from selenium import webdriver from selenium.webdriver.common.by import By

browser = webdriver.Chrome() browser.get('https://www.xxxx.com') browser.find_element(By.ID, 'btn_info_inquiry').click() sleep(1) # 这里传递信息到提示弹窗,警告与确认两类弹窗不可使用,会报错 browser.switch_to_alert().send_keys('20100909') 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

 
 

5.9 鉴权操作

既然是web自动化测试,那我们又怎么能少了Cookie的相关操作呢?用户的状态和业务请求都的需要用他来进行鉴权。在selenium中对Cookie进行操作其实也很简单,首先我们需要手动的登录被测网站一次,待网站Cookie存入本地后即可使用Selenium自带的函数对齐进行业务操作。

 
首先我们获取对应网站的Cookie值

import json from selenium import webdriver

browser = webdriver.Chrome() browser.get('https://www.baidu.com') # 写入保存为文件还是直接打印至控制台,各取所需 with open('cookies.txt', 'w') as f: f.write(json.dumps(browser.get_cookies())) cookies = browser.get_cookies() print(cookies) 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

 
接下来我们简单的对获得的Cookie进行处理

# 删除所有的cookies browser.delete_all_cookies() # 循环打印cookie中的name和value for c in cookies: # 查看打印出的cookie对应的键值对 print("%s : %s" % (c['name'], c['value'])) # 根据自己的业务需求进行cookie的增删改 cookie = {"name": "xxxx", "value": "xxxx"} # 最后添加即可 driver.add_cookie(cookie) 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

 
 

5.9 js操作

Selenium也为我们提供了可执行js脚本相关的函数,他们的作用是在某些页面中模拟一些业务动作(画面滑动,选择日期等)。在一些仅靠webdriver无法实现的业务场景中,我们就可以依靠此函数来辅助测试目的的达成。

 

js的查找元素方法(ID)

document.getElementById("id") 
  • 1

 
js的查找元素方法(name)

document.getElementsByName('name') 
  • 1

 
js的查找元素方法(class)

document.getElementsByClassName("class_name") 
  • 1

 
js的查找元素方法(tag)

document.getElementsByTagName('tag_name') 
  • 1

 
js的查找元素方法(css)

document.querySelector("css selector") 
  • 1

 
js的查找元素方法(css_list)

document.querySelectorAll("css selector") 
  • 1

 
execute_script()
从上可以看出其实js的定位元素方法和selenium中的差不多,接下来我们就可以将需要执行的js语句放入到执行函数中使用。

from selenium import webdriver

browser = webdriver.Chrome() browser.get('https://www.baidu.com') # 定位后修改指定元素的value属性 js_script_exec = 'document.getElementById("form_motion").value="list_modify";' browser.execute_script(js_script_exec) 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

 
 

6. 注意点与小技巧

  1. 对于某些动态div标签(窗口),一般的方法不太奏效的情况下,可以尝试下switch_to_default_content()方法,跳转到最外层;

  2. 使用模拟键鼠操作的时候,无论是单独使用还是链式写法,记得在结尾加上perform()方法进行执行;

  3. 如果元素定位时报错element click intercepted,记得检查界面上是否有其他元素进行覆盖,元素有可能也是具有隐藏属性的;

  4. 元素过期报错element is not attached to the page document,可以尝试重新刷新页面,这里不推荐直接使用refresh方法,还是养成好习惯先怼上try…except…捕捉到异常后在进行刷新或重置操作;

  5. 对于属性值为动态的元素,墙裂推荐使用CSS selector或者xpath方法来进行元素定位,正则表达式也推荐大家最好能掌握;

  6. 如果前期对xpath的相对路径写法比较头疼,推荐使用F12调试工具自带的元素复制功能,在你想要复制的元素所在的标签对这行右键,选择copy —— Copy XPath选项即可;

  7. 输入框默认存在内容想要删除再输入信息的话,不推荐模拟键盘操作Ctrl+A,然后模拟退格键,试试clear()方法吧;

  8. 抓不到元素可以使用延时方法,输入文字也是一样的道理,业务场景中需要大量输入文字的,无论是从文件中还是提取又或者是遍历,出现少字漏字的话,同样也可以使用延时的方法,适当的放慢处理的速度;

  9. 在页面中总会有些不可见的元素,这种情况使用is_displayed()方法即可快速定位找到;

  10. 有些被测页面需要验证码,无论是手机的还是图片验证,和开发同学沟通一下,留个万能的就行了,其本身的功能手工回归一下即可,不必太过纠结;

  11. 三方登录功能也是如此,不推荐直接使用web自动化去搞,三方的一般是不开源的,有这折腾的时间还不如跑跑接口和黑盒,自动化的话绕过去即可;

  12. 自动化测试用例这块的话博主还是推荐不要有依赖,和功能测试用例同理,每次的执行顺序或者数量都会根据需求与业务场景发生变化,一旦依赖了会大大增加测试同学的维护成本,后面有空我会单独出一期自动化测试用例的文章来为大家介绍。




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


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


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

2023年前端开发趋势未来可期

前端达人

目录

一、企业内前端开发比重

        1、目前学校教课的种类多样

        2、目前服务端语言多样

        3、企业中前端开发占比

二、目前业内更受欢迎的开发语言

        1、过去一直到今年的开发语言排名

        2、那么未来呢

三、近期CSDN问答的前端活跃度

        1、近期CSDN问答模块活跃度

        2、活跃度能说明什么

四、前端开发都做什么?

        1、这个问题需要想吗?

        2、日常工作是什么?

        3、还做什么?

        4、想想,还能做什么?

        5、有点理想好不好

五、给初学者的建议

        1、坚定信心

        2、是否要去培训机构

        3、学习之余的巩固

        4、赢在实战

         5、知识点的举一反三


一、企业内前端开发比重

        1、目前学校教课的种类多样

        搞明白前端开发人员在企业中的占比,你才可以在学校或者即将毕业的时候选择出自己将要深入学习的开发语言。很多学校既要教C语言,又教单片机,既教java,也教前端开发知识,但老师的课是有限的,给留了作业,也许都不检查,下一课老师就要继续往下讲,因为这是他的工作,老师们也有生活,不可能围着某些人转,学不会就不往下开课了。

        而搞懂前端开发在企业中的占比呢,能够更好的让你觉得如果自己比较平凡,得到什么等级可以卷得过别人,可以在这么多职位中占有一席之地。

        2、目前服务端语言多样

        很可喜的是,目前传统行业已经信息化改造完成,不管他们是内部系统,或者外部联合系统,都需要前端开发;我们每天看见大街上跑的汽车企业,某些电子企业,手机厂商,都需要前端开发的职位;更别提电商,直播这些我们生活所不可缺少的行业。但你还需要知道的是,如果你想学的一门服务端语言,java phython .net 或者其他,很可能这家公司就不会用,无形中给自己减少了很多工作机会。

        3、企业中前端开发占比

        22461dbde9ea4dc498d3d9891179c32b.png

         0f9b7c29c5c843f1a21abaed4cb8a62d.png

 6d52958d5b544d1b96016c2ff16d461c.png

         以上的图,是从过去几年一直到今年(2022)年的各大公司的占比,毕竟是大厂嘛,对用户体验,前端接触到浏览器,最接近用户的要求肯定会高一些。

        但是通过对多家中小公司的逐步了解发现,出去UI , 项目,产品,DBA, 运维等职位外,服务端开发与前端开发的比例几乎是1:1 ,甚至有的外包性质的公司,他们一旦产品成型后,新的客户换皮肤,更换界面的需求会更多,所以前端开发会需求更多一些。

        

二、目前业内更受欢迎的开发语言

        此前有人戏称,是开发语言受欢迎,并非你受欢迎。但不得不说,某个开发语言受欢迎程度如果更加靠前,说明市场需求更大,更受欢迎,而将来准备从事某一种开发语言,也是非常关键的信息来源。

        1、过去一直到今年的开发语言排名

        e783b4646959444288fc376d85c26ade.png

           5d6915e57ffa4373b9cb338d060d1189.png

                 b43001039ca947cebc1490386fee2d6d.png

                 21f4406245374b54af5292de10b73370.png

 21a7ead82dc844afac42a26d86b44875.png

        通过以上往年到今年的开发语言受欢迎程度发现,javascript这门前端必备的开发语言名列前茅,甚至在众多服务端开发语言中也不甘示弱,当然这之中并没有表明HTML CSS是一门开发语言,如果是的话,HTML CSS 也必将榜上有名,因为各行各业都不要网页对外公式自己的产品,但服务端开发语言五花八门,而前端必备javascript。

        2、那么未来呢

        从web1.0时代,页面简单的只读时代,到web2.0时代,不断的交互,前端开发这个职位也在不断的进步。那么在未来的web3.0时代,很多人疑惑,可能PC的网页用处会越来越少,甚至不客气的说H5的页面也会少很多,据推测APP也会减少,未来将会有更多的数据整合产品出现。那么未来前端还会大有可为吗?

        答案是肯定的,伟大的《红宝书》开头便说:javascript能做所有的事情,如果他能。而且nodejs的流行,也使前端可以更多的渗透到服务端开发,flutter的最新发布,WPA的使用,也使APP得到了更大的挑战,CSS3的不断进步,前端游戏引擎的盛行,也使前端有了更大的发展前景与选择,那么即便未来的元宇宙世界,相信前端javascript也一定能够勇往直前

三、近期CSDN问答的前端活跃度

        1、近期CSDN问答模块活跃度

9f27329550154ebbb6b12739237dad6a.png

be63ffd41bef4ec782c645b847b5fdc4.png

         如果这只是当下技术领域的一个缩影,可见比较活跃的的开发语言有java phython c mysql 然后才是javascript。从开发开发技术职位区分还是服务端和前端,但前端活跃度却比较靠后,不管是提问,回答,数量等维度上

        2、活跃度能说明什么

        说明什么问题呢?从事前端开发人数少吗?前端开发在学习,工作中没有问题吗?前端开发比较懒惰,不愿意上社区来参与活动吗?

        我们知道nodejs可以做服务端开发,但是有多少企业敢于让从开始就搭上node serve的架子,不断让前端同学去尝试,不断在node领域发光发热,为整个行业添砖加瓦呢,很少吧。而几乎大部分公司,还是比较守旧的,从最开始的jSP时代,甚至不需要前端,服务端写完服务端代码,然后开始写JSP。JSP里再套java代码,顺带着添加一些javascript事件,样式怎么办,那个时候extjs jquery还非常盛行,easyui jqueryui 等,可以让服务端开发人员快速生产页面。

        但随着提升用户体验的欲望越来越强烈,《国富论》开篇也讲分工带来的好处,前端才逐渐有了一席之地,甚至在一些大公司,前端的话语权可以超越服务端,他们通过技术驱动业务向前。

        按照比例学可知,一旦某些事物达到一个数量后,某些细节世界也可以大体展现整体的宏观判断。那么我的理解是,在众多开发语言中,尽管javascript那么受欢迎,目前企业中前端占比还算不错,但总的来说,跟其他服务端开发语言总和来比,前端人员还是少。如果服务端语言像前端一样仅有javascript的话,我相信csdn问答模块这个业界缩影将不会是这种状态,甚至会大有不同。

四、前端开发都做什么?

        1、这个问题需要想吗?

         其实很多老师,很多培训机构的老师教前端,大家各有各自的工作,各有各自的生活, 他知道来了一批学生,这是自己分内的工作,其实很多学生也只是停留在前端开发做网页的意识上,未来我想找到一份共走,可以养活自己。这无可厚非

        2、日常工作是什么?

        其实日产工作还真就是做网页,做了C端做B端,做了PC做H5,嵌套到webview里,嵌套的APP的壳子里,这些都是工作。

        小程序,各种各样的小程序;各种手机屏幕尺寸的适配;各种APP内部的嵌套;

        做完了前端,开发点node层的工作吧,卷一卷,棒服务端同学减轻点工作压力;

        3、还做什么?

        再来点代码优化吧,如果将自己的代码调的代码量更少,如何不写注释也可以清晰明了,如何不得不写注释,可以写的更清楚;

        来一点性能优化吧,现在出去面试,没做过性能优化都不好意思说自己做过工作。没办法,整体的需求缠身,但你却很少从中吸取知识,日复一日,到找工作那天发现,自己做的工作,其实都是劳动力。如何驱动自己,再寻求解决方案,再将性能指标不断提升。

        4、想想,还能做什么?

        卷一卷,读书破万卷。将自己的点子,自己的做法不断形成方法论,对内输出,乃至对外输出,提升影响力。

        5、有点理想好不好

          还要啥理想,向公共组件团队渗透,向技术栈所在团队渗透?

       

        小插曲:这里加一个小插曲,promise解决了什么问题?这道题是不是必考题,千篇一律的答案是什么?解决了回调地狱?异步的工作我们当同步的来执行?

        这算不算进步?这算不算创新?那么我就问问你,有回调地狱你的项目跑步起来了?用同步的写法来搞异步的事情降本增效了?

        那么我就问问你,是你把之前的写法用上现在的promise节省的时间多,还是你每天摸鱼的时间多。说白了异步是一个需要花费时间的事情,因为有了异步,有了时间差,才使我们的工作出现了更多的可能性,不确定性。你更应该解决的是不是这个问题。

        个人观点啊,没说promise不好,挺好的。

五、给初学者的建议

        1、坚定信心

        不管是在校或者迷茫的即将离校,一旦决定要学,不管是学哪种开发语言,都要坚定信心,切记不可三天打鱼,两天晒网;

        2、是否要去培训机构

        这要看个人家庭的生活水平,一个家庭攻读出一个大学生实属不易,毕业后念培训班需要一定的资本支持。但对于很多人来说,没有学习方向,念培训班也是个选择,至少可以入个门;但大部分的培训课程对于目前的就业形势掌握不足,就像杨过刚去钟南山一样,练不够基本功,词汇一大堆,实战没多少,最后说啥名词都是666,一干活就挠头;

        其实我根据自己的经验,也在筹备规划一套更卷,更适合入门到守门再到卸门的课程,我的目标就是更实用,更卷,更有助于大多数想学习的同学们,你需要的只是一句:我想学习,我要学习,我能学习,而不是马内。

        3、学习之余的巩固

        现在网络上文章多的是,虽然很多不够系统,但正好够大家巩固当日知识点所用。学一定要用,用后一定要巩固,巩固后一定要举一反三形成自己的知识点,方法论,记录个博客啦,笔记啦,分享到身边的人,这样足可巩固无忧

        4、赢在实战

        知识点掌握的好不叫好,可以把知识点贯穿起来,做出一个市面上的东西,这算超越自我,切记不可自满,学完知识点就说自己精通,那只会在面试或者在工作的时候让自己更加烦恼,掉头发,熬夜。

         5、知识点的举一反三

        做为初级开发,最重要的就是对于解决问题,有自己的一套手段,这样至少可以保证快速的完成需求。但如果想继续往上走,必须得有一些别人所没有的东西。这里说到举一反三,记得当时学习的时候,学完js基础需要写一个99乘法表,当时本来上课就少,硬生生把js的嵌套循环99乘法表写出来。晚上睡觉的时候想,如果纯用HTML CSS 是不是也能写出来,就这样,HTML的倒是好写,但CSS的又憋了很久,总算是写出来了。你就说,这样下去,谁能有我卷。现在我总结出了怎么利用纯HTML CSS JS 写出3版99乘法表,并且总结出了自己的文章,希望可以让初学者能够更快的入门。




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


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


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

是什么让学习 Web 开发在未来几年变得有价值?

前端达人

什么是网页开发?

Web 开发是指在互联网上创建网站或 Web 应用程序。它涉及一系列任务,从开发网站的整体结构和设计到编写使网站栩栩如生的代码。Web 开发可能是一个复杂的过程,它通常涉及使用各种不同的技术,包括 HTML、CSS 和 JavaScript,以及服务器端语言,如 PHP、Ruby、Nodejs 和 Python。Web 开发人员可能在前端工作网站的一部分,这是用户与之交互的部分,或者在后端,这是处理网站幕后功能的部分。Web 开发是一个快速发展的领域,Web 开发人员需要跟上最新的技术和最佳实践,才能创建有效且引人入胜的网站和 Web 应用程序。

在这里插入图片描述

Web 开发领域的未来是什么样的?

可以肯定地说,Web 开发将继续是一个重要且充满活力的领域。随着 Internet 的不断发展和演变,对 Web 开发人员的需求也可能会增加。Web 开发中使用的技术和工具也将继续发展和改进,这将使 Web 开发人员能够创建更先进、更复杂的网站和应用程序。此外,人工智能、虚拟现实和增强现实以及物联网等新技术的兴起可能会为网络开发人员带来新的机遇和挑战。Web 开发的未来看起来一片光明,对于那些对技术充满热情的人来说,它将继续是一个令人兴奋和有益的领域。

现在是成为 Web 开发人员的好时机吗?

Web 开发是一个快速发展和动态的领域,由于 Web 应用程序开发的复杂性和多样性不断增加,因此对 Web 开发人员的需求量很大。

Web 开发人员有什么好的工作机会吗?答案是肯定的。互联网改变了我们的生活方式。如果您想加入一个令人兴奋的新行业来开发新技术,我们建议您这样做并成为一名网络开发人员。该技术不仅“防 covid”,而且相对抗衰退。

人们每天都越来越多地参与网络,并使用他们的智能手机和平板电脑访问互联网,因此对于网络开发人员来说,创建针对这些智能设备优化的网站和网络应用程序非常重要。

对于网站和应用程序而言,提供用户会喜欢的令人难忘的用户体验将变得更加重要。具有提供引人入胜的用户体验天赋的开发人员应该研究这些趋势带来的机会。

总之,每项 Web 技术的背后都有一支经验丰富、才华横溢的开发人员团队,他们负责更新、开发和维护它。技术每天都在发展,因此有才华的 Web 开发人员始终可用并存在非常重要。

在这里插入图片描述

网页设计和网页开发有何不同?

网页开发和网页设计是两个经常混淆的独立领域。虽然它们是相关的,但它们是具有不同重点和目标的不同学科。

网页设计侧重于网站的美学和功能方面,涉及用户界面和用户体验的规划和创建。网页设计师负责网站的布局、配色方案和整体外观,以及网站的导航和用户流程。

另一方面,Web 开发侧重于构建网站的技术方面。这包括编写代码来创建网站的各种组件,例如前端和后端,并将它们集成以创建功能强大且可用的网站。Web 开发人员负责网站的实施和维护,并且可能会使用各种编程技能和框架来实现。

Web 开发人员是专门开发可通过 Web 浏览器访问 Internet 的应用程序和服务的程序员。Web 开发人员使用各种技术和语言(例如 HTML、CSS 和 JavaScript)来创建网站或 Web 应用程序的结构、布局和设计。

Web 开发人员负责构建和维护 Web 应用程序的各种组件,包括用户界面、服务器端逻辑和数据库。他们还可能负责将 Web 应用程序与其他系统和 API 集成,并负责实现增强用户体验的特性和功能。

总之,网页设计关注网站的视觉和面向用户的方面,而网页开发则关注网站的技术实现和功能。

在这里插入图片描述

网络开发人员做什么的?

前端网页开发

前端开发人员是专门从事 Web 开发客户端的 Web 开发人员。他们负责构建和维护 Web 应用程序的用户界面和用户体验,包括布局、设计和交互性。

前端开发人员通常精通前端技术和语言,例如 HTML、CSS 和 JavaScript。他们负责实施 Web 应用程序的视觉设计,包括布局、排版和配色方案。他们还可能负责实现交互元素,例如按钮、表单和菜单,以及将 Web 应用程序与后端系统和 API 集成。

除了技术技能,前端开发人员还需要对用户体验和设计原则有深刻的理解。他们应该能够创建直观、用户友好且美观的 Web 应用程序。

前端开发是 Web 开发的重要组成部分,前端开发人员在创建 Web 应用程序的外观方面发挥着关键作用。

后端网页开发

后端开发人员是专门从事 Web 开发服务器端的 Web 开发人员。他们负责构建和维护 Web 应用程序的底层逻辑和基础设施,包括服务器端逻辑、数据库和 API。

后端开发人员通常具有服务器端语言和技术方面的专业知识,例如 PHP、Python、Ruby 和 Node.js。他们负责实现 Web 应用程序的服务器端逻辑,包括业务规则、数据验证和用户身份验证。他们还可能负责设计和实施数据库模式,以及将 Web 应用程序与其他系统和 API 集成。

除了技术技能,后端开发人员还需要具备强大的问题解决、沟通和协作能力。他们应该能够批判性和逻辑性地思考,并能够设计和实施可扩展、可维护且高效的解决方案。

后端开发是 Web 开发的重要组成部分,后端开发人员在构建和维护 Web 应用程序的功能和性能方面发挥着关键作用。

全栈网页开发

全栈开发人员是在前端和后端开发方面都具有专业知识的 Web 开发人员。他们负责构建和维护整个 Web 应用程序,从用户界面和用户体验到底层服务器端逻辑和数据库。

全栈开发人员通常对用于构建 Web 应用程序的技术和语言有深入的了解,包括 HTML、CSS、JavaScript 和服务器端语言(如 PHP、Python 和 Ruby)。他们能够处理 Web 应用程序的所有层,从用户界面和用户体验到数据库和服务器端逻辑。

除了技术技能,全栈开发人员还需要具备强大的问题解决、沟通和协作能力。他们应该能够创造性和批判性地思考,并能够适应不断变化的技术和要求。

全栈开发是一个充满挑战和回报的领域,由于 Web 应用程序的复杂性和多样性不断增加,对全栈开发人员的需求量很大。

站长

网站管理员负责构建、维护和更新网站。他们还可能负责将网站与其他系统或云服务集成,例如数据库和内容管理系统 (CMS),以及实施增强用户体验的特性和功能。

网站管理员通常与开发团队的其他成员(包括图形设计师、内容创建者和项目经理)密切合作,以创建和维护满足企业或组织需求的网站。他们还可以与客户合作以了解他们的要求并提供满足他们需求的解决方案。

从哪里开始,第一步是什么?

如果你是 Web 开发的新手并且想知道从哪里开始以及第一步是什么,这里有一些建议:

学习 HTML 和 CSS 等 Web 开发基础知识——这些是 Web 的核心技术,良好的这些语言基础对于任何 Web 开发人员来说都是必不可少的。您可以从学习 HTML 和 CSS 的基础知识开始,例如网页的结构、如何添加内容和样式以及如何创建简单的静态网页。

选择开发环境——开发环境是一组用于构建和测试 Web 应用程序的工具和资源。这通常包括用于编写代码的文本编辑器或集成开发环境 (IDE)、用于测试网页的 Web 浏览器以及用于运行 Web 应用程序的本地 Web 服务器。带有大量插件的 vscode 编辑器肯定需要引起您的注意。

构建一个简单的网页——学习了 HTML 和 CSS 的基础知识后,尝试构建一个包含一些文本、图像和基本样式的简单网页。这将使您有机会练习所学的技能,并了解不同技术如何协同工作。然后更进一步,开始复制一些最流行的网络应用程序,然后 memic 尝试重新创建它,我指的只是这里的设计。

探索 Web 开发框架和库– 有许多可用的 Web 开发框架和库可以更轻松地构建 Web 应用程序。一些流行的选项包括 React、Angular、Vue.js 和 Django。一旦你确定了一个框架,立即开始学习它并坚持下去直到你掌握它。

在这里插入图片描述

学习基础知识

HTML或超文本标记语言是一种用于创建和构建网页内容的编程语言。HTML使用一系列元素或标签来定义网页的结构和布局,包括标题、段落、列表和链接。HTML 还允许开发人员向网页添加图像、视频和其他多媒体内容,使其成为构建 Web 应用程序的强大且通用的语言。

定义带有标题、段落和图像的简单网页的 HTML 代码:

<!DOCTYPE html> <html> <head> <title>我的 Web 页面</title> </head> <body> <h1>Hello, World!</h1> <p>这是我的第一个 Web 页面</p> <img src="https://www.example.com/image.jpg" alt="A beautiful landscape"> </body> </html> 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

在此示例中,<html><body>标签定义了网页的结构,而<h1><p><img>标签定义了页面的内容。<img>标签的src属性指定要显示的图像的 URL,而alt属性为无法看到图像的用户提供图像的文本描述。所以你需要了解 HTML 标签和它们的属性。

CSS或层叠样式表是一种样式表语言,用于描述以标记语言编写的文档的外观和格式。在 Web 开发环境中,CSS 用于控制以 HTML 或其他标记语言编写的网页的外观和布局。CSS 允许开发人员为网页上的内容定义颜色、字体、大小和其他样式,使其成为构建现代响应式 Web 应用程序的重要组成部分。

可用于设置上述网页内容样式的 CSS 代码:

body { font-family: Arial, sans-serif; background-color: #f1f1f1; } h1 { color: #333; text-align: center; margin: 30px 0; } p { color: #777; font-size: 18px; line-height: 1.5; padding: 0 20px; } img { width: 100%; height: auto; } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

在此示例中,body选择器将样式应用于网页的<body>元素, h1选择器将样式应用于所有<h1>元素,p和img选择器将样式应用于所有<p><img>元素, 分别。此 CSS 代码中定义的样式指定页面及其元素的字体系列、背景颜色、文本对齐方式和其他属性。显示此示例演示了选择 HTML 元素的重要性以及需要使用哪些属性来设置它的样式。因此,了解所有类型的选择器以及它们需要的属性。

你可以使用 CSS 框架让您的生活更轻松。最受欢迎的是Bootstrap和Tailwind CSS,它们都是用于构建响应式、移动优先的 Web 应用程序的前端框架。这两个框架都提供了一组预定义的 CSS 类和组件,可以轻松地将它们合并到网页中,以创建一致的、具有专业外观的设计。Bootstrap 和 Tailwind CSS 是构建现代响应式 Web 应用程序的强大工具。这两个框架之间的选择将取决于您的个人喜好和项目的具体需求。

最流行的框架

有许多不同的框架可用于 Web 开发,每个框架的流行程度取决于项目的具体需求以及开发人员、团队或公司的偏好。一些最流行的 Web 开发框架包括:

React: React 是用于构建用户界面的最多的javascript 框架之一。 许多公司都在使用它,并且拥有庞大的开发人员社区。

Angular: Angular 是一个基于 TypeScript 的开源 Web 应用程序框架,由 Google 的 Angular 团队以及个人和公司社区领导。

Vue.js: Vue.js 是一个用于构建用户界面的渐进式 JavaScript 框架。它旨在逐步采用并可以集成到现有项目中。

Ember.js: Ember.js 是一个用于构建大型 Web 应用程序的开源 JavaScript Web 框架。它以其约定优于配置方法和强调开发人员生产力而闻名。

10 种最流行的 Web 开发编程语言

以下编程语言列表可帮助您了解在成为 Web 开发人员的过程中您想要学习和追求的语言。大多数时候,选择将取决于您选择的框架或其他方式:

JavaScript——让我们从显而易见的最流行的 Web 开发编程语言开始,它是 JavaScript,它是一种用于构建前端 Web 应用程序的通用语言。它是一种客户端语言,这意味着它在用户的网络浏览器中运行,并允许开发人员创建交互式和动态网页。JavaScript 还通过 Node.js 等技术用于服务器端开发,它允许开发人员构建可扩展的高性能 Web 应用程序。

Python – Python 是一种高级解释型编程语言,广泛用于 Web 开发。它具有简单易学的语法,是初学者的绝佳选择。Python 还以其强大的库和框架而闻名,例如 Flask 和 Django,这使得快速构建复杂的 Web 应用程序变得容易。

Java – Java 是一种流行的面向对象的编程语言,广泛用于构建可扩展的高性能 Web 应用程序。它是一种通用语言,可用于为各种平台(包括桌面、移动和 Web)构建 Web 应用程序。

Ruby – Ruby 是一种高级解释型编程语言,通常用于 Web 开发。它以简单和优雅着称,使其成为想要快速轻松地构建 Web 应用程序的开发人员的热门选择。

PHP – PHP 是一种流行的脚本语言,广泛用于构建动态网站和 Web 应用程序。它是一种服务器端语言,这意味着它在网络服务器上运行并生成发送到用户网络浏览器的 HTML 页面。

C# – C# 是一种流行的面向对象的编程语言,通常用于构建 Web 应用程序。它是一种通用语言,可用于为各种平台(包括桌面、移动和 Web)构建 Web 应用程序。

Swift – Swift 是一种现代的编译型编程语言,通常用于构建 Web 应用程序。它是一种功能强大的语言,以其安全性和性能着称,使其成为构建需要处理大量数据或执行复杂计算的 Web 应用程序的绝佳选择。

Go – Go 是一种现代的编译型编程语言,通常用于构建 Web 应用程序。它是一种快速、高效的语言,以并发性和可扩展性着称,使其成为构建需要处理大量流量或数据的 Web 应用程序的绝佳选择。

TypeScript – TypeScript 是一种流行的类型化编程语言,通常用于构建大型、复杂的 Web 应用程序。它是 JavaScript 的超集,这意味着它包含 JavaScript 的所有功能,以及可以更轻松地构建大型、可维护的 Web 应用程序的附加功能。

Kotlin – Kotlin 是一种现代的编译型编程语言,通常用于构建 Web 应用程序。它是一种简洁、强大的语言,以其安全性和与 Java 的互操作性而著称,使其成为构建需要与现有 Java 代码集成的 Web 应用程序的绝佳选择。

Web开发是一个好职业吗?

追求网络开发职业道路可能是一个不错的选择,原因有很多。Web 开发职业的一些好处包括:

对 Web 开发人员的高需求:对 Web 开发人员的需求一直很高,并且预计在未来几年将继续增长。这意味着那些拥有技能和经验的人将有很多机会在这个领域取得成功。

高薪: Web 开发人员的薪水很高,薪水因经验、地点和其他因素而异。总的来说,Web 开发人员可以期望获得丰厚的薪水,并且成长和进步的潜力很大。

灵活性: Web 开发可以在工作地点和日程安排方面提供很大的灵活性。许多 Web 开发人员远程工作,并且能够设置自己的时间并按照灵活的时间表工作。

学习和成长的机会: Web 开发是一个不断变化的领域,新技术和工具不断涌现。这意味着作为 Web 开发人员,始终有学习和成长的机会,并保持在行业的前沿。

创造有形事物的满足感:作为一名 Web 开发人员,您将有机会创造有形且有用的事物。这可以令人难以置信地满足,并且可以为您的工作提供成就感和自豪感。

Web开发的未来范围

Web 开发的未来看起来一片光明,许多激动人心的发展和趋势即将出现。一些可能影响 Web 开发未来的最新 Web 开发趋势包括:

  • 人工智能和机器学习的兴起:人工智能和机器学习在网络开发中变得越来越重要,出现了许多新的工具和框架来帮助开发人员构建人工智能驱动的应用程序。

  • 物联网的发展:物联网 (IoT) 是一个由可以收集和共享数据的连接设备组成的网络,预计在未来几年将显着增长。这将为网络开发人员创造新的机会来构建可以连接这些设备并与之交互的应用程序。

  • 移动设备的重要性日益增加:随着越来越多的人使用智能手机和其他移动设备访问网络,网络开发人员创建适合移动设备的应用程序和网站将变得越来越重要。

  • 渐进式 Web 应用程序的兴起:渐进式 Web 应用程序 (PWA) 是外观和感觉都像本机移动应用程序的 Web 应用程序,并且有望在未来变得更加流行。这将为 Web 开发人员创造新的机会来构建可跨不同设备和平台提供无缝用户体验的 PWA。

  • 云计算的发展:云计算在网络开发中变得越来越重要,许多公司将他们的应用程序和数据转移到云中。这将为 Web 开发人员创造新的机会来构建云原生应用程序并将它们与现有的云服务集成。

结论:

Web 开发仍然值得学习,因为它是构建和维护作为现代 Internet 支柱的网站和 Web 应用程序的基本技能。随着世界变得越来越紧密,对 Web 开发人员的需求不断增长,对于那些拥有构建和维护未来 Web 应用程序的技能和专业知识的人来说,有许多激动人心的机会。

Web 开发也是一个回报丰厚且具有挑战性的领域,它允许开发人员利用他们的创造力和解决问题的技能来构建供全球数百万人使用的应用程序。有了合适的工具和资源,任何人都可以学习 Web 开发并开始构建自己的 Web 应用程序,从而打开一个充满可能性和机遇的世界。


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


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


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

Vue.js 状态管理:Pinia 与 Vuex

前端达人

Vuex 和 Pinia 是用于管理 Vue.js 应用程序状态的标准 Vue.js 库。让我们比较一下他们的代码、语言、功能和社区支持。

如果没有合适的库,开发人员管理应用程序的状态可能会很困难。Vuex 和 Pinia 是标准的 Vue.js 库,用于处理应用程序中的条件。这两个库都非常适合状态管理,但是由于它们出色的特性和功能,选择哪个库用于你的项目需要时间并且令人沮丧。好吧,我们将在本文中看看为什么一个是最好的。

在本文中,我们将通过实际代码示例查看代码比较、它们的变体、功能,以及推荐使用哪一个来管理你的状态应用程序,以便更好地理解。我们还将考虑每个产品的语言、功能和社区支持。

Pinia 和 Vuex 简介

我将简要总结 Vuex 和 Pinia。如果你想要更详尽的解释,我建议阅读Vuex 文档和Pinia 文档。

什么是Pinia?

Pinia是一个新的状态管理库,可帮助你在 Vue.js 应用程序中跨组件管理和存储响应数据和状态。Pinia 由 Vue 核心团队成员之一 Eduardo San Martin Morote 创建。

Pinia 使用新的反应系统来构建一个直观且完全类型化的状态管理系统。

库中引入的新特性是促成 Pinia 推荐的因素之一。总体而言,Pinia 显得轻巧、简单且易于掌握。它拥有可以使 Vue 3 和 Vue 2 中的编程变得通用的一切。因此,这是试用 Pinia 的理想机会。

什么是 Vuex?

Vuex是一种状态管理模式和库,构建为集中式存储,可帮助你维护 Vue 应用程序中存在的所有组件的状态。Vuex 遵循确保你的状态突变为预测标准的规则。

使 Vuex 更强大的一个因素是组件从 Vuex store 中获取它们的状态,并且可以快速有效地响应 store 状态的变化。

Vuex虽然是维护你store的状态管理库,但建议你熟悉或搭建过大型SPA。如果你没有经验,Vuex 可能会冗长且令人生畏。

如果你的应用程序很广泛,你需要管理复杂的数据流,并且你有嵌套的组件,你可以使用 Vuex。查看官方文档以获取有关何时使用 Vuex 的更多信息。

Pinia 的特点

Pinia 和 Vuex 之间的区别之一是 Pinia 是“模块化设计”,换句话说,它被构建为拥有多个商店,而 Vuex 只有一个商店。在这些商店中,您可以拥有子模块。除此之外,Pinia 允许将这些模块中的每一个从他们的商店直接导入到需要的组件中。

模块化设计

如果您是一名 Vue 开发人员并且曾使用 Vuex 管理应用程序的状态,您会注意到 Vuex 只有一个商店。在该商店中,您可以在其中包含多个模块。使用 Pinia,您可以将这些模块中的每一个都存储在一个地方,并在需要时将它们直接导入到组件中。

此方法允许捆绑器自动对它们进行代码拆分,并提供更好的 TypeScript 推理。

完整的开发工具支持

Pinia 提供开发工具支持,以帮助您使用该库构建和轻松调试。当我们安装 Pinia 时,它会自动挂接到我们的 Vue.js 开发工具,并让我们跟踪对我们的商店所做的更改,这让我们在 Vue.js 版本(Vue 2 和 Vue3)中获得流畅的开发人员体验。

Pinia 很直观

Pinia 提供了一个简单的 API,使您的商店的编写变得简单且井井有条,就像创建组件一样。这意味着与 Vuex 解决方案相比,需要掌握的样板文件和概念更少。

Pinia 是可扩展的

Pinia 还提供了一个完整的插件系统,具有交易和本地存储同步等功能,适用于 Pinia 默认行为不足的情况。

TypeScript 支持

Pinia 提供比 Vuex 更好的 TypeScript 支持,具有 Javascript 自动完成功能,这使得开发过程变得简单。

Pinia 轻量的

Pinia 的重量只有 1 KB,因此很容易融入您的项目。这可能会提高您的应用程序性能。

Vuex的特点

模块

当您的应用程序扩展时,遍历变得很困难。但是,使用 Vuex 模块,您可以根据领域功能将您的商店拆分为多个文件,并从该特定命名空间中的模块访问状态循环。

开发工具支持

Vue devtools 中的 Vuex 选项卡允许我们查看状态并跟踪我们的变化。这使我们能够快速评估我们的程序如何执行和调试错误。

热重载

Vuex支持热重载功能,它使用 webpack 的热模块替换 API,可以在您开发时快速重载您的 mutations、modules、action 和 getters。

TypeScript 支持

如果你想编写一个 TypeScript 存储定义,Vuex 可以提供它的类型并且更容易实现。它有一个默认的 TypeScript 配置,不需要额外的设置。

Pinia和Vuex的代码对比

Pinia 是一个轻量级库,可帮助您管理整个应用程序的反应状态。与 Vuex 相比,Pinia API 易于学习,使您的代码更易于阅读。

让我们看一下使用 Pinia 和 Vuex 管理我们的状态的代码比较:

Vuex

在此示例中,我们将查看一个简单的 Vuex 存储,它跟踪待办事项列表项的状态:

import { createStore } from 'vuex' const TodoListstore = createStore({ state() { return { todoListItems: [] } }, actions: { addNewList({ commit }, item) { { commit('createNewItem', item) } }, mutations: { createNewItem(state, item) { state.todoListItems.push(item) } } }) 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

如果你看上面的代码,你可以看到 Vuex 存储中的三个动作:状态、 动作和突变。状态返回当前的todoListItems,动作提交一个突变来创建一个新项目,最后,突变创建新项目并将其添加到列表中。当你构建一个更大的应用程序时,你可能会意识到动作和突变相对相似,导致冗余代码,因为每个状态变化都需要一个样板。

Pinia

使用 Pinia 简单 API,您可以消除突变和冗余代码。让我们查看一个代码示例,了解当您使用 Pinia 实现之前的代码时的样子:

import { defineStore } from 'pinia' Export const useListStore = defineStore('list', { state() => ({ return { todoListItems: [] } }), actions: { addNewList() { this.todoListItems.push(item) } }}) 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

上面的示例是 Pinia API 在管理应用程序状态时如何工作的简单代码。使用 Pinia,我们删除了突变并将其直接更新到我们的动作中。

注意:在上面的代码示例中,当我们将项目直接提交给我们的操作时,我们不需要跟踪我们的项目。

Pinia 和 Vuex 的优缺点

Pinia 和 Vuex 是控制应用程序状态的优秀工具,但其中一个必须具有另一个所没有的某些功能。让我们来看看它们是什么。

Pinia 的优点

  • Pinia 允许你在不重新加载页面的情况下修改你的商店。
  • 它在 JavaScript 中提供 TypeScript 支持和良好的自动完成功能。
  • Pinia 提供 devtool 支持,这有助于增强开发人员使用该工具的体验。
  • Pinia 只有状态、吸气剂和动作。不需要突变。
  • 使用 Pinia,你可以将状态存储在一个地方,并在请求时将其传递给它们的组件。
  • 它是一个重量为 1 KB 的轻量级库。
  • 它提供服务器端渲染支持和自动类型模块,无需额外工作。
  • Pinia 兼容 Vue 2 和 Vue 3。

Pinia 的缺点

  • 与 Vuex 相比,它没有庞大的社区支持和解决方案。
  • Pinia 不支持调试功能,如时间旅行和编辑。

Vuex 的优点

  • Vuex 有 mutations、getters 和 actions。
  • 与 Pinia 相比,Vuex 的社区支持很大。
  • Vuex 支持调试功能,如时间旅行和编辑。

Vuex 的缺点

  • 它对 TypeScript 不友好。
  • 你只能将其用于大型 SPA。

我应该使用哪个:Pinia 还是 Vuex?

好吧,这就是它变得更具挑战性的地方,因为仍然有一些项目需要使用 Vuex 来处理状态应用程序,即使 Pinia 是新推荐的状态管理库。它有几个 Vuex 没有的有价值的功能。

Vuex 仍然是构建大型 SPA 的理想解决方案,因为对于构建中小型应用程序的人来说,它相当冗长。

Pinia 也一样。尽管如此,如果你需要所有列出的功能,例如 devtool 支持、TypeScript 支持和状态应用程序的轻松管理,那么 Pinia 是最好的解决方案——它为你提供流畅的开发体验。

如果你正在构建一个不太复杂的应用程序,无论是中等到广泛的应用程序,你都可以使用 Pinia,因为它的重量约为 1 KB。

结论

由于功能多样,在管理应用程序状态时,在 Vuex 和 Pinia 之间进行选择可能会造成混淆。不过,这两个框架都非常适合管理状态应用程序。本文简要比较了它们的特性、功能和对代码的影响。读完这篇文章后,也许你将能够找到适合你的库。




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


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


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

MAC 解压rar

前端达人

本文转载至 : Mac解压压缩 rar文件

一、下载压缩包到本地(Downloads文件夹下)

RAR 5.60 for Mac OS Xwww.rarlab.com

二、双击打开下载好的rarosx-5.6.0.tar.gz文件,会自动解压出一个rar文件夹。由于默认下载到了Downloads目录,所以在终端中执行

cd ~/Downloads/rar 
  • 1

三、需要执行两个命令。一个是安装rar压缩命令,一个是安装unrar解压命令

sudo install -c -o $USER rar /usr/local/bin/
sudo install -c -o $USER unrar /usr/local/bin 
  • 1
  • 2

四、走完上面三步,实际上我们mac已经能够正常解压和压缩rar文件了。下面只介绍解压命令

1,解压命令

//解压到当前目录
unrar x a.rar //解压到指定目录
unrar x a.rar ~/Downloads //解压文件到当前目录
unrar e test.rar //查看rar中的文件
unrar l test.rar //更详细Ï
unrar v test.rar //测试是否可以成功解压
unrar t test.rar 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

2,压缩命令

// 将file文件压缩到text.rar
rar a text.rar file




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


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


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

前端基于DOM或者Canvas实现页面水印

前端达人

前言

我们会看到很多页面带有水印,但是怎么实现呢?当然可以有多种实现方式,本文主要讲解在vue项目中基于DOM或者Cavans实现水印效果,当然还有其他的实现方式,比如在原图片的基础上加上水印生成新的图片,但是这需要后端处理。因为要在vue项目中使用,所以我使用自定义指令可以直接对挂载的dom实现水印效果。

本文实现水印的项目环境为:vue + vite + ts

一、vue自定义指令directive讲解

前面专门有一篇讲解vue2.x与vue3.x中自定义指令详解

二、基于DOM的实现方式

1. 思路整理

  • 获取宽高
    (1)获取绑定元素的实际宽度clientWidth
    (2)获取绑定元素实际高度clientHeight
    (3)获取绑定元素的父元素parentElement
  • 创建盒子
    (1)创建一个包裹水印图片的盒子
    (2)创建一个水印图片的盒子
  • 设置盒子样式
    (1)包裹水印盒子宽高为绑定元素的宽高,即clientWidth、clientHeight
    (2)水印盒子设置背景图、旋转度、宽高、点击穿透
  • 设置创建的元素的位置
    (1)水印盒子放到包裹水印图片的盒子里 (包裹水印图片的盒子包裹水印)
    (2)包裹水印图片的盒子放到被绑定元素之前
    (3)被绑定元素放到裹水印图片的盒子里(不然被绑定元素与包裹水印图片的盒子层级同级)

2.新建index.vue

将水印的指令放到标签上,设置标签的宽高。水印可以放大div标签上,也可以是img标签上。注意:img才有onload方法,div标签么有。

<script setup lang="ts"> import { ref } from "vue"; </script> <template> <div class="index-content" > <div class="watermaker" v-watermark ></div> <!-- <img v-watermark style="width:400px;height:400px" src="../assets/vue.svg" alt=""> --> </div> </template> <style scoped> .watermaker { width: 400px; height: 400px; } .index-content{ width: 100%; height: 100%; } </style> 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

3. 新建directives文件

directives文件下创建waterMark.ts 文件,具体内容实现如下:

import waterImg from "@/assets/vue.svg" const directives: any = { mounted(el: HTMLElement) { //如果el元素是img,则可以用el.onload将下面包裹 const { clientWidth, clientHeight, parentElement } = el; console.log(parentElement, 'parentElement') const waterMark: HTMLElement = document.createElement('div'); const waterBg: HTMLElement = document.createElement('div'); //设置waterMark的class和style waterMark.className = `water-mark`; waterMark.setAttribute('style', ` display: inline-block;
            overflow: hidden;
            position: relative;
            width: ${clientWidth}px; 
            height: ${clientHeight}px;`); // 创建waterBg的class和style waterBg.className = `water-mark-bg`;// 方便自定义展示结果 waterBg.setAttribute('style', ` position: absolute;
            pointer-events: none;`在这里插入代码片` transform: rotate(45deg);
            width: 100%;
            height: 100%;
            opacity: 0.2;
            background-image: url(${waterImg}); 
            background-repeat: repeat; `); // 水印元素waterBg放到waterMark元素中 waterMark.appendChild(waterBg); //waterMark插入到el之前,即插入到绑定元素之前 parentElement?.insertBefore(waterMark, el); // 绑定元素移入到包裹水印的盒子 waterMark.appendChild(el); } } export default { name: 'watermark', directives } 
  • 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

4. 在directives文件下创建 index.ts文件

import type { App } from 'vue' import watermark from './waterMark' export default function installDirective(app: App) { app.directive(watermark.name, watermark.directives); } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

5. 在main.ts中全局引入

import { createApp } from 'vue' import App from './App.vue' import directives from './directives' const app = createApp(App); app.use(directives); app.mount('#app'); 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

6. 缺点

  • 直接删除水印元素时,页面中的水印直接就被删除了,当然我们可以用MutationObserver对水印元素进行监听,删除时,我们再立即生成一个水印元素就可以了,具体方面在下面讲解。
  • 如果原始元素本身存在 css 定位等规则,会导致整体布局效果出现影响,因为上面实现排除了原始元素没有定位,所以实现方式不是很严谨,本文具体实现实现如下:
    • 创建一个水印的容器设置为 position:relative
    • 将原有的节点放入到这个容器中
    • 同时创建一个带有水印的 dom 设置为position:absolute ,实现这个水印元素覆盖到原始元素的上层,以实现水印的效果。

三、基于Canvas和MutationObserver的实现方式

1. 思路整理

  • 配置水印的具体样式(大小,旋转角度,文字填充)
  • 设置水印(位置)
  • 监听dom变化(防止水印删除后页面不再展示水印)

2. 生成水印

通过将图片绘制在cavans中,然后通过cavanstoDataURL方法,将图片转为base64编码。

// 全局保存 canvas 和 div ,避免重复创建(单例模式) const globalCanvas = null; const globalWaterMark = null; // 获取 toDataURL 的结果 const getDataUrl = ( // font = "16px normal", // fillStyle = "rgba(180, 180, 180, 0.3)", // textAlign, // textBaseline, // text = "请勿外传", ) => { const rotate = -10; const canvas = globalCanvas || document.createElement("canvas"); const ctx = canvas.getContext("2d"); // 获取画布上下文 ctx.rotate((rotate * Math.PI) / 180); ctx.font = "16px normal"; ctx.fillStyle = "rgba(180, 180, 180, 0.3)"; ctx.textAlign = "left"; ctx.textBaseline = "middle"; ctx.fillText('请勿外传', canvas.width / 3, canvas.height / 2); return canvas.toDataURL("image/png"); }; 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

3. 使用MutationObserver监听水印

使用MutationObserver监听dom变化,MutationObserver详细用法之前已经讲过了,详细可见作为前端你还不懂MutationObserver?那Out了
具体监听逻辑如下:

  • 1.直接删除dom
    (1)先获取设置水印的dom
    (2)监听到被删除元素的dom
    (3)如果他两相等的话就停止观察,初始化(设置水印+启动监控)
  • 2.删除style中的属性
    (1)判断删除的是否是标签的属性 (type === “attributes”)
    (2)判断删除的标签属性是否是在设置水印的标签上
    (3)判断修改过的style和之前的style对比,不等的话,重新赋值
// watermark 样式 let style = ` display: block;
overflow: hidden;
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-repeat: repeat;
pointer-events: none;`; //设置水印 const setWaterMark = (el: HTMLElement, binding: any) => { const { parentElement } = el; // 获取对应的 canvas 画布相关的 base64 url const url = getDataUrl(binding); // 创建 waterMark 父元素 const waterMark = globalWaterMark || document.createElement("div"); waterMark.className = `water-mark`; // 方便自定义展示结果 style = `${style}background-image: url(${url});`; waterMark.setAttribute("style", style); // 将对应图片的父容器作为定位元素 parentElement.setAttribute("style", "position: relative;"); // 将图片元素移动到 waterMark 中 parentElement.appendChild(waterMark); }; // 监听 DOM 变化 const createObserver = (el: HTMLElement, binding: any) => { console.log(el, 'el') console.log(style, 'style') // console.log(el.parentElement.querySelector('.water-mark'),'el.parentElement') const waterMarkEl = el.parentElement.querySelector(".water-mark"); const observer = new MutationObserver((mutationsList) => { console.log(mutationsList, 'mutationsList') if (mutationsList.length) { const { removedNodes, type, target } = mutationsList[0]; const currStyle = waterMarkEl.getAttribute("style"); // console.log(currStyle, 'currStyle') // 证明被删除了 //   (1)直接删除dom //   1.先获取设置水印的dom //   2.监听到被删除元素的dom //   如果他两相等的话就停止观察,初始化(设置水印+启动监控) //   (2) 删除style中的属性 //  1 判断删除的是否是标签的属性 (type === "attributes") //  2.判断删除的标签属性是否是在设置水印的标签上 //  3.判断修改过的style和之前的style对比,不等的话,重新赋值 if (removedNodes[0] === waterMarkEl) { console.log(removedNodes[0]) // 停止观察。调用该方法后,DOM 再发生变动,也不会触发观察器。 observer.disconnect(); //初始化(设置水印,启动监控) init(el, binding); } else if ( type === "attributes" && target === waterMarkEl && currStyle !== style ) { console.log(currStyle, 'currStyle') console.log(style, 'style') waterMarkEl.setAttribute("style", style); } } }); observer.observe(el.parentElement, { childList: true, attributes: true, subtree: true, }); }; // 初始化 const init = (el: HTMLElement, binding: any = {}) => { // 设置水印 setWaterMark(el, binding.value); // 启动监控 createObserver(el, binding.value); }; const directives: any = { mounted(el: HTMLElement, binding: any) { //注意img有onload的方法,如果自定义指令注册在html标签的话,只需要init(el, binding.value) el.onload = init.bind(null, el, binding.value); }, }; 
  • 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
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87

四、成果展示

删除水印标签依然还在,除非删除水印注册的标签才能删除水印,但是这样做毫无意义,因为这样做内容也会全部删除掉。

在这里插入图片描述

附:文中用到的js基础知识

toDataURL用法

toDataURL(type, encoderOptions),接收两个参数:

  • type:图片类型,比如image/png、image/jpeg、image/webp等等,默认为image/png格式
  • encoderOptions:图片质量的取值范围(0-1),默认值为0.92,当超出界限按默认值0.92






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


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


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

日历

链接

个人资料

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

存档