• vue-day16----拿到登录的token、登录的逻辑、加入购物车、购物车图标上的数量-count、加入购物车的逻辑判断-Dialog对话框(优化)、Cart/index.vue购物车页面数据渲染、Cart/index.vue购物车页面加减法的接口调用、详情页 商品-详情-评价 切换动画、nginx打包


    ### 拿到登录的token

        ①api/index.js中添加user接口:
            user: {
                login: "/v3/login"
            },
        ②api/request.js中导出 userLoginApi 接口(注意是post方法):
            export const userLoginApi=(data)=>{
                return http({
                    method:"post",
                    data:{...data},
                    url:api.user.login
                })
            }
        ③store/index.js中引入 userLoginApi 接口,并在actions中设置请求方法(userLogin):
            import { cityApi,userLoginApi } from "@api/request.js";
    
            async userLogin({commit,dispatch},info){
                let data=await userLoginApi(info);
                console.log(data)
            }
        ④pages下新建Login/index.vue(利用vant的Form表单、通过辅助函数解构vuex的actions中的 userLogin 方法、当点击提交,触发 onSubmit() 方法的时候执行 this.userLogin(values); 将username和password带过去,即可拿到data数据):
            <template>
                <div>
                    <Header></Header>
                    <van-form @submit="onSubmit">
                        <van-field
                            v-model="username"
                            name="username"
                            label="用户名"
                            placeholder="用户名"
                            :rules="[{ required: true, message: '请填写用户名' }]"
                        />
                        <van-field
                            v-model="password"
                            type="password"
                            name="password"
                            label="密码"
                            placeholder="密码"
                            :rules="[{ required: true, message: '请填写密码' }]"
                        />
                        <div style="margin: 16px;">
                            <van-button round block type="info" native-type="submit">提交</van-button>
                        </div>
                    </van-form>
                </div>
            </template>
            <script>
            import Header from "@/components/Home/Header/index.vue";
            // 使用vant
            import Vue from "vue";
            import { Form,Field, Button } from "vant";
            Vue.use(Form);
            Vue.use(Field);
            Vue.use(Button);
            // 辅助函数
            import {mapActions} from "vuex";
            export default {
                components: { Header },
                data() {
                    return {
                        username: "",
                        password: ""
                    };
                },
                methods: {
                    ...mapActions({
                        userLogin:"userLogin"
                    }),
                    onSubmit(values) {
                        console.log("submit", values);
                        this.userLogin(values);
                    }
                },
                mounted() {
                    console.log(this.$route)
                },
            };
            </script>
            <style scoped>
            header{
                position:static !important;
            }
            </style>
        ⑤router中配置login路由,router中新建login/index.js:
            export default{
                name:"login",
                path:"/login",
                component:()=>import("@pages/Login"),
                meta:{
                    title:"登录页面",
                }
            }
        ⑥router/index.js中设置全局路由守卫,在cart和mine的路由下设置meta信息required为true,这样当进入cart页面和mine页面时会先经过路由守卫,没有token值就会进入到login页面:
            import login from "./login";
            import store from "@store/index.js";
    
            // 全局前置路由守卫
            router.beforeEach((to, from, next) => {
                document.title = to.meta.title;
                /*
                    cart和mine页面设置了meta信息----required:true,当进入其他页面的时候直接过去,当进入这两个页面的时候先进入路由守卫
                */
                if (to.meta.required) {
                    // 进入路由守卫时判断有没有token,如果有直接过,如果没有则进入到login页面
                    if (store.state.token) {
                        next();
                    } else {
                        next("/login");
                    }
                } else {
                    next();
                }
            });
        注意:
            1、请求方法userLoginApi()的method是post,而不是get
            2、vant的Field和Button是自己引入并注册的,vant文档中没有写:Vue.use(Field);Vue.use(Button);



    ### 登录的逻辑

        ①router/index.js中全局路由守卫的时候判断如果没有token就跳转到login页面,同时将原本将要跳转的路劲通过params传递给login页面:
            router.beforeEach((to, from, next) => {
                document.title = to.meta.title;
                /*
                    cart和mine页面设置了meta信息----required:true,当进入其他页面的时候直接过去,当进入这两个页面的时候先进入路由守卫
                */
                if (to.meta.required) {
                    // 进入路由守卫时判断有没有token,如果有直接过,如果没有则进入到login页面
                    if (store.state.token) {
                        next();
                    } else {
                        next({ name: "login", params: { to: to.path } });
                    }
                } else {
                    next();
                }
            });
        ②store/index.js中actions方法(userLogin())中判断如果用户名和密码正确,则触发返回true,否则返回false:
            async userLogin({commit,dispatch},info){
                let data=await userLoginApi(info);
                console.log(data)
                if(data.code==200){
                    return true;
                }else{
                    return false;
                }
            }
        ③Login/index.vue中onSubmit()方法提交时,接收actions中userLogin()的返回值(true或false),如果为true说明store中请求正确,则显示登录成功,并且通过params取值跳转到原本要跳转的页面:
            async onSubmit(values) {
                let result=await this.userLogin(values);
                if(result){
                    Toast('登录成功');
                    this.$router.push(this.$route.params.to);
                }else{
                    Toast("用户名或密码错误");
                }
            }
        ④store/index.js中actions方法(userLogin())中if判断里如果data.code==200,则触发commit():
            commit("hanldeLogin",data);
        ⑥store/index.js的mutations中添加hanldeLogin():(将token存起来,后面操作购物车要用到)
            hanldeLogin(state,data){
                state.token=data.data.connect_id;
                localStorage.setItem("token",data.data.connect_id);
            }
        ⑦store/index.js的state中添加token:
            token:localStorage.getItem("token")||""
        注意:
            1、vuex中的actions中的方法有返回值,返回值是一个Promise,所以才可以用async搭配await接收userLogin()返回的值。
            2、重要逻辑:路由守卫中将原本要跳转的页面路径通过params传递到onSubmit()方法中,当登录成功时再通过params取值跳转到原本要跳转的页面。
            3、Toast从vant中引入并注册:Vue.use(Toast); ,它是js组件,可以直接使用:Toast('登录成功');



    ### 加入购物车

        分析:添加到购物车的接口一共需要3个参数:store_id_list、product_id、connect_id。其中connect_id就是前面获取的token,前面两个参数是当前商品中的两个id值,可以通过props传到AddCart组件中。在页面中点击会打印{code: "200", msg: "购物车添加成功", cart:{...}}
        ①api/index.js中添加购物车接口:
            // 购物车接口
            cart: {
                addCart: "/v3/addCart",
                cartList: "/v3/cartList",
                increase: "/v3/increase",// 增加 
                decrease: "/v3/decrease" // 减少
            }
        ②api/request.js中导出 addGoodsCartApi() 方法:
            export const addGoodsCartApi=(data)=>{
                return http({
                    method:"get",
                    data,
                    url:api.cart.addCart
                })
            }
        ③store下新建cart/index.js中定义异步 handleAsyncAddCart() 方法调用 addGoodsCartApi 接口:
            import {addGoodsCartApi} from "@/api/request.js";
            export default{
                state:{
                    
                },
                actions:{
                    async handleAsyncAddCart({commit},params){
                        let data=await addGoodsCartApi(params);
                        console.log(data)
                    }
                },
                mutations:{
                    
                },
                namespaced:true
            }
        ④store/index.js中引入import cart from "./cart";,并注册到modules中modules: {...,cart}
        ⑤pages/Details/Goods.vue中通过自定义属性将store_id_list和product_id传递给AddCart组件:(注意要用三目做判断)
            <AddCart :store_id_list="detailsGoods.productInfo?detailsGoods.productInfo.store_id:''" :product_id="detailsGoods.productInfo?detailsGoods.productInfo.product_id:''"></AddCart>
        ⑥components/Details/AddCart/index.vue中tap事件触发 handleAsyncAddCart() 方法,将三个参数传递过去(这三个参数传递到request.js中的addGoodsCartApi):
            <v-touch tag="div" @tap="addCart()">
                <span>明日达</span>
                <span>加入购物车</span>
            </v-touch>
            import {mapActions} from "vuex";
            export default {
                props:["store_id_list","product_id"],
                methods: {
                    ...mapActions({
                        handleAsyncAddCart:"cart/handleAsyncAddCart"
                    }),
                    addCart(){
                        this.handleAsyncAddCart({
                            store_id_list:this.store_id_list,
                            product_id:this.product_id,
                            connect_id:this.$store.state.token
                        });
                    },
    
                },
            }

    ### 购物车图标上的数量-count

        ①store/cart/index.js中handleAsyncAddCart()方法触发成功后,意味着添加成功,即可以触发commit()方法:
            commit("handleAddCart",data.cart);
    
    
            mutations:{            handleAddCart(state,data){
                    state.count=data.count;
                    state.products=data.products;
                    state.total=data.total;
                    localStorage.setItem("count",data.count);
                    localStorage.setItem("products",JSON.stringify(data.products));
                    localStorage.setItem("total",JSON.stringify(data.total));
                }
            },
        ②store/cart/index.js中state设置count、product、total:
            state:{
                count:localStorage.getItem("count")||"",
                products:localStorage.getItem("products")?JSON.parse(localStorage.getItem("products")):[],
                total:localStorage.getItem("total")?JSON.parse(localStorage.getItem("total")):{}
            },
        ③components/Details/AddCart.vue中直接拿count值渲染:
            <span>{{$store.state.cart.count}}</span>

    ### 加入购物车的逻辑判断-Dialog对话框(优化)

        ①components/Details/AddCart/index.vue中全局引入Dialog组件:
            import Vue from 'vue';
            import { Dialog } from 'vant';
            Vue.use(Dialog);
        ②addCart()方法中添加判断,如果已登录状态则可以添加,如果未登录状态询问是否要跳转到login页面,跳转时将当前路由路劲带过去:
            addCart() {
                this.handleAsyncAddCart({
                    store_id_list: this.store_id_list,
                    product_id: this.product_id,
                    connect_id: this.$store.state.token
                });
            },
            替换为
            addCart() {
                if(this.$store.state.token){
                    this.handleAsyncAddCart({
                        store_id_list: this.store_id_list,
                        product_id: this.product_id,
                        connect_id: this.$store.state.token
                    });
                }else{
                    Dialog.confirm({
                        title:"您还没有登录?",
                        message:"是否需要跳转到登录页面?"
                    }).then(()=>{
                        this.$router.push({name:"login",params:{to:this.$route.path}})
                    }).catch(()=>{
                        Dialog.close();
                    })
                }
            },

    ### 购物车的两种状态:一是未登录不可以添加到购物车,二是未登录页可以添加到购物车,但是在付款的时候验证是否登录

    ### Cart/index.vue购物车页面数据渲染

        ①api/index.js中添加cartList接口:
            // 购物车接口
            cart: {
                addCart: "/v3/addCart",
                cartList: "/v3/cartList"
            }
        ②api/request.js中添加cartListApi接口:
            export const cartListApi=()=>{
                return http({
                    method:"get",
                    url:api.cart.cartList
                })
            }
        ③Cart/index.vue中引入接口:
            import {cartListApi} from "@api/request.js";
        ④Cart/index.vue中定义products、total、count,请求接口数据赋值,进行页面渲染:
            data(){
                return{
                    products:[],
                    total:{},
                    count:""
                }
            },
            methods: {
                async getCartList(){
                    let data=await cartListApi();
                    console.log(9999,data)
                    this.getCartInfo(data);
                },
                getCartInfo(data){
                    this.products=data.cart.products;
                    this.total=data.cart.total;
                    this.count=data.cart.count;
                }
            },
            created() {
                this.getCartList();
            }
        注意:这里用的cartListApi,以及后面用到的increaseApi、decreaseApi,都没有传参数,是因为tiantian-api文件中controller/index.js文件的对应接口都写死了,实际工作中这里是需要传对应的参数的。

    ### Cart/index.vue购物车页面加减法的接口调用

        ①api/index.js中添加increase和decrease接口:
            cart: {
                addCart: "/v3/addCart",
                cartList: "/v3/cartList",
                increase: "/v3/increase",// 增加 
                decrease: "/v3/decrease" // 减少
            }
        ②api/request.js中添加increaseApi和decreaseApi接口:
            export const increaseApi=()=>{
                return http({
                    method:"get",
                    data:{},
                    url:api.cart.increase
                })
            }
            export const decreaseApi=()=>{
                return http({
                    method:"get",
                    data:{},
                    url:api.cart.decrease
                })
            }
        ③Cart/index.vue中引入increaseApi和decreaseApi接口:
            import {cartListApi,increaseApi,decreaseApi} from "@api/request.js";
        ④Cart/index.vue中添加increaseHandle()和decreaseHandle():
            async increaseHandle(){
                let data=await increaseApi();
                this.getCartInfo(data);
            },
            async decreaseHandle(){
                let data=await decreaseApi();
                this.getCartInfo(data);
            }
        ⑤Cart/index.vue中为 “-” “+” 号加上tap事件:
            <div class="goodsNum">
                <v-touch tag="div" @tap="decreaseHandle">-</v-touch>
                <!-- <input type="text" :value="item.qty" /> -->
                <p>{{item.qty}}</p>
                <v-touch tag="div" @tap="increaseHandle">+</v-touch>
            </div>
        注意:购物车页面的数据渲染是通过请求接口而来,将用户信息(token)和一些其他参数传递到后端请求而来。加减法的数据更改是通过接口给后端传递不同的参数来触发请求,后端计算好传递给前端,重新渲染页面。任何的计算都是后端完成,前端通过传不同的参实现逻辑。

    ### 详情页 商品-详情-评价 切换动画

        ①pages/Details/index.vue中给router-view加上transition标签,设置name属性:
            <transition name="slider-left">
                <router-view></router-view>
            </transition>
        ②设置样式:
            .slider-left-enter{
                transform: translateX(100%);
            }
            .slider-left-leave-to{
                transform: translateX(-100%);
            }
            .details_goods{
                position: absolute;
                left:0;
                top:0;
                right: 0;
                bottom: 0;
                padding-top: .9rem;
                transition: all .3s;
            }
        ③DetailHeader.vue头部在切换的时候会有跳动,它的宽度不能是100%,而要改成375px
        注意:可以用vant的切换动画,这是针对DetailHeader的:
            <van-tabs v-model="active" animated>
                <van-tab v-for="index in 4" :title="'选项 ' + index">
                    内容 {{ index }}
                </van-tab>
            </van-tabs>

    ### nginx打包

        ①vue.config.js中module.exports={}中配置publicPath:
            module.exports={
                publicPath:"./",
                ...
            }
        ②public/index.html中用<%= BASE_URL %>代替 ./:
            <link rel="stylesheet" href="<%= BASE_URL %>css/reset.css">
            <link rel="stylesheet" href="<%= BASE_URL %>css/font/iconfont.css">
        ③下载解压nginx包,在conf/nginx.conf文件中添加 /v3 代理:
            location /v3 {
                proxy_pass http://localhost:3000;
            }   
        ④将dist文件夹复制到nginx/html下,改名为 tiantian
        ⑤启动nginx:双击nginx.exe文件,此时地址栏输入localhost:80可以进入nginx主页
        ⑥nginx文件夹cmd打开:nginx -s reload 
        ⑦地址栏访问http://localhost/tiantian即可打开nginx代理下的页面,说明代理成功   
        
        注意:
            1、<%= BASE_URL %>指的是当前路径,就是vue.config.js中publicPath
            2、配置跨域代理(vue.config.js中的跨域地址)的时候如果是ip后面不用加 /,如果是域名后面必须加 /
            3、如果是history路由会无效,必须使用hash路由







  • 相关阅读:
    Dedecms(织梦)文章内容页和图片集内容页,调用缩略图的方法
    如何修改织梦dedecms文章标题的最大长度
    织梦自定义表单后台管理增加全选功能,批量删除垃圾留言信息
    自定义表单SQL命令行批量删除垃圾留言
    织梦后台卡死的原因分析及开关功能解决办法
    织梦网站迁移的几种方法
    Dedecms(织梦)文章内容页和图片集内容页,调用缩略图的方法
    织梦CMS被挂马特征汇总
    DedeCMS模板中用彩色tag做彩色关键词
    HDU6038
  • 原文地址:https://www.cnblogs.com/wuqilang/p/12521500.html
Copyright © 2020-2023  润新知