VUE高仿饿了么app

本项目github地址:https://github.com/motysla/eleme.git

VUE 搭建简介

刚学习了VUE高仿饿了么app课,记录课的要点,巩固知识。

VUE 优势

Vue.js 是一个用于创建 web 交互界面的。其特点是

  1. 简洁 HTML 模板 + JSON 数据,再创建一个 Vue 实例,就这么简单。
  2. 数据驱动 自动追踪依赖的模板表达式和计算属性。
  3. 组件化 用解耦、可复用的组件来构造界面。
  4. 轻量 ~24kb min+gzip,无依赖。
  5. 快速 精确有效的异步批量 DOM 更新。
  6. 模块友好 通过 NPM 或 Bower 安装,无缝融入你的工作流。

VUE 搭建工具

借用express + data 构建拟后台

  1. vue 1.0
  2. express
  3. vue.router
  4. vue.rescrouse
  5. better-scroll
  6. less

CSS 使用的要点

1像素边框制作

设备上像素 = 样式像素 * 设备缩放比例

  1. 屏幕宽度 320px 480px 640px
  2. 缩放比例 1 1.5 2

当样式像素一定时,因手机有320px,640px等.各自的缩放比差异,所以设备显示像素就会有1Npx,2Npx.为保设计稿还原度,解决就是用media + scale.

  1. .border(@borderColor){
  2. position: relative;
  3. &::after{
  4. content: "";
  5. position: absolute;
  6. bottom: 0;
  7. left: 0;
  8. width: 100%;
  9. border-top: 1px solid @borderColor;
  10. }
  11. }
  12. @media (min-device-pixel-ratio: 1.5) {
  13. .border{
  14. &::after{
  15. transform: scaleY(0.7);
  16. }
  17. }
  18. }
  19. @media (min-device-pixel-ratio: 2) {
  20. .border{
  21. &::after{
  22. transform: scaleY(0.5);
  23. }
  24. }
  25. }

通过查询它的缩放比,在媒体宽为1.5倍时, round(1px 1.5 / 0.7) = 1px 在媒体宽为2倍时, round(1px 2 / 0.5) = 1px.

自适应宽

在商品路由中,导航宽度固定80px的,因为手机分辨率大小不一,所以食物详情自适应.解决就是flex布局.


css

  1. <style type="text/less">
  2. .food{
  3. display: flex;
  4. width: 100%;
  5. .nav{
  6. flex: 0 0 80px;
  7. width: 80px;
  8. }
  9. .foodList{
  10. flex: 1;
  11. }
  12. }
  13. </style>

html

  1. <div class="food">
  2. <section class="nav"></section>
  3. <section class="foodList"></section>
  4. </div>

在父元素设弹性布局,导航里设弹性为0,定宽为80px.商品食物详情弹性为1.就适应宽度变化.

Sticky footer

做商家弹出页时,信息高度是无法预定的,有可能溢出window高度,也可能少于window高度,但底部按钮,当信息高度少于window高度,要固定在底部40px.解决就是用sticky footer布局


css

  1. <style type="text/less">
  2. .showDetil{
  3. position: absolute;
  4. width: 100%;
  5. height: 100%;
  6. .sellerDetil{
  7. width: 100%;
  8. min-height: 100%;
  9. padding-bottom: 40px;
  10. }
  11. .btn{
  12. position: relative;
  13. top: -40px;
  14. height: 40px;
  15. }
  16. }
  17. </style>

html

  1. <div class="showDetil">
  2. <section class="sellerDetil"></section>
  3. <section class="btn"></section>
  4. </div>

父元素高相同window高,信息最小高就相同window高,按钮这时就溢出了.
再设置底的填充,底内边距高就是按钮的高. 按钮在用相对定位,定在信息的底填充里.
因信息最少高度是100%,所按钮要不钉在底部了.要不溢出.

自适相等宽高

在食物弹出页.设计图食物图的宽高是相等,每张图的宽高比例有可能有区别,但也要做自适应.解决就是用padding边距.


