VUE进阶笔记(3) -购物车解析

(1) 构建VUE实例

cart.js
--------

var vm = new Vue({   //实例对象,注意Vue首字母要大写。一般用vm (ViewModel 的简称) 这个变量名表示 Vue 实例
    el:"#app",    //dom挂载点
    data: { },  //data对象中放初始化的数据,相当于react中的state中的数据
    filters:{ }, //局部过滤器
    mounted: function() { } //钩子函数,相当于react中的componentDidMount,数据渲染完成时,将做的事情
    methods: { },  //方法函数
})

(2) v-for指令

v-for
-------

语法:(item, index) in items           //这里的in也可以写成of   即( item of items )
item:item是数组元素迭代的别名。
index: index是数组元素的索引值。
items:items 是源数据数组
v-for 对象迭代
-------
你也可以用 v-for 通过一个对象的属性来迭代

html

<div id="app">
    <div v-for="(value, key, index) in age">
         {{ index }}. {{ key }} : {{ value }}
    </div>
</div>

第一个参数value:键值
第二个参数key:键名
第三个参数index:索引

以上的输出结果为:
0. firstName : John
1. lastName : Doe
2. ages : 30
---------------------------------------------------------

js

 var vm = new Vue({
    el:'#app',
    data:{
        age:{
            firstName: 'John',
            lastName: 'Doe',
            ages: 30
        }
    },

});

(3) 用axios.get() 发送get请求

var vm = new Vue({
    el:'#app',
    data:{
        porductList: []
    },
    filters: {

    },
    mounted: function() {
        this.cartView();
    },
    methods: {
        cartView: function() {
            axios.get('data/cartData.json')
                // .get('http://api.tianapi.com/meinv/?key=510b4ed16cb0b11b6ccfb7f3236fa8a6&num=10')
                .then( response => {
                    // console.log(response);
                    this.porductList = response.data.result.list;
                    // console.log(this.porductList)
                })
                .catch( err => { console.log(err) })
        }
    }

});

(4)点击+-号实现购买数量的+-,input输入框的数据双向绑定

html

<div class="quentity">
      <a href="javascript:;" v-on:click="changeMoney(product,-1)">-</a>
      <input type="text" v-model="product.productQuentity" disabled>
      <a href="javascript:;" v-on:click="changeMoney(product,1)">+</a>
</div>

----------------------------------
js

  changeMoney: function(product,choose) {  
            if( choose == 1){
                product.productQuentity++;
            }else if( choose == -1){
                product.productQuentity--;
                if(product.productQuentity < 1) {
                    product.productQuentity = 1;
                }
            }
        }

(5) v-bind指令

( prop: 给img绑定src属性,给元素绑定class,style属性等 )

.prop - 被用于绑定 DOM 属性。(what’s the difference?)
.camel - (2.1.0+) 将 kebab-case 特性名转换为 camelCase. (从 2.1.0 开始支持)
.sync (2.3.0+) 语法糖,会扩展成一个更新父组件绑定值的 v-on 侦听器。


购物车中的例子:
![](product.productImage)
<div  id="showOverLay" v-bind:class="{ 'md-overlay': showModal }"></div>


官网的例子:
<!-- 绑定一个属性 -->
![](imageSrc)

<!-- 缩写 -->
![](imageSrc)

<!-- 内联字符串拼接 -->
![]('/path/to/images/' + fileName)

<!-- class 绑定 -->
<div :class="{ red: isRed }"></div>
<div :class="[classA, classB]"></div>
<div :class="[classA, { classB: isB, classC: isC }]">

<!-- style 绑定 -->
<div :style="{ fontSize: size + 'px' }"></div>
<div :style="[styleObjectA, styleObjectB]"></div>

<!-- 绑定一个有属性的对象 -->
<div v-bind="{ id: someProp, 'other-attr': otherProp }"></div>

<!-- 通过 prop 修饰符绑定 DOM 属性 -->
<div v-bind:text-content.prop="text"></div>

<!-- prop 绑定。“prop”必须在 my-component 中声明。-->
<my-component :prop="someThing"></my-component>

