0
点赞
收藏
分享

微信扫一扫

尚硅谷vue前端项目心得5

seuleyang 2022-01-21 阅读 81

p93-112

5.1 trade结算页面

<div class="address clearFix" v-for="(address,index) in addressInfo" :key="index">
    <span class="username " :class="{selected:address.isDefault==1}">{{address.consignee}}</span>
    <p @click="changeDefault(address,addressInfo)">
        <span class="s1">{{address.fullAddress}}</span>
        <span class="s2">{{address.phoneNum}}</span>
        <span class="s3" v-show="address.isDefault==1">默认地址</span>
    </p>
</div>
index.vue

<script>
    import {mapState} from 'vuex'
export default {
    name: 'Trade',
    data () {
        return {
            msg:''
        }
    },
    // 生命周期挂载完毕
    mounted(){
        this.$store.dispatch('getUserAddress'),
            this.$store.dispatch('getOrderInfo')
    },
    computed:{
        ...mapState({
            addressInfo:state=>state.trade.address,
            orderInfo:state=>state.trade.orderInfo
        }),
        // 提交订单的地址
        userDefaultAddress(){
            // find查找数组中符合条件的元素,为最终结果
            return this.addressInfo.find(item=>item.isDefault==1)
        }
    },
    methods:{
        // 修改默认地址
        changeDefault(address,addressInfo){
            // 全部isDefault为0
            addressInfo.forEach(item =>item.isDefault=0);
            address.isDefault=1
        }
    }
}
</script>

5.2 提交订单

当用户点击提交订单按钮的时候,需要发请求的

13700000000

111111

注:不能在生命周期函数(mounted)中写async

export default {
    name: "Pay",
    data () {
        return {
            payInfo:{}
        }
    },
    mounted() {
        this.getPayInfo()
    },
    computed: {
        orderId() {
            return this.$route.query.orderId;
        },
    },
    methods:{
        async getPayInfo(){
            let res=await this.$API.reqPayInfo(this.orderId);
            if(res.code==200){
                this.payInfo=res.data
            }
        }
    }
};

5.3 ElementUI及按需引入

react框架:
UI组件库antd【蚂蚁金服旗下PC端UI组件库】
antd-mobile【蚂蚁金服旗下的移动端UI组件库】

Vue框架:
element-UI【饿了吗旗下的UI组件库,官方承认的PC组件库插件】
vant【Vue官方提供移动端UI组件库】

第一步:项目中安装element-ui组件库 [2.15.6版本:Vue2]

第二步:在入口文件引入elementUI组件库
第一种:全部引入【不采用:因为项目中只是用到一个组件,没必要全都引入进来】
第二种:按需引入【按照开发需求引入相应的组件,并非全部组件引入】

第三步:按需引入,安装相应的插件
cnpm install babel-plugin-component -D
文档中说的.babelrc文件,即为babel.config.js文件
修改完babel.config.js配置文件以后,项目重启

第四部:按照需求引入相应的组件即可

Vue.component();
Vue.prototype.$xxx = xxx;

main.js
import {Button,MessageBox} from 'element-ui'
// 1.注册全局组件
Vue.component(Button.name,Button);