css

  1. <style type="text/less">
  2. .imgs{
  3. width: 100%;
  4. height: 0;
  5. position: relative;
  6. padding-top: 100%;
  7. .image{
  8. position: absolute;
  9. top: 0;
  10. width: 100%;
  11. height: 100%;
  12. left: 0;
  13. }
  14. }
  15. </style>

html

  1. <div class="imgs">
  2. <img src="..." class="image">
  3. </div>

在父元素,边距的长是取决去宽的,所其宽度与边距的长是相等的.
在把高设为0,宽为100%,上边距100%,上边据就盒子的高.盒子是为正形.
子元素设宽与高为100%,那也是正形.

VUE要点

小图标的编选

根据后台输出的数据,判定显示那个的图标.这vue典型的数据.驱动.解决是使用:class困绑数据


html

  1. <template>
  2. <ul>
  3. <li v-for="date in goods">
  4. <span :class="classmap[date.type]"></span>
  5. </li>
  6. </ul>
  7. </template>

js

  1. <script type="text/javascript">
  2. export default{
  3. data() {
  4. return {
  5. classmap: ['decrease', 'discount', 'guarantee', 'invoice', 'special']
  6. };
  7. }
  8. }
  9. </script>

css

  1. <style type="text/less">
  2. .bgimg(@imgs) {
  3. background-image: url('@imgs+".png"') 0 0 no-repeat ~'/' 100% 100%;
  4. }
  5. .decrease{
  6. display: inline-block;
  7. height: 12px;
  8. width: 12px;
  9. .bgimg('decrease_3');
  10. }
  11. .discount{
  12. display: inline-block;
  13. height: 12px;
  14. width: 12px;
  15. .bgimg('discount_3');
  16. }
  17. .guarantee{
  18. display: inline-block;
  19. height: 12px;
  20. width: 12px;
  21. .bgimg('guarantee_3');
  22. }
  23. .invoice{
  24. display: inline-block;
  25. height: 12px;
  26. width: 12px;
  27. .bgimg('invoice_3');
  28. }
  29. .special{
  30. display: inline-block;
  31. height: 12px;
  32. width: 12px;
  33. .bgimg('special_3');
  34. }
  35. </style>

通过v-for,遍历数据,所以date.type得到数据并判断类型.然后通classmap数组判定绑那个class.来加图标.

小球动画

点击加食物时,触动小球弹出的动画,小球的落点是在车的中央.但起点是根各个节点位子而又差别的.解决使用transitions + events + dispatch事件冒泡

cartcontrol子组件


html

  1. <template>
  2. <div class="cartcontrol">
  3. <section class="cart-decrease" @click.stop.prevent="decreaseCart" v-show="food.count > 0" transition="move"></section>
  4. <section class="cart-count" v-show="food.count > 0">{{food.count}}</section>
  5. <section class="cart-add" @click.stop.prevent="addCart"> </section>
  6. </div>
  7. </template>

js

  1. <script type="text/javascript">
  2. export default {
  3. props: {
  4. food: {
  5. type: Object
  6. }
  7. },
  8. methods: {
  9. addCart(event) {
  10. if (!this.food.count) {
  11. Vue.set(this.food, 'count', 1);
  12. this.food.count = 1;
  13. } else {
  14. this.food.count++;
  15. };
  16. this.$dispatch('cart.add', event.target);
  17. },
  18. decreaseCart() {
  19. if (this.food.count) {
  20. this.food.count--;
  21. };
  22. }
  23. }
  24. };
  25. </script>

在加食物,触发了addCart事件,设用set方法给数据加属性,并使cart.add事件冒泡出去,event.target作为事件参数,即节点冒泡出去.

goods父组件


html

  1. <template>
  2. <shop v-ref:shop :delivery-price="seller.deliveryPrice" :min-price="seller.minPrice" :select-foods="selectFoods"></shop>
  3. </template>