<!-- 通过 $props 将父组件的 props 一起传给子组件 -->
<child-component v-bind="$props"></child-component>

<!-- XLink -->
<svg><a :xlink:special="foo"></a></svg>
.camel 修饰符允许在使用 DOM 模板时将 v-bind 属性名称驼峰化,例如 SVG 的 viewBox 属性:
<svg :view-box.camel="viewBox"></svg>

(6)mounted钩子函和this.$nextTick(vue.nextTick)的关系

  • 当数据修改之后,DOM没有立即更新,这个之后执行函数将是异步的,所以要想在DOM更新后立即执行函数的话,需要用到Vue.nextTick(),在组件内部一般使用this.$nextTick()
    mounted: function() {
        this.$nextTick(function() {
             // 代码保证 this.$el 在 document 中
            // this.cartView();
            vm.cartView();
        });
    }
使用 mounted 并不能保证钩子函数中的 this.$el 在 document 中。
为此还应该引入 Vue.nextTick/vm.$nextTick

 Vue.nextTick( [callback, context] ) 

 作用:在下次 DOM 更新循环结束之后执行延迟回调。
 用法:在修改数据之后立即使用这个方法,获取更新后的 DOM。

 // 修改数据
vm.msg = 'Hello'
// DOM 还没有更新
Vue.nextTick(function () {
  // DOM 更新了
})

---------------------------------------------

在组件内部一般使用this.$nextTick()

Vue.component('example', {
  template: '<span>{{ message }}</span>',
  data: function () {
    return {
      message: '没有更新'
    }
  },
  methods: {
    updateMessage: function () {
      this.message = '更新完成'
      console.log(this.$el.textContent) // => '没有更新'
      this.$nextTick(function () {
        console.log(this.$el.textContent) // => '更新完成'
      })
    }
  }
})

(6) 用filter过滤器对金额做(单位,小数)等处理

  • 全局过滤器vue.filter():所有页面都能使用
  • 局部过滤器filters: { } :只能在当前实例使用
局部过滤器:

js

filters: {
        formatMoney: function(value, params) {  //value是默认参数,params是需要传入的参数
            return "¥" + value.toFixed(2) + params;
        }
    }
------------------------------
html

<div class="item-price" >{{ product.productPrice | formatMoney('') }}</div>

<div class="item-price-total">
   {{product.productPrice*product.productQuentity | formatMoney('元') }}
</div>

----------

输出结果:¥xx.00
输出结果:¥xx.00元

全局过滤器:

Vue.filter( id, [definition] )
--------------------------------------

参数:
- {string} id
- {Function} [definition]
--------------------------------------

用法:
// 注册
Vue.filter('my-filter', function (value) {
  // 返回处理后的值
})

// getter,返回已注册的过滤器
var myFilter = Vue.filter('my-filter')
-------------------------------------------
例子:
Vue.filter('formatMoney', function(value,type) {
      return "¥ "+value.toFixed(2) + type;
} )

(7)单选功能

  • 注意:因为单选是在循环列表中,所以不能直接在data里面加状态变量,需要在data中的productList数组中添加checked状态变量

html

<div class="cart-item-check">
    <a href="javascipt:;" class="item-check-btn"
         v-bind:class="{ 'check': product.checked }"  //控制ui显示隐藏的状态
         v-on:click="selectedProduct(product)"   //单选功能函数
    >
         <svg class="icon icon-ok"><use xlink:href="#icon-ok"></use></svg>
   </a>
</div>

------------------------------------------

js

   selectedProduct: function(product) {
    if(typeof product.checked == 'undefined') {
        Vue.set(product,'checked',true)
    } else {
        product.checked = !product.checked
    }
     this.calculateTotalMoney();   //计算总金额
 }

(8)全选功能和全部删除功能


html

