天天看点

商城项目 pc----商品详情页vue路由滚动行为排他思想放大镜 加入购物车操作浏览器缓存window.sessionStorage

目录

vue路由滚动行为

排他思想

放大镜

 加入购物车操作

项目实战

Promise

特点

用法

then

执行顺序

拓展 async/await

Promise优缺点

Promise方法:

浏览器缓存

为什么需要本地存储呢:

window.sessionStorage

window.localStorage

区别

语法

vue路由滚动行为

使用前端路由,当切换到新路由时,想要页面滚到顶部,或者是保持原先的滚动位置,就像重新加载页面那样。 vue-router 能做到,而且更好,它让你可以自定义路由切换时页面如何滚动。

const router = createRouter({
  scrollBehavior(to, from, savedPosition) {
    // 始终滚动到顶部
    return { top: 0 }
  },
})
           

排他思想

点击项为true 其他项都为false

changeActive(val, list) {
      //当前点击项 和整个循环数组
      console.log(val, list);
      //遍历全部的属性值为0 没有高亮
      list.forEach((ele) => {
        ele.isChecked = 0;
      });
      //点击项为1
      val.isChecked = 1;
    },
           

放大镜

<template>
  <div class="spec-preview">
    <img :src="skuImageList[currentIndex].imgUrl" />
    <div class="event" @mousemove="hadleer"></div>
    <!-- 大图 -->
    <div class="big">
      <img :src="skuImageList[currentIndex].imgUrl" ref="big" />
    </div>
    <!-- 遮罩 -->
    <div class="mask" ref="mask"></div>
  </div>
</template>

<script>
export default {
  name: "Zoom",
  props: ["skuImageList"],
  data() {
    return {
      currentIndex: 0,
    };
  },
  mounted() {
    this.$bus.$on("getIndex", (index) => {
      this.currentIndex = index;
      console.log(this.currentIndex);
    });
  },
  methods: {
    hadleer(event) {
      //鼠标移入获取遮罩
      let mask = this.$refs.mask;
      let big = this.$refs.big;
      let left = event.offsetX - mask.offsetWidth / 2;
      let top = event.offsetY - mask.offsetHeight / 2;
      if (left <= 0) left = 0;
      if (left >= mask.offsetWidth) left = mask.offsetWeight;
      if (top <= 0) top = 0;
      if (top >= mask.offsetHeight) top = mask.offsetHeight;
      mask.style.left = left + "px";
      mask.style.top = top + "px";
      big.style.left = -2 * left + "px";
      big.style.top = -2 * top + "px";
    },
  },
};
</script>

<style >
.spec-preview {
  position: relative;
  width: 400px;
  height: 400px;
  border: 1px solid #ccc;

  img {
    width: 100%;
    height: 100%;
  }

  .event {
    width: 100%;
    height: 100%;
    position: absolute;
    top: 0;
    left: 0;
    z-index: 998;
  }

  .mask {
    width: 50%;
    height: 50%;
    background-color: rgba(0, 255, 0, 0.3);
    position: absolute;
    left: 0;
    top: 0;
    display: none;
  }

  .big {
    width: 100%;
    height: 100%;
    position: absolute;
    top: -1px;
    left: 100%;
    border: 1px solid #aaa;
    overflow: hidden;
    z-index: 998;
    display: none;
    background: white;

    img {
      width: 200%;
      max-width: 200%;
      height: 200%;
      position: absolute;
      left: 0;
      top: 0;
    }
  }

  .event:hover ~ .mask,
  .event:hover ~ .big {
    display: block;
  }
}
</style>
           

 加入购物车操作

项目实战

加入购物车的请求放在了vuex里   请求接口只返回状态码 ,我们需要判断派发vuex的结果

vuex 因为使用了async await 调用AsyncAddOrUpdataShopCart 返回promise

我们需要做进一步处理 返回promis实例状态 code200返回非空为成功,否则返回失败态

async AsyncAddOrUpdataShopCart({
    commit
  }, {
    skuId,
    skuNum
  }) {
    let result = await axios.reqAddOrUpdataShopCart(skuId, skuNum)
    //代表服务器加入购物车成功 修改promise状态为成功 成功的值为ok
    if (result.code == 200) {
      return 'ok'
    } else {
      return Promise.reject(new Error('false'))
    }

  }
}
           

 页面等待promise的状态 使用try  catch处理

// 加入购物车
      async addShopCar() {
        //调用返回promise retrun 非空字符串即成功跳转 失败的promise 提示
        try {
          let result = await this.$store.dispatch('AsyncAddOrUpdataShopCart', {
            skuId: this.$route.params.skuId,
            skuNum: this.skuNum
          })
          console.log(result);
        } catch (err) {
          console.log(err);
        }
      }
    },
           

Promise

Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件—更合理且更强大。它最早由社区提出并实现,ES6将其写进了语言标准,统一了用法,并原生提供了Promise对象。

特点

  1. 对象的状态不受外界影响 (3种状态)
    • Pending状态(进行中)
    • Fulfilled状态(已成功)
    • Rejected状态(已失败)
  2. 一旦状态改变就不会再变 (两种状态改变:成功或失败)
    • Pending -> Fulfilled
    • Pending -> Rejected

用法

创建Promise实例

var promise = new Promise(function(resolve, reject){
    // ... some code
    
    if (/* 异步操作成功 */) {
        resolve(value);
    } else {
        reject(error);
    }
})
           

  Promise构造函数接受一个函数作为参数,该函数的两个参数分别是

resolve

reject

。它们是两个函数,由JavaScript引擎提供,不用自己部署。

  resolve作用是将Promise对象状态由“未完成”变为“成功”,也就是