js

  1. <script>
  2. export default {
  3. methods: {
  4. _drop(target) {
  5. this.$refs.shop.drop(target);
  6. }
  7. },
  8. events: {
  9. 'cart.add'(target) {
  10. this._drop(target);
  11. }
  12. },
  13. components: {
  14. shop,
  15. cartcontrol,
  16. food
  17. }
  18. };
  19. </script>

在冒泡被events钩子监听,与触动_drop方法,通过接口获得购物车组建的事件,就把control组建event.target传入购物车组建的事件,及把control节点传入了shop组建.

shop组建


html

  1. <template>
  2. <div class="shopcart">
  3. <section class="ball-container">
  4. <div transition="drop" v-for="ball in balls" v-show="ball.show" class="ball">
  5. <div class="inner inner-hook"></div>
  6. </div>
  7. </section>
  8. </div>
  9. </template>

js

  1. <script type="text/javascript">
  2. export default {
  3. data() {
  4. return {
  5. balls: [
  6. {
  7. show: false
  8. },
  9. {
  10. show: false
  11. },
  12. {
  13. show: false
  14. },
  15. {
  16. show: false
  17. },
  18. {
  19. show: false
  20. }],
  21. dropBalls: [],
  22. fold: true
  23. };
  24. },
  25. methods: {
  26. drop(el) {
  27. for (var i = 0; i < this.balls.length; i++) {
  28. let ball = this.balls[i];
  29. if (!ball.show) {
  30. ball.show = true;
  31. ball.el = el;
  32. this.dropBalls.push(ball);
  33. return;
  34. };
  35. };
  36. }
  37. },
  38. transitions: {
  39. drop: {
  40. beforeEnter(el) {
  41. let count = this.balls.length;
  42. while (count--) {
  43. let ball = this.balls[count];
  44. if (ball.show) {
  45. let rect = ball.el.getBoundingClientRect();
  46. let x = rect.left - 32;
  47. let y = -(window.innerHeight - rect.top - 22);
  48. el.style.display = '';
  49. el.style.transform = `translate3d(0,${y}px,0)`;
  50. let inner = el.getElementsByClassName('inner-hook')[0];
  51. inner.style.transform = `translate3d(${x}px,0,0)`;
  52. }
  53. }
  54. },
  55. enter(el) {
  56. let rf = el.offsetHeight;
  57. this.$nextTick(() => {
  58. el.style.transform = 'translate3d(0,0,0)';
  59. let inner = el.getElementsByClassName('inner-hook')[0];
  60. inner.style.transform = 'translate3d(0,0,0)';
  61. });
  62. },
  63. afterEnter(el) {
  64. let ball = this.dropBalls.shift();
  65. if (ball) {
  66. ball.show = false;
  67. el.style.display = 'none';
  68. };
  69. }
  70. }
  71. },
  72. components: {
  73. cartcontrol
  74. }
  75. };
  76. </script>

传入节点数据,过渡执行前可插入一个beforeEnter事件,通getBoundingClientRect定位.动画执行后可插入一个afterEnter,还原小球

接后台数据

与后台的配合,通过插vue.resource + express 连接得到数据

dev-server

  1. <script type="text/javascript">
  2. import express from 'express';
  3. var app = express();
  4. var appData = require('../data.json');
  5. var seller = appData.seller;
  6. var goods = appData.goods;
  7. var ratings = appData.ratings;
  8. var apiRoutes = express.Router();
  9. apiRoutes.get('/seller', function (req, res) {
  10. res.json({
  11. errno: 0,
  12. data: seller
  13. });
  14. });
  15. apiRoutes.get('/goods', function (req, res) {
  16. res.json({
  17. errno: 0,
  18. data: goods
  19. });
  20. });
  21. apiRoutes.get('/ratings', function (req, res) {
  22. res.json({
  23. errno: 0,
  24. data: ratings
  25. });
  26. });
  27. app.use('/api', apiRoutes);
  28. </script>

通过与配和框架express,连到数据。并放在api里.

main.js

  1. import VueResource from 'vue-resource';
  2. Vue.use('VueResource');

