Vue.js仿蘑菇街项目开发

该项目基础来源于coderwhy:https://github.com/coderwhy/HYMall
我完成的项目地址:https://github.com/IronManTonyStark/Mall-Vue.js
原项目有些小bug有修复,有些地方有点改动。
总结了下学习的过程,大概如下:

一. 项目配置

1.1 目录结构

  • network->网络请求模块
  • components -> common/content
  • common
  • assets
  • router
  • store

1.2 css初始化和全局样式

  • normalize.css
  • base.css

1.3 vue.config.js和.editorconfig

  • vue.config.js->为路径配置别名
  • .editorconfig->编码格式标准

1.4 tabbar封装

  • 封装TabBar->TabBar外部的框,中间预留插槽,可插入多个选项钮

  • 封装TabBarItem->TabBar内部的图标和内容:包括激活时的图标,未激活时的图标,图标说明

  • 路由配置->为Home,Category,Cart,Profile四个组件配置路由

  • 响应点击切换设计

    • r o u t e r 和 router和 router和route的区别:router是VueRouter的一个对象,是一个全局的对象,他包含了所有的路由包含了许多关键的对象和属性。route是一个跳转的路由对象,每一个路由都会有一个route对象,是一个局部的对象。

    • this.$route.path.indexOf(this.link) !== -1
      

      判断当前所在路由进行图标的切换显示。

    •  this.$router.replace(this.link)
      

      通过replace方法来改变路由。

  • 封装完成后,在content中将Tabbar重新封装成为MainTabBar。