// 2.ElementUI注册组件时,还有种写法挂载到原型上
Vue.prototype.$msgbox = MessageBox;
Vue.prototype.$alert = MessageBox.alert;
index.vue
//弹出框
open() {
    this.$alert("<strong>这是 <i>HTML</i> 片段</strong>", "HTML 片段", {
        dangerouslyUseHTMLString: true,
        //中间布局
        center: true,
        //是否显示取消按钮
        showCancelButton: true,
        //取消按钮的文本内容
        cancelButtonText: "支付遇见问题",
        //确定按钮的文本
        confirmButtonText: "已支付成功",
        //右上角的叉子没了
        showClose: false,
    });

5.4 微信支付业务

展示二维码----qrcode插件
通过qrCode.toDataUrl方法,将字符串转换为加密的在线二维码链接,通过图片进行展示。
moment.js
swiper.js
nprogress.js
qrcode.js

async open() {
    //生成二维(地址)
    let url = await QRCode.toDataURL(this.payInfo.codeUrl);
    // console.log(url);
    this.$alert(`<img src=${url} />`, "微信支付", {
        dangerouslyUseHTMLString: true,
        //中间布局
        center: true,
        //是否显示取消按钮
        showCancelButton: true,
        //取消按钮的文本内容
        cancelButtonText: "支付遇见问题",
        //确定按钮的文本
        confirmButtonText: "已支付成功",
        //右上角的叉子没了
        showClose: false,
        //关闭弹出框的配置值
        beforeClose: (type, instance, done) => {
            //type:区分取消|确定按钮
            //instance:当前组件实例
            //done:关闭弹出框的方法
            if (type == "cancel") {
                alert("阿巴巴巴");
                //清除定时器
                clearInterval(this.timer);
                this.timer = null;
                //关闭弹出框
                done();
            } else {
                //判断是否真的支付了
                //开发人员:为了自己方便,这里判断先不要了
                // if (this.code == 200) {
                clearInterval(this.timer);
                this.timer = null;
                done();
                this.$router.push("/paysuccess");
                // }
            }
        },
    });
    //你需要知道支付成功|失败
    //支付成功,路由的跳转,如果支付失败,提示信息
    //定时器没有,开启一个新的定时器
    if (!this.timer) {
        this.timer=setInterval(async ()=>{
            // 发请求获取用户支付状态
            let res=await this.$API.reqPayStatus(this.orderId)
            if(res.code==205){
                //第一步:清除定时器
                clearInterval(this.timer);
                this.timer = null;
                //保存支付成功返回的code
                this.code = res.code;
                //关闭弹出框
                this.$msgbox.close();
                //跳转到下一路由
                this.$router.push("/paysuccess");
            }
        },1000)
    }
},

5.5 我的订单

center下的二级路由myOrder

<div class="orders">
    <!-- 每笔订单 -->
    <table
           class="order-item"
           v-for="(order, index) in myOrder.records"
           :key="index"
           >
        <thead>
            <tr>
                <th colspan="5">
                    <span class="ordertitle"
                          >{{ order.createTime }} 订单编号:{{ order.outTradeNo }}
                        <span class="pull-right delete"
                              ><img src="../images/delete.png" /></span
                            ></span>
                </th>
            </tr>
        </thead>
        <tbody>
            <tr v-for="(cart, index) in order.orderDetailList" :key="index">
                <td width="60%">
                    <div class="typographic">
                        <img :src="cart.imgUrl" style="height: 100px; width: 100px" />
                        <a class="block-text">{{ cart.skuName }}</a>
                        <span>x{{ cart.skuNum }}</span>
                        <a href="#" class="service">售后申请</a>
                    </div>
                </td>
                <td
                    :rowspan="order.orderDetailList.length"
                    v-if="index == 0"
                    width="8%"
                    class="center"
                    >
                    {{ order.consignee }}
                </td>
                <td
                    :rowspan="order.orderDetailList.length"
                    v-if="index == 0"
                    width="13%"
                    class="center"
                    >
                    <ul class="unstyled">
                        <li>总金额¥{{ order.totalAmount }}</li>
                        <li>在线支付</li>
                    </ul>
                </td>
                <td
                    :rowspan="order.orderDetailList.length"
                    v-if="index == 0"
                    width="8%"
                    class="center"
                    >
                    <a href="#" class="btn">{{ order.orderStatusName }}</a>
                </td>
                <td
                    :rowspan="order.orderDetailList.length"
                    v-if="index == 0"
                    width="13%"
                    class="center"
                    >
                    <ul class="unstyled">
                        <li>
                            <a href="mycomment.html" target="_blank">评价|晒单</a>
                        </li>
                    </ul>
                </td>
            </tr>
        </tbody>
    </table>
</div>
<div class="choose-order">
    <!-- 分页器 -->
    <!-- total:一共的数据 pageNo:当前多少页  continues:中间连续几页 pageSize:一页展示多少数据-->
    <Pagination
                :total="myOrder.total"
                :pageSize="limit"
                :pageNo="page"
                :continues="9"
                @getPageNo="getPageNo"
                />
</div>
export default {
    data() {
        return {
            //初始化参数
            //当前第几页
            page: 1,
            //每一页展示数据个数
            limit: 3,
            //存储我的订单的数据
            myOrder: {},
        };
    },
    mounted() {
        this.getData();
    },
    methods: {
        // 获取我的订单的方法
        async getData() {
            const { page, limit } = this;
            let res = await this.$API.reqMyOrderList(page, limit);
            if (res.code == 200) {
                this.myOrder = res.data;
            }
        },
        //获取当前点击那一页
        getPageNo(page){
            //修改组件响应式数据page
            this.page=page
            this.getData()
        }
    },
};

5.6 未登录的导航守卫判断

//未登录:不能去交易(trade)相关、不能去支付相关【pay|paysuccess】、不能去个人中心(center)//未登录去上面这些路由-----登录let toPath=to.pathif(toPath.indexOf('/trade')!=-1||toPath.indexOf('/pay')!=-1||toPath.indexOf('/center')!=-1){    //把未登录的时候向去而没有去成的信息,存储于地址栏中【路由】    next('/login?redirect='+toPath)}else{    //去的不是上面这些路由(home|search|shopCart)---放行    next()}

5.7 用户登录(路由独享与组件内守卫)

3)路由独享守卫
路由独享守卫:需要在配置路由的地方使用
导航守卫:全局守卫->项目当中有任何路由变化【a->b,b->d】触发。
路由独享守卫:专门负责某一个路由

