在普通的html頁面用Vue3組合式API寫的專案(無需Node.js環境和構建專案)

發表於2024-02-20

摘要

Vue.js的優點有很多,但是其使用門檻對於只學習過普通的專案的同學來說,還是比較有挑戰性的,如果你真的想把Vue學的很溜,真的需要一個非常系統的學習才能運用起來。因為學習Vue你不僅僅是學習他的語法、API和一些開發的規範,你還要學習構建工具的使用、除錯、打包等等,有些人連最基本的開發環境都還沒能順利搭建起來。

如果你不想使用Vue強大的生態和工具,只想在html頁面中使用Vue也是可以的,因為Vue也有一個全域性的生產環境cdn(vue.global.prod.min.js),你可以使用這個cdn來使用Vue構建比較小型的專案。

專案介紹

寫這篇文章的原因是我使用了Vue3的組合式Api實現了一個非常簡單的單頁,具體資訊如下:

專案:圍繞廣東省3+證書招生考試資訊為資料,開發一個招生院校、招生專業資訊查詢和展示頁面。

資料:廣東3+證書招生院校目錄、招生專業目錄。

專案截圖:

bb644eb18e3e26a076ea64245cd37d7.jpg

程式碼結構:

image.png

上程式碼

index.html

程式碼中引入了 vue.global.prod.min.js 用於使用Vue的API,引入了 vue-router.js 實現路由功能,引入了 axios.min.js 實現請求介面獲取資料。

在app節點下透過 <router-view></router-view> 渲染對應路由的內容。