1.5 axios的封装

  • 导入axios

    npm install --save axios vue-axios
    
  • 创建axios实例->后续开发某些配置可能和默认实例不一样,创建新的实例,传入属于该实例的配置信息

    const instance = originAxios.create({baseURL: //请求地址,timeout: //时限ms});
    
  • 配置请求和响应拦截

    • 请求拦截的作用和使用

      • 当发送网络请求时, 在页面中添加一个loading组件, 作为动画。

      • 某些请求要求用户必须登录, 判断用户是否有token, 如果没有token跳转到login页面。

      • 对请求的参数进行序列化(看服务器是否需要序列化)。

        config.data = qs.stringify(config.data)
        
      • 使用

        instance.interceptors.request.use(config => {// console.log('来到了request拦截success中');return config}, err => {// console.log('来到了request拦截failure中');return err})
        
    • 响应拦截的作用和使用

      • 响应的成功拦截中,主要是对数据进行过滤。

      • 响应的失败拦截中,可以根据status判断报错的错误码,跳转到不同的错误提示页面。

      • 使用

        instance.interceptors.response.use(response => {// console.log('来到了response拦截success中');return response.data}, err => {console.log('来到了response拦截failure中');console.log(err);if (err && err.response) {switch (err.response.status) {case 400:err.message = '请求错误'breakcase 401:err.message = '未授权的访问'break}}return err})
        
    • 传入对象进行网络请求

      instance(option).then(res => {resolve(res)}).catch(err => {reject(err)})
      

二. 首页开发

2.1 navbar的封装和使用

  • 封装common->navbar包含三个插槽:left、center、right
  • 设置navbar相关的样式
  • 使用navbar实现首页的导航栏

2.2 请求首页的数据

  • 封装请求首页更多数据network->home.js

  • 请求多个数据:将banner数据放在banners变量中,将recommend数据放在recommends变量中

    getHomeMultidata().then(res => {this.banners = res.data[BANNER].listthis.recommends = res.data[RECOMMEND].list})
    
  • 请求商品数据:根据传入类型(POP、NEW、SELL)请求当前页码(page)对应的数据,传入到goodlist中,之后将page加1

    getHomeData(type, this.goodsList[type].page).then(res => {const goodsList = res.data.list;this.goodsList[type].list.push(...goodsList)this.goodsList[type].page += 1})
    

2.3 轮播图swiper的封装和使用

  • 封装Swiper和SwiperItem:可自己封装或使用组件库Mint UI

  • 封装对于首页的childComps->HomeSwiper

    <swiper ref="swiper" v-if="banners.length"><swiper-item v-for="(item, index) in banners" :key="index"><a :href="item.link"><img :src="item.image" alt=""></a></swiper-item></swiper>
    
  • 传入banners进行展示

     <home-swiper :banners="banners" ref="hSwiper"></home-swiper>
    

2.4 FeatureView的封装和使用

  • 封装childComps->FeatureView

    <div class="feature">    <div class="feature-item" v-for="(item, index) in features">      <a :href="item.link">        <img :src="item.image" alt="">        <div>{{item.title}}</div>      </a>    </div>  </div>js
    
  • 传入recommends数据,进行展示

    <feature-view :features="recommends"></feature-view>
    

2.5 RecommendView的封装

​ 展示图片即可。

2.6 TabControl的封装和使用

  • 封装content->TabControl

    <div class="tab-control"><div class="tab-control-item":class="{active: currentIndex === index}"@click="itemClick(index)"v-for="(item, index) in titles"><span>{{item}}</span></div></div>
    
    itemClick: function (index) {// 1.改变currentIndexthis.currentIndex = index;// 2.发出事件this.$emit('itemClick', index)
    }
    
  • 监听点击

    //默认currentType = POPtabClick(index) {switch (index) {case 0:this.currentType = POPbreakcase 1:this.currentType = NEWbreakcase 2:this.currentType = SELLbreak}
    }
    
  • 使用

     <tab-control @itemClick="tabClick":titles="['流行', '新款', '精选']"ref="tabControl"></tab-control>
    

2.7 网格布局GirdView的封装

2.8 GoodList和GoodListItem的封装和使用

  • 展示商品列表,封装childComps->GoodsList

    <grid-view><goods-list-item v-for="(item, index) in goodsList" :key="index" :goods="item"></goods-list-item></grid-view>
    
  • 列表中每一个商品,封装childComps->GoodsListItem

    • 使用vue图片懒加载v-lazy

      npm install vue-lazyload --save-dev
      
      • 在main.js中配置

        Vue.use(VueLazyload, {//预加载的高度比例preLoad: 1,//加载失败显示图片error: require('assets/img/common/error.png')//加载中显示图片loading: require('assets/img/common/placeholder.png'),//尝试次数attempt: 1
        })
        
    • 封装

      <div class="goods"><img v-lazy="getImg" :key="getImg" alt=""><div class="goods-info"><p>{{goods.title}}</p><span class="price">¥{{goods.price}}</span><span class="collect">{{goods.cfav}}</span></div></div>//getImg属性
      computed: {getImg() {return this.goods.img || this.goods.image || this.goods.show.img}}
      
    • 在Home中使用

      <goods-list :goods-list="showGoodsList"/>//showGoodsList属性
      computed: {showGoodsList() {return this.goodsList[this.currentType].list}
      },
      

2.9 滚动组件Scroll的封装

  • 安装better-scroll

    npm install better-scroll --save
    
  • 封装一个独立的组件,用于作为滚动组件:Scroll

  • 组件内代码的封装:

    • 1.创建BetterScroll对象,并且传入DOM和选项(probeType、click、pullUpLoad)

       if (!this.$refs.wrapper) returnthis.scroll = new BScroll(this.$refs.wrapper, {//监听滚动位置//0,1都是不侦测实时位置//2:只要在滚动过程中侦测,手指离开后的惯性滚动中不侦测//3: 只要是滚都,都侦测probeType: this.probeType,//better-scroll 默认会阻止浏览器的原生 click 事件。当设置为 true,better-scroll 会派发一个 click 事件,我们会给派发的 event 参数加一个私有属性 _constructed,值为 true。click: true,//这个配置用于做下拉刷新功能,默认为 false。当设置为 true 或者是一个 Object 的时候,可以开启下拉刷新,pullUpLoad: this.pullUpLoad})
      
    • 2.监听scroll事件,该事件会返回一个position

      this.scroll.on('scroll', pos => {this.$emit('scroll', pos)
      })
      
    • 3.监听pullingUp事件,监听到该事件进行上拉加载更多

      this.scroll.on('pullingUp', () => {console.log('上拉加载');this.$emit('pullingUp')
      })
      
    • 4.封装刷新的方法:this.scroll.refresh()

      refresh() {this.scroll && this.scroll.refresh && this.scroll.refresh()
      },
      
    • 5.封装滚动的方法:this.scroll.scrollTo(x, y, time)

      this.scroll && this.scroll.scrollTo && this.scroll.scrollTo(x, y, time)
      
    • 6.封装完成刷新的方法:this.scroll.finishedPullUp

      this.scroll && this.scroll.finishPullUp && this.scroll.finishPullUp()
      

2.10 上拉加载更多

  • 通过Scroll监听上拉加载更多。

    //触发时机:在一次上拉加载的动作后,这个时机一般用来去后端请求数据。
    @pullingUp="loadMore"
    
  • 在Home中加载更多的数据。

    loadMore() {this.getHomeProducts(this.currentType)
    },
    
  • 请求数据完成后,调动finishedPullUp

    this.$refs.scroll.finishPullUp()
    

2.11 返回顶部按钮

  • 封装BackTop组件

    <div class="back-top" @click="topClick"><slot></slot>
    </div>methods: {topClick: function () {this.$emit('backTop');}}
    
  • 定义一个常量,用于决定在什么数值下显示BackTop组件

    this.showBackTop = position.y < -BACKTOP_DISTANCE
    
  • 监听滚动,决定BackTop的显示和隐藏

    v-show="showBackTop"
    
  • 监听BackTop的点击,点击时,调用scrollTo返回顶部

    backTop() {this.$refs.scroll.scrollTo(0, 0, 300)
    },
    

2.12 tabControl的停留

  • 重新添加一个tabControl组件(需要设置定位,否则会被盖住)

  • 在updated钩子中获取tabControl的offsetTop

    updated() {this.$nextTick(() => {this.tabOffsetTop = this.$refs.tabControl.$el.offsetTop})
    },
    
  • 判断是否滚动超过了offsetTop来决定是否显示新添加的tabControl

    this.isTabFixed = position.y < -this.tabOffsetTop
    

2.13 关于滚动的问题(事件总线,防抖函数)

  • 若使用v-lazy懒加载,目前还没出现这个问题。
  • Better-Scroll在决定有多少区域可以滚动时, 是根据scrollerHeight属性决定

    • scrollerHeight属性是根据放Better-Scroll的content中的子组件的高度
    • 但是我们的首页中, 刚开始在计算scrollerHeight属性时, 是没有将图片计算在内的
    • 所以, 计算出来的告诉是错误的(1300+)
    • 后来图片加载进来之后有了新的高度, 但是scrollerHeight属性并没有进行更新
    • 所以滚动出现了问题
  • 如何解决这个问题了?

    • 监听每一张图片是否加载完成, 只要有一张图片加载完成了, 执行一次refresh()
    • 如何监听图片加载完成了?
      • 原生的js监听图片: img.onload = function() {}
      • Vue中监听: @load=‘方法’
    • 调用scroll的refresh()
  • 监听每一张图片是否加载完成, 只要有一张图片加载完成了, 执行一次refresh()

  • Vue监听图片加载完成:@load=‘方法’

  • 调用scroll的refresh()

mounted() {// 1.图片加载完成的事件监听const refresh = debounce(this.$refs.scroll.refresh, 50)this.$bus.$on('itemImageLoad', () => {refresh()})},
  • 如何将GoodsListItem.vue中的事件传入到Home.vue中

    • 因为涉及到非父子组件的通信, 所以这里我们选择了事件总线

      • bus ->总线
      • Vue.prototype.$bus = new Vue()
      • this.bus.emit(‘事件名称’, 参数)
      • this.bus.on(‘事件名称’, 回调函数(参数))
  • 对于refresh非常频繁的问题, 进行防抖操作

    • 防抖debounce/节流throttle
    • 防抖函数起作用的过程:
      • 如果我们直接执行refresh, 那么refresh函数会被执行30次.
      • 可以将refresh函数传入到debounce函数中, 生成一个新的函数.
      • 之后在调用非常频繁的时候, 就使用新生成的函数.
      • 而新生成的函数, 并不会非常频繁的调用, 如果下一次执行来的非常快, 那么会将上一次取消掉
    debounce(func, delay) {let timer = nullreturn function (...args) {if (timer) clearTimeout(timer)timer = setTimeout(() => {func.apply(this, args)}, delay)}},
    

2.16 Home离开时记录状态和位置

  • 为路由器设施keep-alive属性

  • 离开时

    • 保存位置信息saveY
    • 停止轮播图
    deactivated() {this.$refs.hSwiper.stopTimer()this.saveY = this.$refs.scroll.getScrollY()},
    
  • 进入时

    • 读取位置信息,最好做一次refresh()
    • 开启轮播图
    activated() {this.$refs.hSwiper.startTimer()this.$refs.scroll.scrollTo(0, this.saveY, 0)this.$refs.scroll.refresh()},
    

三. 详情页开发

3.1 点击GoodListItem跳转到详情页并且携带iid

  • 创建views->detail组件,并配置路由

  • 监听GoodListItem点击

     goToDetail () {// 1.获取iidlet iid = this.goods.iid;// 2.跳转到详情页面this.$router.push({path: '/detail', query: {iid}})}
    

3.2 导航栏的封装

  • 在navbar的基础上封装detail->childComps->DetailNavBar
  • 插槽左边放返回图标,中部放文字信息

3.3 请求详情页数据(与首页类似)

  • 封装请求详情页数据network->detail.js
  • 将所要展示的信息封装为Goods、GoodsParam、Shop三个类导出
  • 在Detail的methods中创建将请求的数据保存的方法,在create( )中进行调用

3.4 详情页轮播图展示(与首页类似)

  • 在swiper的基础上封装childComps->DetailSwiper
  • 传入数据进行展示

3.5 商品基本信息展示GoodsBaseInfo

  • 封装childComps->GoodsBaseInfo
  • 根据传入的goods对象展示名字、价格、销量、服务等信息
  • 注意CSS的设计

3.6 加入滚动效果Scroll

  • 将TabBar隐藏
  • 注意CSS样式

3.7 展示更多信息(与GoodsBaseInfo类似)

  • 店铺信息DetailShopInfo
  • 商品图片信息DetailGoodsInfo
  • 商品参数信息DetailParamInfo
  • 商品评论信息DetailCommentInfo

  • 热门推荐信息DetailRecommendInfo

3.8 点击标题滚到固定内容

  • DetailNavBar向Detail发送点击事件

     itemClick: function (index) {this.$emit('itemClick', index)},
    
  • 创建数组themeTops来获取每个标题的offsetTop

  • 获取offsetTop,在updated()中进行调用(小bug:图片加载问题会导致获取错误的位置,有时点击两次才能到正确位置)

    _getOffsetTops() {this.themeTops = []this.themeTops.push(this.$refs.base.$el.offsetTop)this.themeTops.push(this.$refs.param.$el.offsetTop)this.themeTops.push(this.$refs.comment.$el.offsetTop)this.themeTops.push(this.$refs.recommend.$el.offsetTop)},
    
  • 监听点击事件

    titleClick(index) {//console.log(this.themeTops[index])this.$refs.scroll.scrollTo(0, -this.themeTops[index], 100)},
    

3.9 滚动内容显示对应标题

  • 监听滚动事件

    • 为themeTops最后添加一个很大的值,用于和最后一个主题的top进行比较

      this.themeTops.push(Number.MAX_VALUE)
      
    • 根据滚动位置来确定currentIndex

      _listenScrollTheme(position) {let length = this.themeTops.length;for (let i = 0; i < length; i++) {let iPos = this.themeTops[i];if (position >= iPos && position < this.themeTops[i+1]) {if (this.currentIndex !== i) {this.currentIndex = i;}break;}}},
      

3.10 底部工具栏DetailBottomBar的封装

  • 为工具栏添加图标和内容
  • 注意CSS设计

3.11 回到顶部按钮BackTop的混入封装

  • 导入content -> BackTop

  • 与Home类似进行使用

  • 因为在Home和Detail有大量重复的关于BackTop的代码,于是把他们提取出来放到mixin.js中

    export const backTopMixin = {data() {return {showBackTop: false}},components: {BackTop},methods: {backTop: function () {this.$refs.scroll.scrollTo(0, 0, 300);}}
    }
    

四. 购物车开发

4.1 监听加入购物车点击和获取商品信息

  • 在DetailBottomBar中向父组件Detail发出点击事件

    addToCart() {this.$emit('addToCart')}
    
  • 创建对象,获取加入购物车的商品所需要的信息

    const obj = {}
    obj.iid = this.iid;
    obj.imgURL = this.topImages[0]
    obj.title = this.goods.title
    obj.desc = this.goods.desc;
    obj.newPrice = this.goods.nowPrice;
    

4.2 将商品添加到store

  • 在Store的state属性中创建cartList数组来保存加入购物车的商品

  • 在actions中实现addCart方法

    • 为什么不在mutations中实现?

      mutations唯一的目的就是修改state中的状态,里面的方法完成的事件比较单一一点,该方法有判断条件,放到actions中较好

    addCart(context, info) {//console.log(info);// 1.查看是否添加过let oldInfo = context.state.cartList.find(item => item.iid === info.iid)// 2.+1或者新添加if (oldInfo) {//oldInfo.count += 1context.commit('addCounter', oldInfo)} else {info.count = 1context.commit('addToCart', info)}}
    
    • mutations中的方法

      addCounter(state, oldInfo) {oldInfo.count ++;},addToCart(state, info) {state.cartList.push(info)}
      
  • 在Detail中将商品对象添加到Store中

    this.$store.dispatch('addCart', obj)
    

4.3 购物车导航栏实现

  • 导入commen->NavBar使用

    <nav-bar class="nav-bar"><div slot="center">购物车({{count}})</div></nav-bar>
    
  • 从getters中获取cartList和cartCount

    cartList(state) {return state.cartList},
    cartCount(state, getters) {return getters.cartList.length
    }
    
  • 在Cart中使用mapGetters将getters中的方法变为计算属性直接使用

    • 导入

      import { mapGetters } from 'vuex'
      
    • 使用

      computed: {...mapGetters({count: 'cartCount',})}
      

4.4 购物车商品列表展示CartList和CartListItem

  • 在CartList中使用mapGetters获取cartList数据

  • 封装展示每件商品的组件GoodListItem,将CartList中的数据进行展示

  • 封装勾选按钮checkButton,在CartlistItem中使用

    • 在actions中为商品添加Checked属性,默认为false(未选中)

      info.checked = false
      
    • 在CheckButton中接受checked来确定商品是否被选中,用watch来检测变化(也可用计算属性)

            props: {value: {type: Boolean,default: true}},data() {return {checked: this.value}},watch: {value(newValue) {this.checked = newValue;}}
      
    • 发出点击事件

      selectItem: function () {this.$emit('checkBtnClick')
      }
      
    • 在CartListItem中使用

      <CheckButton @checkBtnClick="checkedChange" :value="itemInfo.checked"/>checkedChange() {this.itemInfo.checked = !this.itemInfo.checked;
      }
      
  • 添加滚动效果

    • 滚动的内容必须用

      包裹起来,否则Better-scroll会报错
       <scroll class="cart-list" ref="scroll"><div><cart-list-item v-for="item in list" :key="item.iid" :item-info="item"></cart-list-item></div></scroll>
      
    • 在activated中添加refersh()函数,解决滚动不了的问题

      activated() {this.$refs.scroll.refresh()}
      

4.5 购物车底部工具栏封装

  • 导入CheckButton封装全选按钮

    • 监听点击事件

      • 计算属性isSelectAll与value绑定判断是否有未选中的按钮

        isSelectAll() {return this.$store.getters.cartList.find(item => item.checked === false) === undefined;}
        
      • 点击事件

        checkBtnClick: function () {// 1.判断是否有未选中的按钮let isSelectAll = this.$store.getters.cartList.find(item => !item.checked);// 2.有未选中的内容, 则全部选中if (isSelectAll) {this.$store.state.cartList.forEach(item => {item.checked = true;});} else {this.$store.state.cartList.forEach(item => {item.checked = false;});}}
        
    • 计算总价(过滤filter和累积reduce)

      totalPrice() {const cartList = this.$store.getters.cartList;return cartList.filter(item => {return item.checked}).reduce((preValue, item) => {return preValue + item.count * item.newPrice}, 0).toFixed(2)},
      
    • 总数

      $store.getters.cartCount
      

五. 分类页开发

5.1 分类页导航栏使用

  • 引入NvaBar组件进行使用(与购物车类似)

5.2 分类页面数据请求

  • 封装请求分类页数据network->category.js

  • 在Category中保存请求的数据

    • getCategory

      _getCategory() {getCategory().then(res => {// 1.获取分类数据this.categories = res.data.category.list// 2.初始化每个类别的子数据for (let i = 0; i < this.categories.length; i++) {this.categoryData[i] = {subcategories: {},categoryDetail: {'pop': [],'new': [],'sell': []}}}// 3.请求第一个分类的数据this._getSubcategories(0)})},
      
    • getSubcategories

      _getSubcategories(index) {this.currentIndex = index;const mailKey = this.categories[index].maitKey;getSubcategory(mailKey).then(res => {this.categoryData[index].subcategories = res.datathis.categoryData = {...this.categoryData}this._getCategoryDetail(POP)this._getCategoryDetail(SELL)this._getCategoryDetail(NEW)})},
      
    • getCategoryDetail

      _getCategoryDetail(type) {// 1.获取请求的miniWallkeyconst miniWallkey = this.categories[this.currentIndex].miniWallkey;// 2.发送请求,传入miniWallkey和typegetCategoryDetail(miniWallkey, type).then(res => {// 3.将获取的数据保存下来this.categoryData[this.currentIndex].categoryDetail[type] = resthis.categoryData = {...this.categoryData}})},
      

5.3 分类侧边栏TabMenu封装和使用

  • 传入分类栏的数据进行展示
  • 监听点击事件,根据点击切换效果,并传出点击事件
<div class="menu-list-item":class="{active: index===currentIndex}"v-for="(item, index) in categories":key="index"@click="itemClick(index)">{{item.title}}</div>itemClick(index) {this.currentIndex = indexthis.$emit('selectItem', index)}
  • 为分类侧边栏添加滚动效果
  • 在Category中接收到点击事件请求展示响应的数据
selectItem(index) {this._getSubcategories(index)}

5.4 分类数据展示—TabContentCategory的封装和使用

  • 传入数据进行展示
  • 网格布局
  • 添加滚动效果

5.5 分类数据展示—TabControl和TabContentDetail的封装和使用

  • 将TabControl混合封装到mixin.js后引入

    export const tabControlMixin = {components: {TabControl},data: function () {return {currentType: POP}},methods: {tabClick(index) {switch (index) {case 0:this.currentType = POPbreakcase 1:this.currentType = NEWbreakcase 2:this.currentType = SELLbreak}console.log(this.currentType);}}
    }
    
    import {tabControlMixin} from "@/common/mixin";mixins: [tabControlMixin],
    
  • 使用TabControl

    <tab-control :titles="['综合', '新品', '销量']"@itemClick="tabClick"/>
    

  • 传入CategoryDetail的数据
  • 与首页类似,引入GoodListItem封装TabContentDetail
  • 网格布局,展示数据

六. 个人页面开发

6.1 个人页导航栏使用

  • 引入NavBar(与前面类似)

6.2 用户信息UseInfo封装

  • 所用到的图标都封装到content->Icon中

  • 在App中注册使用Icom和SvgIcon

  • 将用户信息进行排布,预留相应的插槽(如头像,名字,手机号等)

6.3 用户的优惠、余额和积分显示

  • 需要传过多的参数,目前还无数据,为封装
  • 注意CSS样式

6.4 功能列表ListView的封装和使用

  • 根据传入的图标和文字进行功能栏的展示
  • 注意CSS样式
  • 使用
<list-view :list-data="orderList" class="order-list"></list-view>
<list-view :list-data="serviceList" class="service-list"></list-view>

Vue学习笔记(二):购物街开发相关推荐

  1. amazeui学习笔记二(进阶开发4)--JavaScript规范Rules

    amazeui学习笔记二(进阶开发4)--JavaScript规范Rules 一.总结 1.注释规范总原则: As short as possible(如无必要,勿增注释):尽量提高代码本身的清晰性. ...

  2. amazeui学习笔记二(进阶开发2)--Web组件简介Web Component

    amazeui学习笔记二(进阶开发2)--Web组件简介Web Component 一.总结 1.amaze ui:amaze ui是一个web 组件, 由模板(hbs).样式(LESS).交互(JS ...

  3. Vue学习笔记01:准备开发与调试环境

    文章目录 一.安装Vue.js (一)使用独立版本 1.开发版本 2.生产版本 3.案例演示 (二)使用CDN方式 1.采用 Staticfile CDN 2.案例演示 (三)使用NPM方式 1.安装 ...

  4. CSS学习笔记(二) 移动WEB开发

    思维导图 文章目录 思维导图 1. 移动端基础 1.1 浏览器现状 1.2 手机屏幕现状 1.3 移动端调试方法 2. 视口 2.1 布局视口 2.2 视觉视口 2.3 理想视口 2.4 视口总结 2 ...

  5. 少侠请重新来过 - Vue学习笔记(二) - Vue生命周期

    Vue 生命周期和钩子 每一个vue实例创建时,会经历一段初始化的过程,同时会调用其生命周期钩子,实例的钩子this指向它的Vue实例,不需要在钩子用箭头函数. <template>< ...

  6. Vue学习笔记之16-tarbar地开发思路

    页面下方有一个单独的TabBar组件, 如何封装 自定义TabBar组件, 在App组件中使用 让TabBar处在底部, 并且在 .vue文件中的style标签中设置相关的样式 页面中会有很多公共的样 ...

  7. Vue学习笔记01——Vue开发基础

    一.Vue实例配置选项 选项 说明 data Vue实例数据对象 methods 定义Vue中的方法 components 定义子组件 computed 计算属性 filters 过滤器 el 唯一根 ...

  8. Vue学习笔记(二)组件化和模块化

    Vue学习笔记(二)组件化和模块化 前言 组件化 什么是组件化 1.基础使用 2.全局组件和局部组件 3.语法糖和模板抽离 4.组件的data为什么是函数 5.父子组件 5.1 父子组件 5.2 父子 ...

  9. Polyworks脚本开发学习笔记(二十)-补充几个常见操作指令的使用

    Polyworks脚本开发学习笔记(二十)-补充几个常见操作指令的使用 大概要写到结尾了,最后几篇就将手册的各常用命令再看一遍,组合一下,并列举出常见的一些有用的操作. DATA_COLOR_MAP数 ...

  10. Polyworks脚本开发学习笔记(二)-TREEVIEW基本操作

    Polyworks脚本开发学习笔记(二)-TREEVIEW对象基本操作 TREEVIEW对象选择 选择/不选对象 TREEVIEW OBJECT SELECT ALL 全部对象选择,包括参考/数据/对 ...

最新文章

  1. HardwareSoftwareTutorial
  2. art-template入门(六)之解析规则
  3. js压缩图片_Web 性能优化: 图片优化让网站大小减少 62%
  4. java 手写签名_Android 自定义View手写签名并保存图片
  5. linux命令行如何上翻,Linux学习教程-获取可用命令行参数 or 文件上下翻转和左右翻转...
  6. 解读边缘计算在7大领域的研究趋势和最新进展
  7. 自动驾驶 9-5: EKF 的局限性 Limitations of the EKF
  8. 据说这些基础知识90%的人都回答错了,你呢?
  9. html圆形圆心坐标,圆心坐标公式
  10. 使用Setup Factory把java应用打包成安装软件并更改默认安装路径
  11. 基于聚类分析和因子分析的空气质量研究
  12. H3CIE-----这只是一个过程!
  13. *ST东方A:山重水复疑无路 强烈推荐评级
  14. 20190406-楞次定律、洛伦兹力与安培力、切割磁感线过程中的能量关系
  15. 深圳大厂程序员自述:我37岁,年薪百万,等着被公司干掉!
  16. 视觉技术再赋能,深眸科技一体化解决方案引领工业视觉机器人落地应用
  17. mysql的查询分析工具下载_万能数据库查询分析器(ODBC数据库查询分析工具)V7.03 最新版...
  18. 项目如何在Linux系统后台运行以及调回前台运行
  19. 危化品柜颜色如何区分?
  20. 用excel做anova分析

热门文章

  1. 技术大咖云集,GIAC 2017全球互联网架构大会圆满落幕
  2. 小马哥---高仿三星n9100刷机 单双卡主板外观机型对比,分n910f n9100 n910c 拆机主板详图
  3. 最简单DIY基于ESP32CAM的物联网相机系统②(在JAVAWEB服务器实现图片查看器)
  4. 开源协议比较(BSD,Apache,GPL,LGPL,AGPL,MIT)
  5. CentOS/Debian/Ubuntu永久保存iptables配置规则
  6. 【观察】新华三Oasis Cloud-Net绿洲云简网络解决方案:开箱即用打通网络建设“最后一公里”...
  7. Windows网络通信流量和网速监控设计(一)
  8. 耶鲁大学《博弈论》课程——逆向归纳
  9. CentOS 7 服务器配置NTP服务(chrony)
  10. vmware 显示器一拖二