Vue.js MediaApp 知识梳理

功能技术分析

  • 前端 vue - router
  • 后端 vue - resource
  • 第三方javascript库better-scroll 最大程度组件化

动手敲每一行代码

学习目标

  • 掌握Vue.js 在实战中的应用
  • 学会使用Vue.js 完整开发移动端App
  • 学会组件化,模块化开发方式

学习内容

  • Vue.js 框架介绍
  • Vue-cli 脚手架 搭建基本代码框架
  • vue-router 官方插件管理路由
  • vue-resource Ajax通信
  • Webpack 构建工具
  • es6 + eslint eslint:es6 代码风格检查工具
  • 工程化
  • 组件化
  • 模块化
  • 移动端常用开发技巧

近年来前端开发趋势

  • 旧浏览器逐渐淘汰,移动端需求增加
  • 前端交互越来越多
  • 架构从传统后代MVC 想REST API + 前端 MV* 迁移

MVVM框架

这里写图片描述

  • 针对具有复杂交互逻辑的前端应用
  • 提供基础的架构抽象
  • 通过Ajax数据持久化,保证前端体验

什么是vue.js

  • 它是一个轻量级mvvm框架
  • 数据驱动+ 组件化前端开发
  • github star数量 社区完善

对比Angular React

  • Vue.js 更轻量,gzip 后大小只有20k
  • Vue.js 更容易上手,学习曲线平稳
  • 吸取两个之长,借鉴了angular 的指令和react的组件化

Vue.js核心思想

  • 数据驱动
  • 组件化

数据驱动

DOM是数据的一种自然映射
这里写图片描述

数据响应原理

数据(model) 改变驱动视图(view) 自然更新

这里写图片描述

组件化

扩展HTML元素 ,封装可重用的代码

组件设计原则

  • 页面上每个独立的可视。可交互区域视为一个组件
  • 每个组件对应一个工程目录,组件所需要的各种资源在这个目录下就近维护
  • 页面不过是组件的容器,组件可以嵌套自由组合形成完整的页面

3-Vue-cli 介绍

Vue-cli是Vue的脚手架工具 帮助我们搭建基础代码

  • 目录结构
  • 本地调试
  • 代码部署
  • 热加载
  • 单元测试

学习一个开源项目最好的方法:去github 看readme

https://github.com/vuejs/vue-cli

npm install -g @vue/cli-init
# vue init now works exactly the same as vue-cli@2.x
vue init webpack my-project

项目文件目录

  • build webpack配置文件相关文件
  • config wenback配置相关文件
  • node_modules npm install 安装的依赖代码库
  • src 存放项目源码
    • common
      • js
      • fonts
      • stylus
    • components
      • header
  • .babelrc babel 相关配置
  • .editorconfig 编辑器配置
  • .eslintignore 忽略语法检查的目录文件
  • .eslintrc.js eslint的配置文件
  • .gitignore git 忽略检查文件
  • package.json 项目配置文件
  • README.md 项目说明

4-5mock数据(模拟后台数据)

express

在github看项目API,真是爽的不要不要的。

eslint

语法检查,让你写的代码更加规范

vue-router

border-1px处理方式

  • mixin.styl文件
border-1px($color)
  position: relative
  &:after
    display: block
    position: absolute
    left: 0
    bottom: 0
    width: 100%
    border-top: 1px solid $color
    content: ' '

  • 引入
 @import "./common/stylus/mixin.styl"
  • 使用css属性
 border-1px(rgba(7, 17, 27, 0.1))
  • DOM 添加class
border-1px
  • .border-1px媒体查询像素适配
@media (-webkit-min-device-pixel-ratio: 1.5),(min-device-pixel-ratio: 1.5)
  .border-1px
    &::after
      -webkit-transform: scaleY(0.7)
      transform: scaleY(0.7)

@media (-webkit-min-device-pixel-ratio: 2),(min-device-pixel-ratio: 2)
  .border-1px
    &::after
      -webkit-transform: scaleY(0.5)
      transform: scaleY(0.5)

css文件引入其他css文件方式