<div class="cart-foot-l">
   <div class="item-all-check">
      <a href="javascipt:;" v-on:click="checkAll(true)">
          <span class="item-check-btn" v-bind:class="{ 'check': checkedAll }">
              <svg class="icon icon-ok"><use xlink:href="#icon-ok"></use></svg>
          </span>
          <span>全选</span>
      </a>
   </div>
   <div class="item-all-del">
     <a href="javascipt:;" class="item-del-btn" v-on:click="checkAll(false)">
                                取消全选
     </a>
 </div>
</div>
----------------------------------------------

js

data:{
        productList: [],
        showModal: false,
        checkedAll: false, //循环列表中的class状态不能在data中定义,因为是个循环
        totalMoneys:10
    },



checkAll: function(bool) {
            this.checkedAll = bool;
            this.productList.forEach( ( porduct,index ) => {
                if(typeof porduct.checked == 'undefined'){
                    Vue.set(porduct,'checked',this.checkedAll)
                }else{
                    porduct.checked = this.checkedAll;
                }
            });
            this.calculateTotalMoney();
        },
calculateTotalMoney:function() {
            this.totalMoneys = 0 ; //必须先清零,防止重复点击的情况
            this.productList.forEach( (item,index) => {
                if(item.checked){  //这里必须筛选出选中状态,切记记记记记记记记记记记                   
                    this.totalMoneys += item.productPrice * item.productQuentity;
                }
            } )
        }

(9)删除功能

  • (1) indexOf()

indexOf() 方法可返回某个指定的字符串值在字符串中首次出现的位置。

stringObject.indexOf(searchvalue,fromindex)
- searchvalue:必需。规定需检索的字符串值。
- fromindex:可选的整数参数。规定在字符串中开始检索的位置。
  它的合法取值是 0 到 stringObject.length - 1。如省略该参数,则将从字符串的首字符开始检索。

注释:indexOf() 方法对大小写敏感!
注释:如果要检索的字符串值没有出现,则该方法返回 -1。

例子:
<script type="text/javascript">
var str="Hello world!"
document.write(str.indexOf("Hello") + "<br />")
document.write(str.indexOf("World") + "<br />")  //没有出现 world+空格 
document.write(str.indexOf("world"))
</script>

输出结果:
0
-1
6
  • (2) splice()
splice():

arrayObject.splice(index,howmany,item1,.....,itemX)

- index :必需。整数,规定添加/删除项目的位置,使用负数可从数组结尾处规定位置。
- howmany:必需。要删除的项目数量。如果设置为 0,则不会删除项目。
- item1, ..., itemX:可选。向数组添加的新项目

购物车删除案列:


js部分

    delateConfirm: function(product) {
            this.showModal = true;
            this.currentItem = product;
        },
    delProduct: function() {
            this.showModal = false;
            var index = this.productList.indexOf(this.currentItem);
                 //在productList中检索this.currentItem第一次出现的位置
            this.productList.splice(index,1); //删除的位置是index,数量是1,返回被删除的项目
            this.calculateTotalMoney(); //删除后,重新计算总价格
        }

-------------------

html

 <div class="md-modal modal-msg md-modal-transition" 
         id="showModal" 
         v-bind:class="{ 'md-show': showModal }"
 >
            <div class="md-modal-inner">
                <div class="md-top">
                    <button class="md-close" v-on:click="showModal=false">关闭</button>
                </div>
                <div class="md-content">
                    <div class="confirm-tips">
                        <p id="cusLanInfo" lan="Cart.Del.Confirm">你确认删除此订单信息吗?</p>
                    </div>
                    <div class="btn-wrap col-2">
                        <button class="btn btn--m" id="btnModalConfirm" v-on:click="delProduct()">Yes</button>
                        <button class="btn btn--m btn--red" id="btnModalCancel"v-on:click="showModal=false">No</button>
                    </div>
                </div>
            </div>
        </div>

(10) v-for循环列表的item数量控制

( computed计算属性 ) ( slice分割数组 )

  • slice() 方法可从已有的数组中返回选定的元素。

arrayObject.slice(start,end)   //分割数组,对比: (   splice() 删除数组   )

返回值
返回一个新的数组,包含从 start 到 end (不包括该元素)的 arrayObject 中的元素。