引进插件和使用,在全局也可以使用.

header组建

  1. <script type="text/javascript">
  2. export default{
  3. created() {
  4. this.$http.get('/api/ratings').then((response) => {
  5. var response = response.body;
  6. if (response.errno === 0) {
  7. this.ratings = response.data;
  8. };
  9. });
  10. }
  11. }
  12. </script>

在框架的钩子,及创建就通过http.get连到express发的数据,通参数response得到.body表示数据以json格式响应.注意接收数据是异步实现,如果出报错undefined,可用v-if判断,当获取数据后在渲染.

评分类换

用户的满意度有,推荐与吐槽再加上全部,就三个分页,分页通过按钮切换.如何制作呢?解决是使用v-show进判断.

ratingselect子组件


html

  1. <template>
  2. <div class="ratingselect">
  3. <div class="rating-type">
  4. <span @click="select(2, $event)"</span></span> <span class="hljs-keyword" style="font-weight:bold;"><span class="hljs-keyword">class</span></span>=<span class="hljs-string" style="color:rgb(221,17,68);"><span class="hljs-string">"block positive"</span></span> :<span class="hljs-keyword" style="font-weight:bold;"><span class="hljs-keyword">class</span></span>=<span class="hljs-string" style="color:rgb(221,17,68);"><span class="hljs-string">"{'active':selectType === 2}"</span></span>&gt;{{desc.all}}&lt;span <span class="hljs-keyword" style="font-weight:bold;"><span class="hljs-keyword">class</span></span>=<span class="hljs-string" style="color:rgb(221,17,68);"><span class="hljs-string">"count"</span></span>&gt;{{ratings.length}}&lt;/span&gt;&lt;/span&gt;</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="5"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> &lt;span @click=<span class="hljs-string" style="color:rgb(221,17,68);"><span class="hljs-string">"select(0, $event)" class="block positive" :class="{'active':selectType === 0}">{{desc.positive}}<span class="count">{{positives.length}}</span></span>
  5. <span @click="select(1, $event)" class="block negative" :class="{'active':selectType === 1}">{{desc.negative}}<span class="count">{{negatives.length}}</span></span>
  6. </div>
  7. <div @click="toggleContent" class="switch" :class="{'on':onlyContent}">
  8. <span class="iconfont arre">&#xe905;</span>
  9. <span class="text">只看有内容的评价</span>
  10. </div>
  11. </div>
  12. </template>

js

  1. <script type="text/javascript">
  2. export default{
  3. props: {
  4. ratings: {
  5. type: Array,
  6. default() {
  7. return [];
  8. }
  9. },
  10. selectType: {
  11. type: Number,
  12. default: 2
  13. },
  14. onlyContent: {
  15. type: Boolean,
  16. default: true
  17. },
  18. desc: {
  19. type: Object,
  20. default() {
  21. return {
  22. all: '全部',
  23. positive: '满意',
  24. negative: '不满意'
  25. };
  26. }
  27. }
  28. },
  29. methods: {
  30. select(type) {
  31. this.selectType = type;
  32. this.$dispatch(</span><span class="hljs-string" style="color:rgb(221,17,68);"><span class="javascript"><span class="hljs-string">'ratingtype.select'</span></span></span><span class="javascript">, type);</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="33"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> },</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="34"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> toggleContent() {</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="35"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-keyword" style="font-weight:bold;"><span class="javascript"><span class="hljs-keyword">this</span></span></span><span class="javascript">.onlyContent = !</span><span class="hljs-keyword" style="font-weight:bold;"><span class="javascript"><span class="hljs-keyword">this</span></span></span><span class="javascript">.onlyContent;</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="36"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-keyword" style="font-weight:bold;"><span class="javascript"><span class="hljs-keyword">this</span></span></span><span class="javascript">.$dispatch('ratingtype.toggleContent', this.onlyContent);
  33. }
  34. }
  35. };
  36. </script>
满意是为:0,不满意是为:1,全部是为:2.