@import "./mixin"
@import "./icon"
@import "./base"

引入公共css文件方式

import 'common/stylus/index.styl'

axios ajax 前后端数据通信

统一设置数据请求返回的状态码

  const ERR_OK = 0

对于img 一般固定宽高防止浏览器重绘

<img width="64" height='64'>

去除子元素空白字符间隙

父元素设置 font-size: 0

行内元素设置宽度高度

需要设置 display:inline-block

统一处理背景图@2x @3x 图片

// 第一步
bg-image($url)
  background-image: url($url + "@2x.png")
  @media (-webkit-min-device-pixel-ratio: 3),(min-device-pixel-ratio: 3)
    background-image: url($url + "@3x.png")

// 第二步
  
  @import "~common/stylus/mixin"

// 第三部步

   bg-image('logo')
   

设置行内块元素对齐方式

vertical-align:***

我和很喜欢这样设置初始化html body

html, body {
 line-height: 1; //这里高度是和当前设置字体大小一样的高度
 font-weight: 200;
 font-family: 'PingFang SC', 'STHeitiSC-Light', 'Helvetica-Light', arial, sans-serif, 'Droid Sans Fallback'
}

数据抽象 不同数据对应不同class从而实现不同icon


        .support
          .icon
            display: inline-block
            vertical-align: top
            width: 12px
            height: 12px
            margin-right: 4px
            background-size: 12px 12px
            background-repeat: no-repeat
            &.decrease
              bg-image('decrease_1')
            &.discount
              bg-image('discount_1')
            &.guarantee
              bg-image('guarantee_1')
            &.invoice
              bg-image('invoice_1')
            &.special
              bg-image('special_1')
  
 <span class="icon" :class="classMap[seller.supports[0].type]"></span>

this.classMap = ['decrease', 'discount', 'special', 'invoice', 'guarantee'];             

chrome 浏览器字体最小为12px

blur属性

filter: blur(10px)

clearfix

display: inline-block
&:after
  display:block
  content:''
  height: 0
  line-height: 0
  clear: both
  visibility: hidden

css sticky footer

//html
<div ckass="detail-wrapper clearfix">
   <div class="detail-main"></div>
 </div>
 <div class="detail-close"></div>
//    
.detail-wrapper
        width: 100%
        min-height: 100%
        .detail-main
          padding-bottom: 64px
.detail-close
       position: relative
       width: 32px
       height: 32px
       margin: -64px auto 0 auto
       clear: both
       font-size: 32px                 

star组件

  <div class="star" :class="starType">
    <span v-for="itemClass in itemClasses" :class="itemClass" class="star-item" track-by="$index"></span>
  </div>
    @import "../../common/stylus/mixin.styl"

  .star
    font-size: 0
    .star-item
      display: inline-block
      background-repeat: no-repeat
    &.star-48
      .star-item
        width: 20px
        height: 20px
        margin-right: 22px
        background-size: 20px 20px
        &:last-child
          margin-right: 0
        &.on
          bg-image('star48_on')
        &.half
          bg-image('star48_half')
        &.off
          bg-image('star48_off')
    &.star-36
      .star-item
        width: 15px
        height: 15px
        margin-right: 6px
        background-size: 15px 15px
        &:last-child
          margin-right: 0
        &.on
          bg-image('star36_on')
        &.half
          bg-image('star36_half')
        &.off
          bg-image('star36_off')
    &.star-24
      .star-item
        width: 10px
        height: 10px
        margin-right: 3px
        background-size: 10px 10px
        &:last-child
          margin-right: 0
        &.on
          bg-image('star24_on')
        &.half
          bg-image('star24_half')
        &.off
          bg-image('star24_off')