關鍵的程式碼都在 app.js 中使用Vue3的組合式API實現資料請求和資料響應式渲染。所以透過模組的方式引入了 app.js

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>廣東省3+證書(中職)招生計劃</title>
    <script src="js/vue.global.prod.min.js"></script>
    <script src="js/vue-router.js"></script>
    <script src="js/axios.min.js"></script>
    <link rel="stylesheet" href="css/app.css">
    <style>
        .college-card {
            width: 100%;
            display: flex;
            border-bottom: 1px solid #eee;
            background: #fff;
        }
        .college-card .college-logo {
            width: 90px;
        }
        .college-card .college-logo img {
            width: 55px;
            height: 55px;
            margin: 25px 15px 15px 20px;
            border-radius: 100px;
        }
        .college-card .college-info {
            flex: 1;
        }
        .college-card .college-name {
            width: 100%;
            height: 45px;
            line-height: 45px;
            font-size: 17px;
            font-weight: bold;
            color: #333;
        }
        .college-card .college-category {
            width: 100%;
            height: 25px;
        }
        .college-card .college-category .tag {
            background: #fff4ef;
            color: #ff7637;
            padding: 3px 6px;
            font-size: 12px;
            margin-right: 8px;
            border-radius: 5px;
        }
        .college-card .college-plan {
            width: 100%;
            height: 30px;
            line-height: 30px;
            font-size: 14px;
            color: #999;
            padding-bottom: 5px;
        }
        .college-card .next {
            width: 30px;
            background: url('img/next.png')no-repeat;
            background-size: 80%;
            background-position: center;
            opacity: 0.5;
        }
        
        .college-info {
            background: #fff;
        }
        .college-info .info-header {
            width: 100%;
            margin: 0 auto;
            display: flex;
            border-bottom: 1px solid #eee;
            padding-top: 15px;
        }
        .college-info .info-header .info-logo {
            width: 90px;
        }
        .college-info .info-header .info-logo img {
            width: 60px;
            height: 60px;
            margin: 25px 15px 15px 10px;
            border-radius: 100px;
        }
        .college-info .info-header .info {
            flex: 1;
        }
        .college-info .info-header .info .college-name {
            width: 100%;
            height: 45px;
            line-height: 45px;
            font-size: 20px;
            font-weight: bold;
            color: #333;
        }
        .college-info .info-header .info .college-tag {
            width: 100%;
            height: 25px;
        }
        .college-info .info-header .info .college-tag .info-tag {
            background: #fff4ef;
            color: #ff7637;
            padding: 3px 6px;
            font-size: 12px;
            margin-right: 8px;
            border-radius: 5px;
        }
        .college-info .info-header .info .info-plan {
            width: 100%;
            height: 30px;
            line-height: 30px;
            font-size: 14px;
            color: #999;
        }
        
        .college-info-nav {
            width: 100%;
            display: flex;
        }
        .college-info-nav .nav-tag {
            flex: 1;
            height: 40px;
            line-height: 40px;
            text-align: center;
            font-size: 15px;
            color: #666;
        }
        
        .college-info-plan {
            width: 95%;
            background: #fff;
            margin: 15px auto 0;
            overflow: hidden;
            border-radius: 10px;
        }
        .college-info-plan .college-info-plan-year {
            width: 93%;
            height: 30px;
            margin: 15px auto 0;
        }
        .college-info-plan .college-info-plan-year .plan-year {
            padding: 6px 10px;
            background: #eee;
            font-size: 15px;
            margin-right: 10px;
            border-radius: 10px;
            color: #666;
        }
        .college-info-plan .college-info-plan {
            width: 93%;
            height: 30px;
            margin: 10px auto;
            font-size: 14px;
        }
        
        .college-info-plan .college-info-plan-zyz {
            width: 93%;
            height: 20px;
            margin: 10px auto 0;
            font-size: 15px;
            color: #ff7637;
            font-weight: bold;
        }
        .college-info-plan .college-info-zyz-plan {
            width: 93%;
            height: 20px;
            margin: 5px auto;
            font-size: 14px;
        }
        .college-info-plan .college-info-zyz-major {
            width: 93%;
            margin: 15px auto;
            font-size: 14px;
        }
        .college-info-plan .college-info-zyz-major table{
            width: 100%;
            border-collapse: collapse;
            border-spacing: 0;
            text-align: center;
            margin: 0 auto;
            position: relative;
        }
        .college-info-plan .college-info-zyz-major th{
            background: #fff4ef;
        }
        .college-info-plan .college-info-zyz-major th,td{
            padding: 6px 10px;
            border: 1px solid #ff7637;
        }
        
        .zyzList {
            background: #fff;
            width: 95%;
            margin: 20px auto 0;
            overflow: hidden;
            border-radius: 10px;
        }
        .zyzList table {
            width: 93%;
            font-size: 13px;
            text-align: center;
            border-collapse: collapse;
            margin: 10px auto;
        }
        .zyzList table th {
            padding: 6px 0;
            border: 1px solid #eee;
        }
        .zyzList table td {
            border: 1px solid #eee;
            color: #666;
        }
        
        .majorList {
            background: #fff;
            width: 95%;
            margin: 20px auto 0;
            overflow: hidden;
            border-radius: 10px;
        }
        .majorList table {
            width: 93%;
            font-size: 13px;
            text-align: center;
            border-collapse: collapse;
            margin: 10px auto;
        }
        .majorList table th {
            padding: 6px 0;
            border: 1px solid #eee;
        }
        .majorList table td {
            border: 1px solid #eee;
            color: #666;
        }
        
        .list-title {
            width: 93%;
            margin: 15px auto 0;
            display: block;
            font-size: 15px;
            color: #ff7637;
            font-weight: bold;
        }
    </style>
</head>

<body>
    
    <div id="app">
        <router-view></router-view>
    </div>
    
    <!--引入Vue應用例項-->
    <script type="module" src="js/app.js"></script>
</body>

</html>

app.js

app.js 也是比較簡單的,構建元件程式碼,然後將元件建立到路由當中渲染到app節點。

const { createApp, ref } = Vue;
const { createRouter, createWebHashHistory, useRouter, useRoute } = VueRouter;

