vue常用案例

官網(wǎng)

https://cn.vuejs.org/v2/guide/

一、單頁面Tab導航欄切換

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <script src="vue.js"></script>
    <style>
        .tab{
            position: relative;
        }
        ul{
            width: 300px;
            display: flex;
            justify-content: space-between;
        }
        ul li{
            border: 1px solid #000;
            padding: 10px;
            list-style: none;
        }
        ul li.active{
            background-color: #ccc;
        }
        .tab div{
            display: none;
            width: 300px;
            height: 300px;
        }
        .tab div.current{
            display: block;
        }
    </style>
</head>
<body>
    <div id="app">
        <div class="tab">
            <ul>
                <!-- 初始化序號與當前點擊元素序號相等,添加類名 ,等價于 :style="{backgroundColor: currentIndex == index ? '#ccc': 'initial' }"-->
                <li :class="currentIndex == index ? 'active':''" v-for="(item,index) in list" :key="item.id" @click="click(index)">{{ item.name }}</li>
            </ul>
            <div :class="currentIndex == index ? 'current':''" v-for="(item,index) in bg" :key="item.id" :style="'backgroundColor:' + item.color"></div>
        </div>
    </div>
</body>
<script>
    new Vue ({
        el: "#app",
        data: {
            currentIndex: 0,
            // 初始化序號
            list: [
                {id:1,name:'張三'},
                {id:2,name:'李四'},
                {id:3,name:'王五'},
            ],
            bg: [
                {id:1,color:'red'},
                {id:2,color:'blue'},
                {id:3,color:'pink'},
            ]
        },
        methods:{
            // 點擊當前導航欄元素并將當前點擊元素序號給初始化序號
            click(i){
                this.currentIndex = i;
            }
        }
    })
</script>
</html>

補充案例:底部導航欄路由和圖片切換,同時使用router-link和@click點擊圖標2次才顯示,可使用props和$router.push解決
參考文獻:https://www.jb51.net/article/160601.htm

// 子組件
<template>
    <ul class="tabbar-container">
      <li class="tabbar-item" v-for="(item,index) in tabs" :key="index" @click="$router.push(item.path)">
        <i class="tabbar-icon" :style="{backgroundImage: index == currentIndex ? 'url(' + item.reicon + ')' : 'url(' + item.icon + ')',backgroundRepeat: 'no-repeat',backgroundSize: '100%'}"></i>
          {{ item.name }}           
      </li>
    </ul>
</template>

<script>
    export default {
        name: "TabBar",
        props:{
            index: Number
        },
        data() {
            return {
                currentIndex: this.index,
                tabs: [
                    {id:1,name:"首頁",active:true,icon:require("../../assets/images/icon/dibu-shouye.png"),reicon:require("../../assets/images/icon/dibu-shouye2.png"),path:"/home"},
                    {id:2,name:"分類",active:false,icon:require("../../assets/images/icon/dibu-fenlei.png"),reicon:require("../../assets/images/icon/dibu-fenlei2.png"),path:"/type"},
                    {id:3,name:"購物車",active:false,icon:require("../../assets/images/icon/dibu-gouwuche.png"),reicon:require("../../assets/images/icon/dibu-gouwuche2.png"),path:"/shopcar"},
                    {id:4,name:"消息",active:false,icon:require("../../assets/images/icon/dibu-xiaoxi.png"),reicon:require("../../assets/images/icon/dibu-xiaoxi2.png"),path:"/message"},
                    {id:5,name:"個人中心",active:false,icon:require("../../assets/images/icon/dibu-gerenzhongxin.png"),reicon:require("../../assets/images/icon/dibu-gerenzhongxin2.png"),path:"/my"}
                ]
            }
        }
    }
</script>

// 父組件
<TabBar class="tabbar" :index='0'></TabBar>

二、模擬后端接口,驗證用戶名是否可用

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <script src="vue.js"></script>
    <style>

    </style>
</head>
<body>
    <div id="app">
        <!-- lazy:失去焦點后觸發(fā) -->
        用戶名:<input type="text" v-model.lazy="username">{{ tip }}
    </div>