说明
请注意,该方法并不会修改数组,而是返回一个子数组。
如果想删除数组中的一段元素,应该使用方法 Array.splice()。

(1) start:必需。
规定从何处开始选取。如果是负数,那么它规定从数组尾部开始算起的位置。
也就是说,-1 指最后一个元素,-2 指倒数第二个元素,以此类推。

(2) end:可选。
规定从何处结束选取。该参数是数组片断结束处的数组下标。如果没有指定该参数,
那么切分的数组包含从 start 到数组结束的所有元素。
如果这个参数是负数,那么它规定的是从数组尾部开始算起的元素。

下面是购物车选址实例:

js

computed: {
        filteAddress:function (){
            return this.addressList.slice(0,3)        }
    },
//addressList是请求的json数据,存放在data中

//这里需要注意:
// slice()  返回的是全新的数组,不会破坏原数组addressList。
// splice() 会对addressList直接进行删除操作。

--------------------------------------

html

 <li v-for=" (item,index) in filteAddress ">

(11) 点击more加载所有的地址列表

js部分


 var vm = new Vue({
    el:".container",
    data: {
        addressList: [],
        addressLength:3
    },
    computed: {
        filteAddress:function (){
            return this.addressList.slice(0,this.addressLength)
        }
    },
    methods: {
        showAllAddresss: function() {
            // return this.addressList; 这里不能直接返回addressList,因为循环的是filteAddress
            this.addressLength = this.addressList.length;   //改变data从而改变computed
        }
    }
});
----------------------------------------------------



html部分

 <div class="shipping-addr-more" v-on:click="showAllAddresss()">
            ...
 </div>
--------------------

也可以在click中直接写表达式,如下面这样:
 <div class="shipping-addr-more" v-on:click="addressLength = addressList.length">
            ...
 </div>


注意:在指令里面( v-xxx ),在视图view中 ( html )中都不要使用this
注意:在指令里面( v-xxx ),在视图view中 ( html )中都不要使用this
注意:在指令里面( v-xxx ),在视图view中 ( html )中都不要使用this

(12) 点击选中某一个卡片

  <li v-for=" (item,index) in filteAddress "
      v-bind:class="{ 'check' : index == currentCard }"
      v-on:click=" currentCard = index"
  >

解析: 
当点击某个卡片的时候,让该卡片的 index 赋值给currentCard 变量,
而当index==currentCard ,就出现check的ui状态

(12) 设为默认卡片

js部分:

setDefaultAddress: function(addressId) {
            this.addressList.forEach( (item,index) => {
                if( item.addressId == addressId ){
                    item.isDefault = true
                }else{
                    item.isDefault = false
                }
            })
        }
-----------------------------------------------

html部分

  <div class="addr-opration addr-set-default"
       v-if="!item.isDefault"
       v-on:click="setDefaultAddress(item.addressId)"
   >
     <a href="javascript:;" class="addr-set-default-btn" ><i>设为默认</i></a>
 </div>

 <div class="addr-opration addr-default" v-if="item.isDefault">默认地址</div>

解析: 

如果点击的是第三个卡片,传过来的卡片的id=3,
而在循环addressList中,假如正在循环的是第一个卡片,那么卡片id是1,
  1 != 3,
所以执行:item.isDefault = false,所以第一个卡片不显示(默认地址)

(13) 只切换两张选项卡

  <ul>
      <li  v-bind:class="{'check': switchPeisong == 1 }" v-on:click=" switchPeisong = 1">
            <div class="name" >标准配送</div>
             <div class="price">Free</div>
      </li>
      <li  v-bind:class="{'check': switchPeisong == 2 }" v-on:click=" switchPeisong = 2">
              <div class="name">高级配送</div>
              <div class="price">180</div>
      </li>
  </ul>
购物车
购物车地址
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,928评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,192评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,468评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,186评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,295评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,374评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,403评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,186评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,610评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,906评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,075评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,755评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,393评论 3 320
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,079评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,313评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,934评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,963评论 2 351

推荐阅读更多精彩内容