美文网首页Vue.js学习JavaScript 进阶营
VUE进阶笔记(3) -购物车解析

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

作者: woow_wu7 | 来源:发表于2017-08-29 18:51 被阅读59次

    (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>
    
    购物车 购物车地址

    相关文章

      网友评论

        本文标题:VUE进阶笔记(3) -购物车解析

        本文链接:https://www.haomeiwen.com/subject/zuhidxtx.html