</body>
<script>
    /*步驟:
    1、采用偵聽器監(jiān)聽用戶名的變化
    2、調(diào)用后臺接口進行驗證
    3、根據(jù)驗證的結(jié)果調(diào)整提示信息
    */
    new Vue ({
        el: "#app",
        data: {
            currentIndex: 0,
            username: "",
            tip: ""
        },
        methods:{
            checkName(username){
                // 模擬接口調(diào)用
                setTimeout(() => {
                    if (username == "admin") {
                        this.tip = "用戶名已存在,請更換一個"
                    }else{
                        this.tip = "用戶名可以使用"
                    }
                },2000)
            }
        },
        watch: {
            // 屬性名與方法名必須一致
            username(val){
                // 調(diào)用后臺接口驗證用戶名的合法性
                this.checkName(val);
                // 修改提示信息
                this.tip = "正在驗證……"
            }
        }
    })
</script>
</html>

三、購物車(父子組件傳值)

插槽:https://cn.vuejs.org/v2/guide/components-slots.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <script src="vue.js"></script>
    <style>
        .cart-title,.cart-total{
            width: 50%;
            border: 1px solid #000;
            padding: 10px;
            box-sizing: border-box;
        }
        .cart-title{
            margin: 0;
            border-bottom: 0;
            text-align: center;
        }
        .cart-total{
            border-top: 0;
            display: flex;
            justify-content: space-between;
        }
        .cart-list{
            width: 50%;
            text-align: center;
            border-collapse: collapse;
        }
        .cart-list .totalSelect{
            margin-top: -10px;
        }
        .cart-list .btn-group .btn-num{
            width: 20px;
            text-align: center;
        }
    </style>
</head>
<body>
    <div id="app">
        <h3 class="cart-title">我的商品</h3>
        <!-- 綁定屬性或方法,前后名稱可以不一致 -->
        <car-list :list="cart_list" @del-good="delGood" @change-num="changeNum"></car-list>
        <car-total :list="cart_list"></car-total>
    </div>
    <template id="carList">
        <table class="cart-list" border="1" cellpadding="10" cellspacing="10">
            <tr>
                <th>商品名稱</th>
                <th>商品價格</th>
                <th>數(shù)量</th>
                <th>操作</th>
            </tr>
            <tr v-for="(item,index) in list" :key="index">
                <td>{{ item.goods_name }}</td>
                <td>{{ item.goods_price }}</td>
                <td class="btn-group">
                    <span class="btn btn-reduce" @click="reduce(index)">-</span>
                    <input class="btn-num" type="text" v-model="item.num" @blur="change(index,$event)"/>
                    <span class="btn btn-add" @click="add(index)">+</span>
                </td>
                <td>
                    <button class="delete" @click="del(index)">刪除</button>
                </td>
            </tr>
        </table>
    </template>
    <template id="carTotal">
        <div class="cart-total">
            <div class="total-pay">
                總計:共 {{ list.length }} 件商品,
                合計:{{ totalPrice }} 元
            </div>
            <button class="total-pay-success">去結(jié)算</button>
        </div>
    </template>