因在点击切换按钮,触发方法,通过传入参数来替换数据,数据selectType赋值等于参数.参数是自义定,然而可以在参数下功夫,然用冒泡将数据分出.

food父组件
html

  1. <template>
  2. <transiton>
  3. <div class="rating">
  4. <h4 class="title">商品评价</h4>
  5. <ratingselect :select-type="selectType" :only-content="onlyContent" :desc="desc" :ratings="food.ratings"></ratingselect>
  6. <div class="rating-wrapper">
  7. <ul v-show="food.ratings && food.ratings.length">
  8. <li v-for="rating in food.ratings" v-show="needShow(rating.rateType,rating.text)" class="rating-item">
  9. <div class="user">
  10. <span class="name">{{rating.username}}</span>
  11. <img class="avatar" width="12" height="12" :src="rating.avatar">
  12. </div>
  13. <div class="time">{{rating.rateTime | formatDate}}</div>
  14. <p class="text">
  15. <span v-if="rating.rateType === 0" class="arrowUp iconfont"></span>
  16. <span v-if="rating.rateType === 1" class="arrowDown iconfont"></span>{{rating.text}}
  17. </p>
  18. </li>
  19. </ul>
  20. <div class="no-rating" v-show="!food.ratings || !food.ratings.length">暂无评价</div>
  21. </div>
  22. </div>
  23. </transiton>
  24. </template>

js

  1. <script type="text/javascript">
  2. import Vue from 'vue';
  3. import ratingselect from 'components/ratings/ratingselect';
  4. const POSITIVE = 0;
  5. const NEGATIVE = 1;
  6. const ALL = 2;
  7. export default {
  8. data() {
  9. return {
  10. showFlage: false,
  11. selectType: ALL,
  12. onlyContent: true,
  13. desc: {
  14. all: '全部',
  15. positive: '推荐',
  16. negative: '吐槽'
  17. }
  18. };
  19. },
  20. methods: {
  21. needShow(type, text) {
  22. if (this.onlyContent && !text) {
  23. return false;
  24. }
  25. if (this.selectType === ALL) {
  26. return true;
  27. } else {
  28. return type === this.selectType;
  29. }
  30. }
  31. },
  32. events: {
  33. 'ratingtype.select'(type) {
  34. this.selectType = type;
  35. this.$nextTick(</span><span class="hljs-function"><span class="hljs-params" style="color:rgb(153,0,0);font-weight:bold;"><span class="javascript"><span class="hljs-function"><span class="hljs-params">()</span></span></span></span><span class="javascript"><span class="hljs-function"> =&gt;</span></span></span><span class="javascript"> {</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="39"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-keyword" style="font-weight:bold;"><span class="javascript"><span class="hljs-keyword">this</span></span></span><span class="javascript">.scroll.refresh();</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="40"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> });</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="41"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> },</div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="42"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-string" style="color:rgb(221,17,68);"><span class="javascript"><span class="hljs-string">'ratingtype.toggleContent'</span></span></span><span class="javascript">(onlyContent) {</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="43"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-keyword" style="font-weight:bold;"><span class="javascript"><span class="hljs-keyword">this</span></span></span><span class="javascript">.onlyContent = onlyContent;</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="44"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-keyword" style="font-weight:bold;"><span class="javascript"><span class="hljs-keyword">this</span></span></span><span class="javascript">.$nextTick(() => {
  36. this.scroll.refresh();
  37. });
  38. }
  39. },
  40. components: {
  41. ratingselect
  42. }
  43. };
  44. </script>

在事件钩子上,实行监听,把冒泡触发并赋值,数据就得到.在遍历数据,用v-show进行判断.

VUE杂项

过渡流程

只在v-if,v-show,v-for触动节点的变动效果

当 show 属性改变时,Vue.js 将相应地插入或删除元素,按照如下规则改变过渡的 CSS 类名:

如果 show 变为 false,Vue.js 将:

调用 beforeLeave 钩子;
添加 v-leave 类名到元素上以触发过渡;
调用 leave 钩子;
等待过渡结束(监听 transitionend 事件);
从 DOM 中删除元素并删除 v-leave 类名;
调用 afterLeave 钩子。
如果 show 变为 true,Vue.js 将:

调用 beforeEnter 钩子;
添加 v-enter 类名到元素上;
把它插入 DOM;
调用 enter 钩子;
强制一次 CSS 布局,让 v-enter 确实生效。然后删除 v-enter 类名,以触发过渡,回到元素的原始状态;
等待过渡结束;
调用 afterEnter 钩子。

better-scroll

节点溢满时,是设计稿没有滚动条的,要上下移动.解决使用better-scroll插件.


html

  1. <div class="sellerx" v-el:seller style="overflow: hidden;">
  2. <div class="seller-content"></div>
  3. </div>

js

  1. <script type="text/javascript">
  2. ready() {
  3. this.$nextTick(<span class="hljs-function"><span class="hljs-params">()</span> =&gt;</span> {</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="4"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-keyword" style="font-weight:bold;"><span class="javascript"><span class="hljs-keyword">if</span></span></span><span class="javascript"> (!</span><span class="hljs-keyword" style="font-weight:bold;"><span class="javascript"><span class="hljs-keyword">this</span></span></span><span class="javascript">.scroll) {</span></div></div></li><li><div class="hljs-ln-numbers"><div class="hljs-ln-line hljs-ln-n" data-line-number="5"></div></div><div class="hljs-ln-code"><div class="hljs-ln-line"> <span class="hljs-keyword" style="font-weight:bold;"><span class="javascript"><span class="hljs-keyword">this</span></span></span><span class="javascript">.scroll = </span><span class="hljs-keyword" style="font-weight:bold;"><span class="javascript"><span class="hljs-keyword">new</span></span></span><span class="javascript"> Bscroll(</span><span class="hljs-keyword" style="font-weight:bold;"><span class="javascript"><span class="hljs-keyword">this</span></span></span><span class="javascript">.$els.seller, {
  4. click: true
  5. });
  6. } else {
  7. this.scroll.refresh();
  8. }
  9. });
  10. },
  11. </script>

