Vue商城项目04

vue

绘制 商品列表 页面基本结构并美化

<template>

<div class="goods-list">

<div class="goods-item">

<img src="https://img14.360buyimg.com/n0/jfs/t1/68656/34/7819/87669/5d5e0becE1808db2a/4f29ef986f103e36.jpg" alt="">

<h1 class="title">小米(Mi)小米Note 16G双网通版</h1>

<div class="info">

<p class="price">

<span class="now">¥899</span>

<span class="old">¥999</span>

</p>

<p class="sell">

<span>热卖中</span>

<span>剩60件</span>

</p>

</div>

</div>

<div class="goods-item">

<img src="https://img14.360buyimg.com/n0/jfs/t1/68656/34/7819/87669/5d5e0becE1808db2a/4f29ef986f103e36.jpg" alt="">

<h1 class="title">尼康(Nikon)D3300套机(18-55mm f/3.5-5.6G VRII)(黑色)</h1>

<div class="info">

<p class="price">

<span class="now">¥899</span>

<span class="old">¥999</span>

</p>

<p class="sell">

<span>热卖中</span>

<span>剩60件</span>

</p>

</div>

</div>

<div class="goods-item">

<img src="https://img14.360buyimg.com/n0/jfs/t1/68656/34/7819/87669/5d5e0becE1808db2a/4f29ef986f103e36.jpg" alt="">

<h1 class="title">小米(Mi)小米Note 16G双网通版</h1>

<div class="info">

<p class="price">

<span class="now">¥899</span>

<span class="old">¥999</span>

</p>

<p class="sell">

<span>热卖中</span>

<span>剩60件</span>

</p>

</div>

</div>

</div>

</template>

<script>

</script>

<style lang="scss" scoped>

.goods-list{

display: flex;

flex-wrap: wrap;//默认情况下,flex项目都会尝试适合一行。 wrap规定灵活的项目在必要的时候拆行或拆列。

padding: 7px;

justify-content: space-between; //让里面的两个盒子靠边对齐

.goods-item{

width: 49%; //中间有2%的空隙

border: 1px solid #ccc;

box-shadow: 0 0 8px #ccc;

margin: 4px 0;

padding: 2px;

display: flex;

flex-direction: column;//改变主轴row沿x轴的方向成沿y轴

justify-content: space-between;//沿y轴上两个盒子靠边对齐,不然底部可能有很大空隙

min-height: 293px;//找盒子的最小高度,在还没加载出来有一个最小高度

img{

width: 100%;

}

.title{

font-size: 14px;

}

.info{

background-color: #eee;

p{

margin: 0;//p标签有默认Margin

padding: 5px;

}

.price{

.now{

color: red;

font-weight: bold;

font-size: 16px;

}

.old{

text-decoration: line-through; //删除线

font-size: 12px;

margin-left: 10px;

}

}

.sell{

display: flex;

justify-content: space-between;

font-size: 13px;

}

}

}

}

</style>

尝试在手机上 去进行项目的预览和测试

vue项目" title="vue项目">vue项目如何通过电脑连接手机热点在手机上访问:(wifi同理 无线局域网适配器 本地连接的IPV4)

  1. 首先当然得让电脑连上手机热点,使他们处于同一个局域网中;
  2. 去命令行工具输入 ipconfig获取电脑的ip,如下图所示IPv4地址就是本机电脑的IP
    无线局域网适配器 WLAN: IPv4 地址
  3. 去vue项目中修改配置项, package.json文件
    “dev”: “webpack-dev-server --open --port 3000 --hot --host IPv4 地址”
  4. 在电脑上打开之后,把地址输入到手机上即可。

在手机运行的时候,有的页面显示不该显示的东西。把click换成tap。
mui提供了tap事件替换了html5的click事件
@tap=“getPhotoListByCateId(item.id)”

加载商品列表中的数据

vue-router中编程式导航

    <!-- 在网页中,有两种跳转方式: -->

<!-- 方式1: 使用 a 标签 的形式叫做 标签跳转 -->

<!-- 方式2: 使用 window.location.href 的形式,叫做 编程式导航 -->

<div class="goods-item" v-for="item in goodslist" :key="item.id" @click="goDetail(item.id)"></div>