</body>
<script>
    new Vue ({
        el: "#app",
        data: {
            cart_list: [{
                goods_name: '小米6',
                goods_price: '1699',
                num: '2',
            }, {
                goods_name: '紅米3',
                goods_price: '699',
                num: '1',
            }, {
                goods_name: '小米8',
                goods_price: '2899',
                num: '1',
            }],
        },
        methods:{
            // 根據(jù)子組件傳過來的值中的type,改變數(shù)量輸入框的值
            changeNum(val){
                // console.log(val)
                if (val.type == 'change') {
                    this.cart_list[val.id].num = val.num;
                }else if (val.type == 'reduce') {
                    if (this.cart_list[val.id].num <= 0) {
                        this.cart_list[val.id].num = 0;
                    }else{
                        this.cart_list[val.id].num--;
                    }
                }else{
                    this.cart_list[val.id].num++;
                }

            },
            // 接收子組件傳過來的當前元素的id,刪除當前點擊元素
            delGood(id){
                this.cart_list.splice(id,1);
            },
        },
        components: {
            carList: {
                template: '#carList',
                data(){
                    return{

                    }
                },
                methods: {
                    // 將當前已減少的輸入框數(shù)量傳給父組件
                    reduce(id){
                        this.emit('change-num',id,'reduce')
                    },
                    // 將當前已增加的輸入框數(shù)量傳給父組件
                    add(id){
                        this.emit('change-num',id,'add')
                    },
                    // 將當前已改變的輸入框數(shù)量傳給父組件
                    change(id,event){
                        this.emit('change-num',id,'change',event.target.value)
                    },
                    // 將當前點擊元素id傳給父組件
                    del(id){
                        this.emit('del-good',id)
                    },
                    // 封裝子組件傳值父組件
                    emit(){
                        // console.log(arguments)
                        if (arguments.length > 2) {
                            this.$emit(arguments[0],{
                                id: arguments[1],
                                type: arguments[2],
                                num: arguments[3]
                            })
                        }else{
                            this.$emit(arguments[0],arguments[1])
                        }
                    }
                },
                // 接收父組件傳給子組件的值
                props: ['list']
            },
            carTotal: {
                template: '#carTotal',
                computed: {
                    // 計算總價
                    totalPrice(){
                        let total_price = 0;
                        this.list.forEach(item => {
                            total_price += Number(item.goods_price) * Number(item.num);
                        })
                        return total_price;
                    }
                },
                props: ['list']
            }
        }
    })
</script>
</html>

補充:兄弟組件傳值
https://www.cnblogs.com/rich23/p/7110409.html

五、異步操作

promise和ajax使用

query(url){
        let p = new Promise((resolve,reject) => {
            Ajax('get',url,null,success,failed);
            // 返回成功數(shù)據(jù)
            function success(jsondata){
                let json = JSON.parse(jsondata);
                resolve(json);
            }
            // 返回失敗數(shù)據(jù)
            function failed(){
                reject('服務器錯誤');
            }
        });
        return p;
    };
    query('http://localhost:3000/data')
        .then(res => {
            // 返回成功數(shù)據(jù)
            console.log(res);
            // 返回下一次異步調(diào)用數(shù)據(jù)
            return query('http://localhost:3000/data2');
        },rej => {
            // 返回失敗數(shù)據(jù)
            console.log(rej);
        })
        .then(res => {
            console.log(res);
            return query('http://localhost:3000/data3');
        },rej => {
            console.log(rej);
        })
        .then(res => {
            console.log(res);
        },rej => {
            console.log(rej);
        })

// Ajax封裝
function Ajax(type, url, data, success, failed){
    // 創(chuàng)建ajax對象
    let xhr = null;
    if(window.XMLHttpRequest){
        xhr = new XMLHttpRequest();
    } else {
        xhr = new ActiveXObject('Microsoft.XMLHTTP')
    }
    //轉(zhuǎn)化為大寫
    type = type.toUpperCase();
    // 用于清除緩存,防止瀏覽器緩存
    let random = Math.random();
    // 字符串拼接傳過來的數(shù)據(jù),如'name=zhangsan&'
    if(typeof data == 'object'){
        var str = '';
        for(var key in data){
            str += key+'='+data[key]+'&';
        }
        data = str.replace(/&$/, '');
    }
    // 判斷使用方法
    if(type == 'GET'){
        // 根據(jù)是否傳入數(shù)據(jù)處理參數(shù)顯示
        if(data){
            xhr.open('GET', url + '?' + data, true);
        } else {
            xhr.open('GET', url + '?t=' + random, true);
        }
        xhr.send(null);

    } else if(type == 'POST'){
        xhr.open('POST', url, true);
        // 如果需要像html表單那樣POST數(shù)據(jù),請使用setRequestHeader() 來添加http頭
        xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
        xhr.send(data);
    }
    // 檢測狀態(tài),處理返回數(shù)據(jù)
    xhr.onreadystatechange = function(){
        //檢測是否已經(jīng)準備好
        if(xhr.readyState == 4){
            //表示響應準備就緒
            if((xhr.status >= 200&&xhr.status<300)||xhr.status==304){
                //請求成功之后的處理
                success(xhr.responseText);
            } else {
                //處理ajax返回異常的情形
                if(failed){
                    failed(xhr.status);
                }
            }
        }
    }
}