但父元素设置溢出隐藏,可用插件的移动显出子节点超的内容.要在节点放个接口,使用框架钩子,创建betterScroll事例,那藏的内容通立体相上下移.better-scroll是调用样式的translate是子节点上下引动.

less样式处理

通过引入样式,有是会错误.解决使用设置标签

<style type="text/less"></style>

处理器会识别到标签的样式类别,编译样式.

esLint

在使用eslint语法校验时,经常报错,但可以在eslintrc设置进行忽略.

no mixed spaces and tabs

是把标签缩进与空格捆和使用,解决是可用tab代替空格.

Expected indentation of 2 space characters but found 3 indent

‘indent’: 0,
‘space-before-function-paren’: 0
设置缩进空行.

defined but never use

可在前加注销
/ eslint-disable no-unused-vars /

后序

要灵活的用vue,先要处理好数据的逻辑. 然而要懂得基本的数据传递属性.

  1. 子组件传给父组件-
  2. 可以用接口ref;也可以子组件的冒泡把数据传去,父组件用钩子events监听并接到数据.
  3. 父组件传给子组件-
  4. 可以在子组件props钩子,接收父组件的传递.也可以父组件用ref接口调用子组件的方法,并把数据传入方法去.

实战是最重要.

Vue高仿饿了吗学习笔记相关推荐

  1. vue高仿饿了么学习笔记(五)—— header 组件

    先贴一张 header 的 UI 图 一.header 组件 1)传入 seller 数据 // App.vue <template><div id="app"& ...

  2. vue高仿饿了么项目学习笔记之二:头部header组件的实现

    1. Vue-resource应用 在父组件APP.vue的钩子函数created使用vue-resource来ajax请求/api/seller,将数据赋值给vue实例的seller对象,并传值给子 ...

  3. 豆瓣电影页面html代码,Vue.js 仿豆瓣电影DEMO 学习笔记一

    豆瓣电影的首页效果 movie_1.png 豆瓣电影的列表页面 movie_2.png 豆瓣电影的电影内页面效果 movie_3.png 参照以上的三个页面,做出豆瓣电影的首页,列表页面以及电影的详细 ...

  4. vue高仿饿了么APP(二)

    这里我直接跳过vue-cli的安装. 一,vue.js代码是如何运行的? 1,进入页面,首先加载index.html和main.js文件. ① index.html文件 <!DOCTYPE ht ...

  5. vue高仿饿了么APP(三)

    一·需求分析 二,制作css字体图标的制作和使用 前面已经有人做过总结,我就直接引用了 css字体图标的制作和使用. 三,项目目录结构设计 1,每一个组件都单独建立一个文件夹,例如商品页建立goods ...

  6. VUE高仿饿了么app开发思维导图

    来自互联网 文章来源:刘俊涛的博客 地址:http://www.cnblogs.com/lovebing

  7. vue +vue-router + es6 +webpack 高仿饿了么app

    vue +vue-router + es6 +webpack 高仿饿了么app 刚通过某课网的教程学习了vue高仿饿了么app,由于教程是用Vue1.0编写的,现在Vue已经更新到了2.0,所以项目遇 ...

  8. vue + vue-router + vue-resource + es6 + stylus + webpack 高仿饿了么外卖App商家详情

    VUE高仿饿了么app 本项目github地址:https://github.com/motysla/eleme.git VUE 搭建简介 刚学习了VUE高仿饿了么app课,记录课的要点,巩固知识. ...

  9. Vue.js高仿饿了么外卖App学习记录

    (给达达前端加星标,提升前端技能) 开发一款vue.js开发一款app,使用vue.js是一款高效的mvvm框架,它轻量,高效,组件化,数据驱动等功能便于开发.使用vue.js开发移动端app,学会使 ...