goDetail(id) {

// 使用JS的形式进行路由导航

// 注意: 一定要区分 this.$route 和 this.$router 这两个对象,

// 其中: this.$route 是路由【参数对象】,所有路由中的参数, params, query 都属于它

// 其中: this.$router 是一个路由【导航对象】,用它 可以方便的 使用 JS 代码,实现路由的 前进、后退、 跳转到新的 URL 地址

// 1. 最简单的传字符串

// this.$router.push("/home/goodsinfo/" + id);

// 2. 传递对象

// this.$router.push({ path: "/home/goodsinfo/" + id });

// 3. 传递命名的路由

this.$router.push({ name: "goodsinfo", params: { id } });

}

绘制商品详情页面的卡片视图

在hello-mui,examples,card.html中 找对应的代码拷贝。
父级元素内部有子元素,如果给子元素添加margin-top样式,那么父级元素也会跟着下来,造成外边距塌陷:
overflow: hidden;解决外边距塌陷
id: this.$route.params.id, // 将路由参数对象中的 id 挂载到 data , 方便后期调用

抽离轮播图组件 轮播图宽度的设置

<template>

<div>

<mt-swipe :auto="4000">

<!-- 将来,谁使用此 轮播图组件,谁为我们传递 lunbotuList -->

<!-- 此时,lunbotuList 应该是 父组件向子组件传值来设置 -->

<mt-swipe-item v-for="item in lunbotuList" :key="item.url">

<img :src="item.img" alt="" :class="{\'full\': isfull}">

<!--如果isfull为true,则应用full类宽度为100%。,否则宽度自适应-->

</mt-swipe-item>

</mt-swipe>

</div>

</template>

<script>

export default {

props: ["lunbotuList", "isfull"]

};

</script>

<style>

.full {

width: 100%;

}

</style>

其他页面引入该组件
import swiper from "../subcomponents/swiper.vue";
components: {swiper}
<swiper :lunbotuList="lunbotuList" :isfull="false"></swiper>
方法自己写

    getLunbotu() {

this.$http.get("api/getthumimages/" + this.id).then(result => {

if (result.body.status === 0) {

// 先循环轮播图数组的每一项,为 item 添加 img 属性,因为 轮播图 组件中,只认识 item.img, 不认识 item.src

result.body.message.forEach(item => {

item.img = item.src;

});

this.lunbotu = result.body.message;

}

});

},

一点样式:
<del>¥oldprice</del>删除线
display: flex;的时候 br 不换行,若不想一行排列,可以让display: block;

购物车小球动画效果

页面中id="badge"购物车的位置:

			<router-link class="mui-tab-item-llb" to="/shopcar">

<span class="mui-icon mui-icon-extra mui-icon-extra-cart">

<span class="mui-badge" id="badge">0</span>

</span>

<span class="mui-tab-label">购物车</span>

</router-link>

一些关键代码:

    <!-- transition的过渡-->

<transition

@before-enter="beforeEnter"

@enter="enter"

@after-enter="afterEnter">

<!-- 只要想要在Vue中直接操作DOM元素,就必须用ref属性进行注册

ref在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;this.$refs.ball获取当前元素-->

<div class="ball" v-show="ballFlag" ref="ball"></div>

</transition>

<mt-button type="danger" size="small" @click="addToShopCar">加入购物车</mt-button>

data() {

return {

ballFlag: false, // 控制小球的隐藏和显示的标识符

};

addToShopCar() {

// 添加到购物车

this.ballFlag = !this.ballFlag;

},

beforeEnter(el) {

el.style.transform = "translate(0, 0)";

//translate(0, 0)位置(0, 0)

},

enter(el, done) {

el.offsetWidth;

//offsetWidth = width + padding +border

// 小球动画优化思路:

// 1. 先分析导致 动画 不准确的 本质原因: 我们把 小球 最终 位移到的 位置,已经局限在了某一分辨率下的 滚动条未滚动的情况下;

// 2. 只要分辨率和 测试的时候不一样,或者 滚动条有一定的滚动距离之后, 问题就出现了;

// 3. 因此,我们经过分析,得到结论: 不能把 位置的 横纵坐标 直接写死了,而是应该 根据不同情况,动态计算这个坐标值;

// 4. 经过分析,得出解题思路: 先得到 徽标的 横纵 坐标,再得到 小球的 横纵坐标,然后 让 y 值 求差, x 值也求 差,得到 的结果,就是横纵坐标要位移的距离

// 5. 如何 获取 徽标和小球的 位置 domObject.getBoundingClientRect()

// 获取小球的 在页面中的位置

const ballPosition = this.$refs.ball.getBoundingClientRect();

// 获取 徽标 在页面中的位置,只要页面中有,就可以获取到

const badgePosition = document

.getElementById("badge")

.getBoundingClientRect();

const xDist = badgePosition.left - ballPosition.left;

const yDist = badgePosition.top - ballPosition.top;

// ${xDist}模版字符串,等价于\' + xDist + \'

el.style.transform = `translate(${xDist}px, ${yDist}px)`;

el.style.transition = "all 0.5s cubic-bezier(.4,-0.3,1,.68)";

done();

},

afterEnter(el) {

this.ballFlag = !this.ballFlag;

}

},