用户登陆了:
去交易页面:从购物车才能跳转到交易页面。

next():你本来想去哪里,我就放行,你就去完事了。

next(’/login’):执行守卫放行到执行的路由。

next(false):路由跳转的时候,从哪里来回那里去。

{        path: "/pay",        name: 'pay',        component: Pay,        meta: { show: true },        beforeEnter:(to,from,next)=>{            // 去支付页,从交易页来的            if(from.path=='/trade'){                next()            }else{                 // 其他的路由组件而来,停留在当前                next(false)            }        }    },

4)组件内守卫---->一般很少用【全局 + 路由独享守卫】
组件内守卫:也是专门负责某一个路由【并非负责全部路由】,写法和路由独享守卫有区别?
组件内守卫需要书写在组件内部

beforeRouteEnter
beforeRouteUpdate (2.2 新增)
beforeRouteLeave

// 组件内守卫beforeRouteEnter(to, from, next) {    // 在渲染该组件的对应路由被 confirm 前调用    // 不!能!获取组件实例 `this`    // 因为当守卫执行前,组件实例还没被创建    if(from.path=='/pay'){        next()    }else{        next(false)    }},

5.8 图片懒加载

面试【高频的面试】:项目的性能优化手段有哪些?
v-if|v-show:尽可能采用v-show
按需引入【lodash、elementUI】
防抖与节流
路由懒加载:当用户访问的时候,加载对应组件进行展示。

7)图片懒加载
vue-lazyload:图片懒加载
图片:比用用户网络不好,服务器的数据没有回来,
总不可能让用户看白色,至少有一个默认图片在展示。

main.js// 引入Vue-lazyloadimport VueLazyLoad from 'vue-lazyload'import mwzi from '@/assets/1.jpg'// 注册插件Vue.use(VueLazyLoad,{    // 懒加载默认的图片    loading:mwzi})

5.9 vee-validate表单验证使用

8)表单验证【后台管理系统:大量使用elementUI】
以后工作的时候经常会进行表单验证【element-ui】进行表单验证,so 简单。
项目当中表单验证功能比较常见的。

8.1vee-validate插件:Vue官方提供的一个表单验证的插件【老师接下来的操作能大概看懂即可】
这个插件很难用:如果你翻看它的文档(看一个月:不保证能看懂),依赖文件很多(文档书写的很难理解)
花大量时间学习,很难搞懂。

8.2哪怕将来工作了,真的使用vee-valadiate【老师项目搞出来:改老师代码即可】

使用步骤:
1:安装vee-valadite,别安装最新版本@2
2:在plugins文件夹中创建一个validate.js[专门注册vee-valadite]
3:注册插件
4:注册插件的时候,用中文,以及需要验证的字段【用中文显示提示形式】
5:在入口文件需要引入执行一次
6:使用vee-valadiate插件

8)vee-validate 基本使用

第一步:插件安装与引入
cnpm i vee-validate@2 --save 安装的插件安装2版本的

import VeeValidate from ‘vee-validate’
import zh_CN from ‘vee-validate/dist/locale/zh_CN’ // 引入中文 message
Vue.use(VeeValidate)

第二步:提示信息
VeeValidate.Validator.localize(‘zh_CN’, {
messages: {
…zh_CN.messages,
is: (field) => ${field}必须与密码相同 // 修改内置规则的 message,让确认密码和密码相同
},
attributes: { // 给校验的 field 属性名映射中文名称
phone: ‘手机号’,
code: ‘验证码’,
password:‘密码’,
password1:‘确认密码’,
isCheck:‘协议’
}
})

第三步:基本使用

{{ errors.first(“phone”) }}

const success = await this.$validator.validateAll(); //全部表单验证
//自定义校验规则
//定义协议必须打勾同意
VeeValidate.Validator.extend(‘agree’, {
validate: value => {
return value
},
getMessage: field => field + ‘必须同意’
})

5.10 路由懒加载

引入组件方式 箭头函数

 {   path: "/home",   component: ()=>import('@/pages/Home'),   meta: { show: true }  },

5.11 打包上线

打包npm run build

项目打包后,代码都是经过压缩加密的,如果运行时报错,输出的错误信息无法准确得知是哪里的代码报错。有了map就可以像未加密的代码一样,准确的输出是哪一行哪一列有错。

所以该文件如果项目不需要是可以去除掉

vue.config.js 配置

productionSourceMap:false

举报

相关推荐

0 条评论