前言:
当前我们对“python电商网站”大体比较着重,你们都想要知道一些“python电商网站”的相关知识。那么小编在网摘上网罗了一些有关“python电商网站””的相关知识,希望小伙伴们能喜欢,我们快快来了解一下吧!移动端开发必备使用rem单位进行手机适配,在路径/src/assets/js/common.js里面加入以下代码,作为公用JS方法,便于每个页面调用。
// 页面单位remrem: function () { var docEl = document.documentElement, resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize', recalc = function () { var clientWidth = docEl.clientWidth; if (!clientWidth) return; if (clientWidth >= 750) { docEl.style.fontSize = '100px'; } else { docEl.style.fontSize = 100 * (clientWidth / 750) + 'px'; } }; recalc(); window.addEventListener(resizeEvt, recalc, false);}
这是rem布局的核心代码,如果页面宽度超过了750px,那么页面中html的font-size字体大小应为100px。否则,页面中html的font-size字体大小为: 100 * (当前页面宽度 / 750)。一般UI设计师提供的设计稿宽度是640px或750px,为了方便计算,选择750px,那么转化rem的时候,像素/100等于rem。比如:图片宽度100px,100px/100=1rem。
禁用a,button,input,select,textarea等标签背景变暗,直接在/src/assets/css/common.css加入如下代码即可:
// 去掉点击链接和文本框对象的半透明覆盖(iOS)或者虚框(Android)a, button, input, optgroup, select, textarea { -webkit-tap-highlight-color: rgba(0, 0, 0, 0);}
// 页面窗口自动调整到设备宽度,并禁止用户缩放页面<meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=0">
属性基本含义:
更多的meta:
//编码格式<meta charset="UTF-8">// 优先使用 IE 最新版本和 Chrome<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/> // 兼容国产浏览器的高速模式<meta name="renderer" content="webkit">// UC强制全屏<meta name=”full-screen” content=”yes”> // 忽略将页面中的数字识别为电话号码<meta name="format-detection" content="telephone=no">// 忽略 android 平台对邮箱的识别<meta name="format-detection" content="email=no">// 添加到主屏幕后,会全屏显示<meta name="apple-touch-fullscreen" content="yes" />// 当网站添加到主屏幕快速启动方式,可隐藏地址栏,进针对ios的safari<meta name="apple-mobile-web-app-capable" content="yes">// 将网站添加到主屏幕快速启动方式,仅针对ios的safari顶端状态条的样式// 可选default、black、black-translucent<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">// 页面描述<meta name="description" content="不超过150个字符"/> // 页面关键词,多个关键词用逗号分隔<meta name="keywords" content=""/> // 需要在网站的根目录下存放favicon图标,防止404请求<link rel="shortcut icon" href="/favicon.ico">webkit表单输入框placeholder的颜色值改变
input::-webkit-input-placeholder{ color: red;}消除原生外观,在iOS手机端加上这个属性才能给按钮和输入框自定义样式
input, textarea { -webkit-appearance: none;}在iOS下禁止长按页面时弹出菜单
a, img { -webkit-touch-callout: none;}
calc基本语法,支持加,减,乘,除; 在做手机端的时候非常有用的一个知识点。优点如下:
(1) 支持使用 “+”、"-"、"*"、"/" 四则运算
(2) 可以混合使用百分比(%)、px、em、rem等作为单位可进行计算
浏览器兼容性:IE9+、FF4.0+、chrome19+、safari6+
用法如下:
.box { width: calc(100% - 20px - 2em);}<div class="box">测试文本</div>
flex弹性布局,容器的6个属性,一般与rem配合使用绝佳。
(1) flex-direction
(2) flex-wrap
(3) flex-flow
(4) justify-content
(5) align-items
(6) align-content
以上6个属性,具体如何使用,推荐阮一峰老师的flex布局教程,熟读+实操。
页面组件开发
整个网站的主体包括首页、商品列表页、商品搜索页、商品详情页、领取优惠券等页面组成。
根据UI设计师提供的设计稿制作静态界面,我们在动手前先来分析一下首页有哪些场景设计或交互效果。上一篇已经介绍首页长什么样,可以说出头部导航,搜索框,分享弹框按钮,轮播图,商品类目,商品列表页,返回顶部按钮,预加载动画。其他页面大家也可以开动脑筋想一想它们的场景设计或交互效果,思考多了收获也多。
再想一想,是不是可以进行前端组件化和模块化的思维开发呢?答案:肯定是。
也许有的小伙伴一知半解,有的却很陌生,有的经常听到面试官提这些概念问题。其实不难理解,简单说前端架构设计的目的是制定标准,提高质量和效率。那合理的架构就囊括工程化、组件化、模块化、规范化。
然而前端组件化、模块化能帮我们解决哪些问题呢?
组件化更多关注UI部分,页面的每个部件,比如头部导航,搜索框,商品列表甚至返回顶部按钮都可以成为一个组件,每个组件有独立的HTML、css、js代码。可以根据需要把它放在页面的任意部位,也可以和其他组件一起形成新的组件。一个页面是各个组件的结合,可以根据需要进行组装。
而模块化侧重功能的封装,主要是针对Javascript代码,隔离、组织复制的javascript代码,将它封装成一个个具有特定功能的模块。(比如常用到ES6模块)
前面讲的这些,还是没弄明白的话,可以去网上查找相关资料。
步入正轨
由于时间关系,会挑几个功能重点细讲,先看看首页模板组成:index.html,index.js,index.vue三个文件如下图:
首页效果图
了解了每个页面组成部分,接下来可以进行页面布局,开发静态界面,最后写业务逻辑与后端联调接口。之前有提到前端组件化思维,根据实际项目需求使用,经过分析,一般头部或底部导航、商品分类、商品列表、返回顶部按钮、loading预加载动画等等都可以抽离出来做成组件,在src/components/位置存放所有组件。比如头部导航是公用父组件,里面包括搜索框,可抽离出来做成公用子组件。由于作者很懒,没有实现抽离,直接写在模板页面。小伙伴可以自己抽时间尝试改成组件形式。
既然要做前端组件化开发,那就拿商品分类为例。在src/components/下创建categoryList.vue文件,在template模板标签写布局,代码如下图:
样式写在style标签里面,如果要使样式私有化,只在当下模块有效,可以在style标签上加scoped属性。代码如下图:
Vue实例获取商品分类数据,是在script标签中export default模块实现数据初始化,因为是对象数组,所以在data()函数里面自定义对象数组来初始化数据。代码如下:
<script>export default { data () { return { categoryList: [ { id: "1", category: 2, name: "男装", sort: "100", imgUrl: require('../assets/img/category/nanzhuang.png') }, { id: "2", category: 1, name: "女装", sort: "100", imgUrl: require('../assets/img/category/nvzhuang.png') }, { id: "3", category: 6, name: "居家", sort: "100", imgUrl: require('../assets/img/category/jujia.png') }, { id: "4", category: 4, name: "母婴", sort: "100", imgUrl: require('../assets/img/category/muying.png') }, { id: "5", category: 3, name: "内衣", sort: "100", imgUrl: require('../assets/img/category/meizhuang.png') }, { id: "6", category: 7, name: "鞋包", sort: "100", imgUrl: require('../assets/img/category/xiebao.png') }, { id: "7", category: 5, name: "美妆", sort: "100", imgUrl: require('../assets/img/category/meizhuang.png') }, { id: "8", category: 0, name: "更多", sort: "100", imgUrl: require('../assets/img/category/more.png') } ] } } }在template模板里面获取初始化对象数组数据,采用v-for循环遍历对象数组,代码如下:
在template模板里面获取初始化对象数组数据,采用v-for循环遍历对象数组,代码如下:
<ul class="category fix"> <li v-for="item in categoryList"> <a href="javascript:;" @click="gotoSearch(item.category)" target="_blank"> <img :src="item.imgUrl" :alt="item.name" :title="item.name"> <span class="category-tit">{{item.name}}</span> </a> </li></ul>
顺便提一下Vue常用的点击事件,可以用v-on指令监听 DOM 事件,并在触发时运行一些 JavaScript 代码。
v-on:click = handleClick // handleClick方法名,可带参数// OR @click = handleClick // 点击事件简写
点击事件中调用的自定义方法名,统一写在methods属性里面,代码如下:
methods: { handleClick () { console.log('点击我') ; }}
商品分类组件完整代码如下:
<template> <div class="category-list"> <div class="floor-area"> <ul class="category fix"> <li v-for="item in categoryList"> <a href="javascript:;" @click="gotoSearch(item.category)" target="_blank"> <img :src="item.imgUrl" :alt="item.name" :title="item.name"> <span class="category-tit">{{item.name}}</span> </a> </li> </ul> </div> </div></template><script>export default { data () { return { categoryList: [ { id: "1", category: 2, name: "男装", sort: "100", imgUrl: require('../assets/img/category/nanzhuang.png') }, { id: "2", category: 1, name: "女装", sort: "100", imgUrl: require('../assets/img/category/nvzhuang.png') }, { id: "3", category: 6, name: "居家", sort: "100", imgUrl: require('../assets/img/category/jujia.png') }, { id: "4", category: 4, name: "母婴", sort: "100", imgUrl: require('../assets/img/category/muying.png') }, { id: "5", category: 3, name: "内衣", sort: "100", imgUrl: require('../assets/img/category/meizhuang.png') }, { id: "6", category: 7, name: "鞋包", sort: "100", imgUrl: require('../assets/img/category/xiebao.png') }, { id: "7", category: 5, name: "美妆", sort: "100", imgUrl: require('../assets/img/category/meizhuang.png') }, { id: "8", category: 0, name: "更多", sort: "100", imgUrl: require('../assets/img/category/more.png') } ] } }, methods: { gotoSearch (category) { window.location.href = `../search?category=${category}` ; } }, created () {}, mounted () {}}</script> <style scoped>.floor-area { background: #fff; text-align: center; overflow: hidden; padding-top: .2rem; border-top: 1px solid #eee;}.floor-area li { width: 25%; display: block; float: left; margin-bottom: .2rem;}.floor-area li a { display: block;}.floor-area li img { width: 1rem; height: 1rem; display: block; margin: 0 auto;}.floor-area li .category-tit { font-weight: 400; display: block; text-align: center; padding-top: .1rem; font-size: .24rem;}</style>
商品分类组件开发完成后,如何引入自定义组件,代码如下:
<template> <div id="app"> // 模板中使用组件 // 第一种写法 <category-list></category-list> // 第二种写法 <category-list> // slot自定义插槽内容,具体用法,参考Vue官网: </category-list> // 第三种写法 <categoryList /> </div></template><script>// 引入组件import categoryList from '@/components/categoryList'export default { components: { categoryList }, // 注册组件 data() { return { // 设置初始化数据 } }, methods: {}, created() {}, mounted() {}}</script>
现在讲讲首页轮播图效果有自动播放、左右滑动、点击图片跳内页或外链等等功能。如果自己想手写Vue轮播图特效没问题,多花一点点时间就可以完成,但如果赶项目,可以找一些市面上很成熟的开源免费插件,直接引入到你的项目中。我直接选用cdn方式引入swiper插件,操作如下:
// 先在首页index.html文件中引入以下外链<link rel="stylesheet" href=";><link rel="stylesheet" href=";><script src=";> </script><script src=";> </script>
在template模板中使用
先在script标签下的methods属性中自定义初始化Swiper实例的方法initSwiper,然后再mounted生命周期函数中调用initSwiper方法,使轮播图生效,如下图:
Swiper插件的具体用法,可以参考官网API和DEMO示例:
动态获取数据调用API接口
上面提过开发商品分类组件数据获取方式是静态的,如果商品列表要动态获取数据,该怎么操作。由于项目采用前后端分离技术,通过后端提供的API接口调用获取动态数据。要求前后端同步进行开发,但是在后端完成前,暂时是没有数据返回给前端使用的,如果先写静态后面再改,就有重复工作的内耗存在。所以我们需要一种简单快速的模拟数据的模块或管理工具,这样我们自己提供或修改接口。下面提供两种方式,博主推荐第二种操作更简便。
一、mock文件
安装mockjs和axios
npm install -D mockjsnpm install -S axios在src目录下新建mock文件夹,并创建index.js文件,结构如下:index.js文件内容及返回的数据结构如下(注意:返回的数据结构可以根据不同的功能模块写成单独的JS文件):
import Mock from 'mockjs'let shopData = { 'success|1': [true, false], 'msg': function() { if (this.success) { return '调用成功'; } else { return '调用失败'; } }, 'pageNum': 1, 'pageSize': 10, 'data': function() { if (this.success) { return this.result; } else { return this.result = []; } }, 'result|1-10': [{ 'id|+1': 1, 'GoodsId': '@guid', 'GoodsName|1': ['浙江特产手工糯米糕桂花糕250g', '【买一送一】夏季冰丝男裤休闲长裤', '仁和红豆薏米祛茶湿茶饮小袋装'], 'actDate': '@now', 'sales|0-100': 10, 'ShopName|1': ['汉兰图旗舰店', '吴玉源旗舰店', '帅趣旗舰店'], 'ImgUrl': '@image("200x200", "#00405d", "#FFF", "Mock.js")', 'GoodsPrice|1-200.1': 50, 'GoodsLink': '@url' }], 'totalNum': function() { return this.data.length; },}//格式:Mock.mock(url, post/get, 返回的数据)Mock.mock('/api/shoplist', shopData)export default Mock在src/js/api.js文件中添加模拟商品列表接口的get方法,代码如下:
// mockjs 模拟商品列表接口export function getMockData() { return network({ url: '/shoplist', method: 'get' });}在src/js/url.js文件中添加以下代码保证与mock数据url地址一致,如下图:验证mock接口,直接在首页index.vue文件中使用
// 在script标签下引入定义好的mock接口方法import { getMockData } from '@/assets/js/api'methods: { // 封装mock接口方法调用 getMockList() { getMockData().then(res => { console.log('mockData===', res) }).catch(err => { console.log(err) }) }}mounted () { this.getMockList(); // 初始化调用mock数据}返回结果如下图:
二、yapi管理工具
官网地址:创建项目
第一次进来是没有我的项目,需要自己去创建项目,上面截图有说明。接下来点击添加项目,进入新建项目页面。如下图:
一般填个项目名称,其他默认,提交就可以了。
添加接口
以上配置完成后,点击保存按钮,提示保存成功后,再回到预览界面。如下图:
直接打开postman,测试API接口,如调用成功,说明模拟数据接口配置有效,如下图:
如需了解更多yapi的功能,请查看官网文档:
父子组件相互传值
先来说两个概念:
父组件通过props属性给子组件传值
父组件监听子组件this.$emit('事件名', 参数)方法获取值
现在拿项目实例讲解上面两个功能,比如首页index.vue是父组件,二维码公众号弹框是子组件,如下图:
父组件传值给子组件,先在父组件data中定义isPopup初始值,然后在子组件上绑定isPopup,代码如下:
<template> <div id="app"> <div class="wrap"> <qrcode-pop :isPopup="isPopup" @showPopper="closeBtn"> <h3>微信打开长按二维码关注公众号</h3> <div class="qrcode-img"> <img src="../../assets/img/qrcode.jpg" class="qrcode"> </div> <div class="close-btn" @click="closeBtn">关闭</div> </qrcode-pop> </div> </div></template><script>import qrcodePop from '@/components/qrcodePop'export default { components: { qrcodePop }, data () { return { isPopup: false } }, methods: { closeBtn () { this.isPopup = false; } }}</script><style scoped></style>
子组件使用props属性,接收父组件isPopup状态的传值,可以设定默认传值类型。代码如下:
<template> // 二维码弹框提示 <div id="qrcodePop" class="qrcodePop" v-show="isPopup"> <div class="qrcode-box"> <slot></slot> </div> <div id="mask" @click="closeBtn"></div> </div></template><script>export default { data () { return { } }, props: { isPopup: Boolean }, methods: { closeBtn () { this.$emit('showPopper'); } }}</script><style scoped>#mask { position: fixed; top: 0; left: 0; bottom: 0; right: 0; height: 100%; width: 100%; z-index: 9999; background: rgba(0, 0, 0, .7);}.qrcode-box { position: fixed; top: 50%; left: 50%; width: 6rem; height: 7rem; margin-top: -3.5rem; margin-left: -3rem; display: flex; justify-content: space-between; flex-direction: column; background: #fff; border-radius: .2rem; z-index: 10000; overflow: hidden; text-align: center;}.qrcode-box h3 { width: 100%; height: auto; padding: .2rem 0; font-size: .32rem; color: #fff; background: #fc0786; text-overflow: ellipsis; white-space: nowrap; overflow: hidden;}.qrcode-box img { width: 5.16rem; height: 5.16rem;}.qrcode-box .close-btn { width: 100%; height: auto; padding: .2265rem 0; font-size: .32rem; border-top: 1px solid #ddd; background: #f2f2f2;}.layer-cont { padding: .2rem .3rem 0 .3rem; line-height: .44rem; text-align: center;}.kouling-cont { position: relative; background: #fff4f8; padding: .2rem; margin: 0 auto; display: flex; align-items: center; justify-content: center;}#textarea { display: block; font-size: .24rem; width: 100%; height: 2.2rem; line-height: .28rem; color: #fc0786; background: #fff; resize: none; border: none; outline: none; overflow-x: hidden; word-wrap: break-word; word-break: break-all;} .better-change{ display: flex; align-items: center; justify-content: space-around;}.onecopy { width: 50%; padding: .25rem .0; background: #f8285c; text-align: center; margin: 0 auto; color: #fff; cursor: pointer; border-top: 1px solid #ddd; font-size: .32rem;}.kouling-tips p { display: block; border-bottom: 1px dotted #e5e5e5; padding: .15rem 0; text-align: justify; font-size: .28rem;}.kouling-tips i { color: #dd514c;}.kouling-tips p.nber { border-bottom: none;}</style>
子组件传值给父组件,在父组件中定义方法名closeBtn,并在子组件上添加自定义事件名@showPopper,如下图:
在子组件中将this.$emit()方法放在closeBtn点击函数里面,来触发父组件事件传递isPopup状态值,如下图:
父子组件之间的传值已完成,最后再补充一下rem适配手机页面生效,需在每个Vue模板页面引入即可,代码如下:
<script>import Export from '@/assets/js/export'export default { data() { return {} }, methods: {}, created () { Export.rem(); // 调用rem手机页面适配方法 }, mounted () {} }}</script>
项目中涉及的功能点基本讲完,若需看整站效果或源代码请移步去github上查看或下载。附上地址:
还包括更多实战项目哦!
标签: #python电商网站