.ball {

width: 15px;

height: 15px;

border-radius: 50%;

background-color: red;

position: absolute;

z-index: 99; //让其在最上面显示

top: 390px; //找位置调试的时候在f12里鼠标滑动值

left: 146px;

}

当子组件numbox里面的值发生变化立即传给父组件,同时有最大数量

子组件:

<template>

<!-- 问题: 因为该max值是从父组件调用的方法里取到的,可能在拿到值前面该组件就被渲染完毕。我们不知道什么时候能够拿到 max 值,但是,总归有一刻,会得到一个真正的 max 值 -->

<!-- 我们可以 使用 watch 属性监听,来 监听 父组件传递过来的 max 值,不管 watch 会被触发几次,但是,最后一次,肯定是一个 合法的 max 数值 -->

<div class="mui-numbox" data-numbox-min=\'1\'>

<button class="mui-btn mui-btn-numbox-minus" type="button">-</button>

<!--@change="countChanged" 值改变了就会触发事件countChanged -->

<input id="test" class="mui-input-numbox" type="number" value="1" @change="countChanged" ref="numbox" />

<button class="mui-btn mui-btn-numbox-plus" type="button">+</button>

</div>

</template>

<script>

import mui from "../../lib/mui/js/mui.min.js";

export default {

mounted() {

// 初始化数字选择框组件

mui(".mui-numbox").numbox();

console.log(this.max);

},

methods: {

countChanged() {

// 每当 文本框的数据被修改的时候,立即把 最新的数据,通过事件调用,传递给父组件

//在子组件中需要向父组件传值处使用this.$emit("function",param);

//其中function为父组件定义函数,param为需要传递参数

//在父组件中子组件引用处添加函数 @:function="function1";

其中function为子组件中定义函数,function1为父组件定义函数--用于接收子组件传值并进行相应数据处理,可定义为同一名称

this.$emit("getcount", parseInt(this.$refs.numbox.value));

}

},

props: ["max"],//从父组件取到的值

watch: {

// 属性监听

max: function(newVal, oldVal) {

// 使用Mui里该组件的 JS API , 设置 numbox 的最大值

mui(".mui-numbox")

.numbox()

.setOption("max", newVal);

}

}

};

</script>

<style lang="scss" scoped>

</style>

父组件:

        <!-- 分析: 如何实现加入购物车时候,拿到 选择的数量 -->

<!-- 1. 经过分析发现: 按钮属于 goodsinfo 页面, 数字 属于 numberbox 组件 -->

<!-- 2. 由于涉及到了父子组件的嵌套了,所以,无法直接在 goodsinfo 页面zhong 中获取到 选中的商品数量值-->

<!-- 3. 怎么解决这个问题:涉及到了 子组件向父组件传值了(事件调用机制) -->

<!-- 4. 事件调用的本质: 父向子传递方法,子调用这个方法, 同时把 数据当作参数 传递给这个方法 -->

<p>购买数量:<numbox @getcount="getSelectedCount" :max="goodsinfo.stock_quantity"></numbox></p>

data里 selectedCount: 1 // 保存用户选中的商品数量, 默认,认为用户买1个

getSelectedCount(count) {

// 当子组件把 选中的数量传递给父组件的时候,把选中的值保存到 data 上

this.selectedCount = count;

console.log("父组件拿到的数量值为: " + this.selectedCount);

}

以上是 Vue商城项目04 的全部内容, 来源链接: utcz.com/z/379388.html

回到顶部