最新文章

  1. python入门教程完整版(懂中文就能学会)-Python入门教程完整版(懂中文就能学会)...
  2. Android 5.0 Usb调试拦截分析及修改
  3. [Asp.net]SignalR实现实时日志监控
  4. 对团队建设与管理的几点看法
  5. linux之vim操作快速跳到下一个空格和上一个空格命令
  6. c语言获取dll文件路径,C语言URLDownloadToFile获取文件下载进度
  7. 虚拟主机php.ini在哪里,虚拟主机的php.ini配置文件在哪里
  8. 打印冻结窗格怎么保证每页都有_在打印Excel表时怎么设置才能实现每页都打印标题行...
  9. 栈的应用(进制转换)
  10. Spring源码之创建AOP代理(补)
  11. 多线程——java练习题
  12. 关于Ubuntu python程序利用lixb264生成h264格式的视频相关问题
  13. java excel 打勾_在excel中如何打钩
  14. 超简洁WIN10桌面分享
  15. 仿uniapp - 时间轴组件
  16. xcode引入sdk_解决Xcode引入第三方SDK找不到头文件
  17. Linux Terminal 下工具栏显示设置
  18. 那些容易被忽视但又非常重要的安全知识
  19. mysql导入.dmf文件_AX2012 DMF数据导入的问题
  20. 安卓pdf阅读器_BOOX阅读器:不仅阅读效果逆天,PDF阅读和手写体验更出色!

热门文章

  1. 拖拉验证框的位置检测
  2. 外贸中英繁三语企业网站管理系统 v2020.6.23
  3. 2021电赛F题-智能送药小车-国一
  4. 跟着c++Primer Plus学编程--- 4.13编程练习答案详解】
  5. (转)微信获取到的经纬度坐标不精准的问题
  6. autojs文档(包括4.1.0、9、autoxjs)
  7. 由于装备新的计算机英语,大学英语4课后cloze及翻译原题带答案整理完整清晰
  8. 京东爬虫——京东评论信息爬取及评论图片的下载
  9. 软件介绍,告诉你文字转语音软件有哪些
  10. 5、Python量化交易-回测收益计算