fetch使用
https://developer.mozilla.org/zh-CN/docs/Web/API/Fetch_API/Using_Fetch

axios使用
post報錯400:https://www.cnblogs.com/chenlw/p/9994891.html
傳參:https://blog.csdn.net/zhaofuqiangmycomm/article/details/89479904
官方文檔:https://www.kancloud.cn/yunye/axios/234846
vue:https://hacpai.com/article/1567922774522
封裝:https://www.cnblogs.com/panax/p/10942889.html
https://www.cnblogs.com/chaoyuehedy/p/9931146.html
async/await使用
https://segmentfault.com/a/1190000007535316

四、后臺管理路由

vue-router使用
https://router.vuejs.org/zh/installation.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <script src="vue.js"></script>
    <script src="vue-router.js"></script>
    <style>
        *{
            padding: 0;
            margin: 0;
        }
        html,body,#app,.wrapper{
            height: 100%;
        }
        ul{
            list-style: none;
        }
        a{
            text-decoration: none;
            color: #fff;
        }
        .wrapper{
            display: flex;
            flex-direction: column;
            justify-content: space-between;
        }
        .header,.footer,.main .left{
            background-color: #666;
            color: #fff;
        }
        .header,.footer,.main .left ul li{
            text-align: center;
            padding: 10px 0;
        }
        .main{
            height: 100%;
            display: flex;
            justify-content: space-between;
        }
        .main .left{
            width: 20%;
        }
        .main .left ul li{
            border-bottom: 1px solid #fff;
            background-color: #ccc;
        }
        .main .right{
            flex: 1;
            text-align: center;
        }
        .main .right h3{
            padding: 10px 0;
        }
        .main .right table{
            border-collapse: collapse;
            width: 60%;
            margin: 0 auto;
        }
        .main .right table td,.main .right table th{
            padding: 10px 0;

        }
        .main .right table a{
            color: #000;
        }
    </style>
</head>
<body>
    <!-- 要被vue實例控制的區(qū)域 -->
    <div id="app">
        <router-view></router-view>
    </div>