// 院校列表
const collegeList = {
    template: `
    <div>
        <div v-for="college in collegeListData.collegeList" :key="college.college_code" class="college-card" @click="showCollegeInfo(college.college_code)">
            <div class="college-logo">
                <img :src="'img/college_logo/' + college.college_logo" />
            </div>
            <div class="college-info">
                <p class="college-name">{{ college.college_name }}</p>
                <p class="college-category">
                    <span class="tag"> {{ college.college_public === 0 ? '公辦' : '民辦' }} </span>
                    <span class="tag"> {{ college.college_city }} </span>
                    <span class="tag"> {{ college.college_category }} </span>
                </p>
                <p class="college-plan">2023年招生計劃{{ college.college_plan_2023 }}人</p>
            </div>
            <div class="next"></div>
        </div>
    </div>`,
    setup() {
        const collegeListData = ref([]);
        const router = useRouter();

        axios.get('./getCollegeList/')
            .then(response => {
                collegeListData.value = response.data;
            })
            .catch(error => {
                console.error('Error fetching JSON data:', error);
            });

        const showCollegeInfo = (college_code) => {
            router.push(`/college/${college_code}`);
        };

        return {
            collegeListData,
            showCollegeInfo,
        };
    },
};

// 院校詳情
const collegeDetails = {
    template: `
    <div>
        <div class="college-card">
            <div class="college-logo">
                <img :src="'img/college_logo/' + collegeInfo.college_logo" />
            </div>
            <div class="college-info">
                <p class="college-name">{{ collegeInfo.college_name }}</p>
                <p class="college-category">
                    <span class="tag"> {{ collegeInfo.college_public === 0 ? '公辦' : '民辦' }} </span>
                    <span class="tag"> {{ collegeInfo.college_city }} </span>
                    <span class="tag"> {{ collegeInfo.college_category }} </span>
                </p>
                <p class="college-plan">2023年招生計劃{{ collegeInfo.college_plan_2023 }}人</p>
            </div>
        </div>
        <div class="zyzList">
            <span class="list-title">院校專業組</span>
            <table>
                <tr>
                    <th>專業組</th>
                    <th>計劃</th>
                    <th>備註</th>
                </tr>
                <tr v-for="zyz in zyzList" :key="zyz.zyz_code">
                    <td>{{zyz.zyz_code}}</td>
                    <td>{{zyz.zyz_plan}}</td>
                    <td>{{zyz.zyz_bz}}</td>
                </tr>
            </table>
        </div>
        <div class="majorList">
            <span class="list-title">招生專業目錄</span>
            <table>
                <tr>
                    <th>專業組</th>
                    <th>專業</th>
                    <th>計劃</th>
                    <th>最低分/排位</th>
                </tr>
                <tr v-for="major in majorList" :key="major.major_code">
                    <td>{{major.major_zyzcode}}</td>
                    <td>{{major.major_name}}</td>
                    <td>{{major.major_number}}</td>
                    <td v-if="major.major_lowest_score > 0">{{major.major_lowest_score}}/{{major.major_lowest_rank}}</td>
                    <td v-else> / </td>
                </tr>
            </table>
        </div>
    </div>`,
    setup() {
        const collegeInfo = ref({});
        const majorList = ref({});
        const zyzList = ref({});
        const route = useRoute();
        const id = route.params.id;
        axios.get('./getMajorList/?college_code=' + id)
            .then(response => {
                collegeInfo.value = response.data.collegeInfo[0];
                majorList.value = response.data.majorList;
                zyzList.value = response.data.zyzList;
            })
            .catch(error => {
                console.error('Error fetching college details:', error);
            });

        return {
            collegeInfo,
            majorList,
            zyzList
        };
    },
};

// 建立路由
const router = createRouter({
    history: createWebHashHistory(),
    routes: [
        { path: '/', component: collegeList },
        { path: '/college/:id', component: collegeDetails },
    ],
});

// 建立Vue應用
const app = createApp({});
app.use(router);

// 掛載應用
app.mount('#app');

完整程式碼

https://likeyun.lanzout.com/iOAnJ1otloaf

演示

https://demo.likeyunba.com/san-jia-zheng-shu

手機網頁,建議使用手機訪問:

image.png

作者

TANKING

相關文章