Pending -> Fulfilled

,在异步操作成功时调用,并将异步操作的结果作为参数传递出去;而reject函数则是将Promise对象状态由“未完成”变为“失败”,也就是

Pending -> Rejected

,在异步操作失败时调用,并将异步操作的结果作为参数传递出去。

then

  Promise实例生成后,可用

then

方法分别指定两种状态回调参数。then 方法可以接受两个回调函数作为参数:

  1. Promise对象状态改为Resolved时调用 (必选)
  2. Promise对象状态改为Rejected时调用 (可选)

基本用法示例

function sleep(ms) {
    return new Promise(function(resolve, reject) {
        setTimeout(resolve, ms);
    })
}
sleep(500).then( ()=> console.log("finished"));
           

  这段代码定义了一个函数sleep,调用后,等待了指定参数(500)毫秒后执行then中的函数。值得注意的是,Promise新建后就会立即执行。

执行顺序

  接下来我们探究一下它的执行顺序,看以下代码:

let promise = new Promise(function(resolve, reject){
    console.log("AAA");
    resolve()
});
promise.then(() => console.log("BBB"));
console.log("CCC")

// AAA
// CCC
// BBB
           

  执行后,我们发现输出顺序总是

AAA -> CCC -> BBB

。表明,在Promise新建后会立即执行,所以

首先输出 AAA

。然后,then方法指定的回调函数将在当前脚本所有同步任务执行完后才会执行,所以

BBB 最后输出

与定时器混用首先看一个实例:

let promise = new Promise(function(resolve, reject){
    console.log("1");
    resolve();
});
setTimeout(()=>console.log("2"), 0);
promise.then(() => console.log("3"));
console.log("4");

// 1
// 4
// 3
// 2
           

  可以看到,结果输出顺序总是:

1 -> 4 -> 3 -> 2

。1与4的顺序不必再说,而2与3先输出Promise的then,而后输出定时器任务。原因则是Promise属于JavaScript引擎内部任务,而setTimeout则是浏览器API,而引擎内部任务优先级高于浏览器API任务,所以有此结果。

拓展 async/await

async

  顾名思义,异步。async函数对 Generator 函数的改进,async 函数必定返回 Promise,我们把所有返回 Promise 的函数都可以认为是异步函数。特点体现在以下四点:

  • 内置执行器
  • 更好的语义
  • 更广的适用性
  • 返回值是 Promise

await

  顾名思义,等待。正常情况下,await命令后面是一个 Promise 对象,返回该对象的结果。如果不是 Promise 对象,就直接返回对应的值。另一种情况是,await命令后面是一个thenable对象(即定义then方法的对象),那么await会将其等同于 Promise 对象。

混合使用先看示例:

function sleep(ms) {
    return new Promise(function(resolve, reject) {
        setTimeout(resolve,ms);
    })
}
async function handle(){
    console.log("AAA")
    await sleep(5000)
    console.log("BBB")
}

handle();

// AAA
// BBB (5000ms后)

           

  我们定义函数sleep,返回一个Promise。然后在handle函数前加上async关键词,这样就定义了一个async函数。在该函数中,利用await来等待一个Promise。

Promise优缺点

优点 缺点
解决回调 无法监测进行状态
链式调用 新建立即执行且无法取消
减少嵌套 内部错误无法抛出

Promise方法:

常用的方法有5中:then()、catch()、all()、race()、finally()。

1.then()

接受俩个俩个回调函数作为参数,第一个参数表示成功的时候去执行,第二参数表示失败的时候去执行,返回的时一个新的promise的实列。

2.catch()

相当于then方法的第二个参数。

3.all()

接受一个数组作为自己的参数,数组中每一项都是一个promise对象,当数组的每一个promise状态时resolved时,all方法的状态才会变成resolved,有一个变成rejected,那么all方法的状态就会变成rejected。

4.race()

他和all方法一样,接受一个数组作为自己的参数,但是不同的时他时以第一完成的promise的状态来定义直接的状态,假设第一个状态时resolved,那么race方法的状态就是resolved,反之相反。

5finally()

他是不管promise时什么状态都会执行的都会去执行的,他不接受任何的参数。

浏览器缓存

为什么需要本地存储呢:

  1. 数据存储在用户浏览器中,在控制台中Application模块中查看。
  2. 设置、读取方便、甚至页面刷新不丢失数据
  3. 容量较大,

    sessionStorage

    约5M、

    localStorage

    约20M
  4. 只能存储字符串,可以将对象

    JSON.stringify()

     编码后存储

地储存分两种,一种是

sessionStorage

,以及

localStorage

.那么有什么异同点呢?

window.sessionStorage

  1. 生命周期为关闭浏览器窗口
  2. 在同一个窗口(页面)下数据可以共享
  3. 以键值对的形式存储使用

window.localStorage

  1. 声明周期永久生效,除非手动删除 否则关闭页面也会存在
  2. 可以多窗口(页面)共享(同一浏览器可以共享)
  3. 以键值对的形式存储使用

区别

最大的区别:生命周期的不同,sessionStorage在浏览器存储数据的页面关闭以后存储的数据就消失了,但是localStorage即使浏览器存储数据的页面关闭了,数据也不会丢失,那怎么删除localStorage存储的数据呢?使用localStorage.removeItem(key)和localStorage.clear()语句来删除。

相同点:都是用来存储数据的并且代码语法结构相似。下面细说一下存储数据结构的代码:

语法

  • 存储数据:  sessionStorage.setItem(key, value)
  • 获取数据:sessionStorage.getItem(key)
  • 删除数据:sessionStorage.removeItem(key)
  • 清空数据:(所有都清除掉) sessionStorage.clear()

继续阅读