</body>
<script>
    // 定義app根組件
    const App = {
        template: `
            <div class="wrapper">
                <header class="header">后臺管理系統(tǒng)</header>
                <div class="main">
                    <div class="left">
                        <ul>
                            <li>
                                <router-link to="/users">用戶管理</router-link>
                            </li>
                            <li>
                                <router-link to="/rights">權(quán)限管理</router-link>
                            </li>
                            <li>
                                <router-link to="/goods">商品管理</router-link>
                            </li>
                            <li>
                                <router-link to="/orders">訂單管理</router-link>
                            </li>
                            <li>
                                <router-link to="/settings">用戶管理</router-link>
                            </li>
                        </ul>
                    </div>
                    <div class="right">
                        <router-view></router-view>
                    </div>
                </div>
                <footer class="footer">版權(quán)信息</footer>
            </div>
        `
    }

    const Users = {
        data(){
            return{
                list: [
                    {id:1,name:"張三",age: 10},
                    {id:2,name:"李四",age: 20},
                    {id:3,name:"王五",age: 30},
                ]
            }
        },
        methods: {
            goDetail(id){
                this.$router.push('/userinfo/' + id)
            }
        },
        template: `
            <div>
                <h3>用戶管理區(qū)域</h3>
                <table border="1">
                    <thead>
                        <tr>
                            <th>編號</th>
                            <th>姓名</th>
                            <th>年齡</th>
                            <th>操作</th>
                        </tr>
                    </thead>
                    <tbody>
                        <tr v-for="(item,index) in list" :key="item.id">
                            <td>{{ item.id }}</td>
                            <td>{{ item.name }}</td>
                            <td>{{ item.age }}</td>
                            <td>
                                <a href="javascript:;" @click="goDetail(item.id)">詳情</a>
                            </td>
                        </tr>
                    </tbody>
                </table>
            </div>
        `
    }

    const UserInfo = {
        // 接收參數(shù)
        props: ['id'],
        methods: {
            // 返回
            goBack(){
                this.$router.go(-1)
            }
        },
        template: `
            <div>
                <h5>用戶詳情頁-{{ id }}</h5>
                <button @click="goBack()">后退</button>
            </div>
        `
    }

    const Rights = {
        template: `
            <div>
                <h3>權(quán)限管理區(qū)域</h3>
            </div>
        `
    }
    const Goods = {
        template: `
            <div>
                <h3>商品管理區(qū)域</h3>
            </div>
        `
    }
    const Orders = {
        template: `
            <div>
                <h3>訂單管理區(qū)域</h3>
            </div>
        `
    }
    const Settings = {
        template: `
            <div>
                <h3>系統(tǒng)管理區(qū)域</h3>
            </div>
        `
    }
    // 創(chuàng)建路由對象
    const router = new VueRouter({
        routes: [
            {
                path: '/',
                redirect: '/users',
                component: App,
                children: [
                    {
                        path: '/users',
                        component: Users
                    },
                    {
                        // 傳參id
                        path: '/userinfo/:id',
                        component: UserInfo,
                        props: true
                    },
                    {
                        path: '/rights',
                        component: Rights
                    },
                    {
                        path: '/goods',
                        component: Goods
                    },
                    {
                        path: '/orders',
                        component: Orders
                    },
                    {
                        path: '/settings',
                        component: Settings
                    }
                ]
            }
        ]
    })

    new Vue({
        el: "#app",
        router
    })
</script>
</html>

五、登錄

token:https://blog.csdn.net/c880420/article/details/80346127
完整案例:https://www.cnblogs.com/web-record/p/9876916.html

// 根目錄下vue.config.js 解決跨域
module.exports = {
  devServer: {
    proxy: {
      '/api': {
        target: 'http://localhost:3000/api',
        ws: true,
        changeOrigin: true,
        pathRewrite:{
          '^/api': ''
        }
      },    
    }
  }
}

// main.js
import axios from 'axios'
Vue.prototype.$http = axios
// 添加請求頭
axios.interceptors.request.use(config => {
    config.headers.Authorization = window.sessionStorage.getItem('token');
    return config;
})

router.beforeEach((to,from,next) => {
    // 登錄頁無需權(quán)限
    if (to.path == '/login') {
        next()
    }else{
        // 獲取token
        const token = window.sessionStorage.getItem('token');
        // token不存在直接跳轉(zhuǎn)登錄頁
        if(!token) return next('/login');
        // 存在放行
        next();
    }
})

// login.vue
this.$http.post('/api/login',data).then(res => {
    if(res.status !== 200){
         // element-ui彈窗
        this.$message.error('登錄失敗');
    }
    this.$message.success('登錄成功');
     // 緩存token
    window.sessionStorage.setItem('token',res.data.token);
    this.$router.push('/home')
})

// 退出,清緩存
window.sessionStorage.clear();
this.$router.push('/login');

六、增刪改查

調(diào)用后端接口實現(xiàn)圖書管理增刪改查

https://github.com/mycummity/book

實現(xiàn)功能

navArray: [
        {
          href: "#navTitle1",
          name: "應用簡介"
        }
]

<div
          class="navItem"
          :class="{'selected':currentIndex==index}"
          v-for="(item,index) in navArray"
          :key="index"
          @click="goAnchor(item.href)"
        >
          <span>{{item.name}}</span>
</div>


<div class="appSketch" id="navTitle1">
      
</div>


goAnchor(type) {
      var anchor = this.$el.querySelector(type);
      // chrome
      document.body.scrollTop = anchor.offsetTop - 50;
      // firefox
      document.documentElement.scrollTop = anchor.offsetTop - 50;
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容