const LENGTH = 5;
  const CLS_ON = 'on';
  const CLS_HALF = 'half';
  const CLS_OFF = 'off';

  export default {
    props: {
      size: {
        type: Number
      },
      score: {
        type: Number
      }
    },
    computed: {
      starType() {
        return 'star-' + this.size;
      },
      itemClasses() {
        let result = [];
        let score = Math.floor(this.score * 2) / 2;
        let hasDecimal = score % 1 !== 0;
        let integer = Math.floor(score);
        for (let i = 0; i < integer; i++) {
          result.push(CLS_ON);
        }
        if (hasDecimal) {
          result.push(CLS_HALF);
        }
        while (result.length < LENGTH) {
          result.push(CLS_OFF);
        }
        return result;
      }
    }
  };

 <star :size="48" :score="seller.score"></star>

transition


<!-- 简单元素 -->
<transition>
  <div v-if="ok">toggled content</div>
</transition name="fade">
    .detail
      position: fixed
      z-index: 100
      top: 0
      left: 0
      width: 100%
      height: 100%
      overflow: auto
      transition: all 0.5s
      backdrop-filter: blur(10px)
      &.fade-transition
        opacity: 1
        background: rgba(7, 17, 27, 0.8)
      &.fade-enter, &.fade-leave
        opacity: 0
        background: rgba(7, 17, 27, 0)

flex

flex: 0 0 80px 第一个参数等分 第二个参数空间不足缩放情况 第三个参数站位空间
width: 80px

computed

    computed: {
      currentIndex() {
        for (let i = 0; i < this.listHeight.length; i++) {
          let height1 = this.listHeight[i];
          let height2 = this.listHeight[i + 1];
          if (!height2 || (this.scrollY >= height1 && this.scrollY < height2)) {
            return i;
          }
        }
        return 0;
      }
     }

$refs

this.$refs.foodsWrapper.getElementsByClassName('food-list-hook')

box-sizing

border-box
content-box

box-shadow

box-shodow: 0 4px 8px 0 rgba(0,0,0,.4)

ES6

`¥${this.minPrice}元起送`

新增或者删除某个字段的时候

Vue.set(this.food, 'count', 1)

vue派发事件

 this.$emit('give-advice', this.possibleAdvice[randomAdviceIndex])

访问组件

<child-component ref="child"></child-component>

在vue中data数据里面的名称,不要和方法名称相同

神奇css黑魔法 自适应宽高百分比

position: realtive
width: 100%
height: 0
padding-top: 100%

fromDate

export function formatDate(date, fmt) {
	if (/(y+)/.test(fmt)) {
		fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length));
	}
	let o = {
		'M+': date.getMonth() + 1,
		'd+': date.getDate(),
		'h+': date.getHours(),
		'm+': date.getMinutes(),
		's+': date.getSeconds()
	};
	for (let k in o) {
		if (new RegExp(`(${k})`).test(fmt)) {
			let str = o[k] + '';
			fmt = fmt.replace(RegExp.$1, (RegExp.$1.length === 1) ? str : padLeftZero(str));
		}
	}
	return fmt;
};

function padLeftZero(str) {
	return ('00' + str).substr(str.length);
}

解析url参数

export function urlParse() {
  let url = window.location.search;
  let obj = {};
  let reg = /[?&][^?&]+=[^?&]+/g;
  let arr = url.match(reg);
  // ['?id=12345', '&a=b']
  if (arr) {
    arr.forEach((item) => {
      let tempArr = item.substring(1).split('=');
      let key = decodeURIComponent(tempArr[0]);
      let val = decodeURIComponent(tempArr[1]);
      obj[key] = val;
    });
  }
  return obj;
};

存储本地

export function saveToLocal(id, key, value) {
	let seller = window.localStorage.__seller__;
	if (!seller) {
		seller = {};
		seller[id] = {};
	} else {
		seller = JSON.parse(seller);
		if (!seller[id]) {
			seller[id] = {};
		}
	}
	seller[id][key] = value;
	window.localStorage.__seller__ = JSON.stringify(seller);
};

export function loadFromLocal(id, key, def) {
	let seller = window.localStorage.__seller__;
	if (!seller) {
		return def;
	}
	seller = JSON.parse(seller)[id];
	if (!seller) {
		return def;
	}
	let ret = seller[key];
	return ret || def;
};

组件状态保持

keep-alive

打包vue 项目开发的项目

npm run build
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值