[終極巨坑]golang+vue開發日記【二】,登陸界面制作(一)


寫在前面

本期內容是適合第一次使用vue或者golang開發的,內容會以實戰的形式來講解。看懂本段內容需要了解基礎內容有html,css,最好可以看一下vue的基礎。並且這里的每個知識點不可能詳細解說,只會告訴你大概做什么的,入門切記要不求甚解,不然學到自閉

遠征的第一步,啟動一個vue項目

我們這次主要是寫一個以vue為前端框架的登陸和注冊,因此我們的第一步也就是創建一個vue項目,並且這個內容在上一節已經講過了,不過這里我們可以再操作一番。

vue create your_projectname

然后根據之前的配置即可,甚至你可以使用默認配置,接下來假設我們已經創建好了一個項目,然后我們需要怎么啟動他呢?

cd your_projectname
npm run serve

用這個命令一段時間之后,就可以看到項目被啟動在了localhost:8080上(也有可能不是8080端口),在瀏覽器輸入鏈接即可訪問。

基礎的vue操作

寫代碼一定需要一個ide的,因此這里推薦一個ide叫vscode,可在這里下載安裝:vscode官網,然后也可以看看這篇大佬的內容把插件裝好:Vue推薦VSCode開發必備的插件

裝完之后在剛剛vue項目目錄下面輸入code .,就可以看到ide下的環境。你應該會大概看到這樣的文件結構:

一看有一大堆文件,一時間肯定講不完,所以通過實際操作一個個演示到底是作什么的?

首先可以打開一下App.vue,可以看到這樣幾個兩個結構:<templarte>和<style>,template的就是網頁html中body里面的內容,而style就是你平時寫的css文件,然后可以把App.vue改成這樣:

<template>
  <div id="app">
    <router-view/>
  </div>
</template>

這步操作到底在做什么呢?其實是我們之后寫的vue文件是這個文件的子模板,就是router-view,所以我們可以在這里把不必要的元素給刪了,就保留我上面那段即可。以后甚至可以添加一些公共的元素在里面。

接下來可以在views里面新建一個文件叫login.vue,這就是我們的登陸注冊界面了。如果說權限不夠不給你新建文件的可以在上一層文件夾輸入

sudo chmod -R 777 your_projectname

這樣即可獲得權限去創建文件,輸入完之后可以先來一套<template>,<script>和<style>的標簽,這里script就是平時的js腳本,但是在格式上又有所差別,之后寫再講。我們這里寫一個跟icloud類似的登錄界面來實戰演練好了。

首先寫一個主題框架,注意:每一個template下面只有由一大的div包住,不能寫2個及以上!這里我就寫了一個main的div包住其他內容,之后寫了一個bg作為背景,一個page作為頁面。

<template>
    <div class="main">
        <div class="bg">
        </div>
        <div class="page">
        </div>
    </div>
</template>

如果你寫成這樣,就包含了2個div,這樣會直接報錯的。

<template>
<div class="bg">
</div>
<div class="page">
</div>
</template>

接下來我們給bg加一個背景,在style添加如下的基礎樣式這段樣式不是重點,覺得太多不能理解的可以跳過

.main{
    width: 99vw;
    height: 95vh;
    display: flex;
    align-items: center; 
    justify-content: center; 
}

.bg{
    width: 100%;
    height: 100%;
    background: url("https://i.loli.net/2019/09/28/ytGhbzr3Xe7TsAc.png") no-repeat;
    position: absolute;
    background-size: cover;
    -webkit-filter: blur(5px);
    -moz-filter: blur(5px);
    -ms-filter: blur(5px);
    -o-filter: blur(5px);
    filter: blur(5px);
}

.page{
        width: 300px;
        height: 300px;
        position: relative;
        background-color: rgba(255,255,255,0.6);
        border-radius: 8px;
	box-shadow: 0 10px 20px rgba(0,0,0,0.5);
	overflow: hidden;
	z-index: 2;
	padding: 30px;
	box-sizing: border-box;
}

這樣就完成了最初的樣子,給背景加了點高斯模糊,什么?你不知道怎么看到這個界面,這里的話就要講一下router.js了。routers是管理瀏覽器路由的,你可以看到文件中有2個例子,他們的path就是代表路由路徑,name的話代表這個路徑的名字表示,這兩個例子有一個區別,在component中,這個東西是對應的vue文件的物理路徑,可能難以理解的是后者:

component: () => import(/* webpackChunkName: "about" */ './views/About.vue')

這個的意思代表懶加載,其實不用這個的時候,他是有預先加載的,而用了懶加載的時候只有到走到這個路由的時候才會真的加載這個文件,這可以省下不少的初次加載時間。所以我們添加一下我們的路由在routes下。

    {
      path:'/login',
      name:'login',
      component:()=>import("./views/login.vue")
    }

寫出來一個扁平化的登陸界面

我們要作一個好康的界面首先要有一個好康的組件工具,這里我推薦一下上手方便的element,這里可以康他的文檔:vue官方文檔,我們可以直接按他文檔的方法進行安裝

sudo npm i element-ui -S

然后我們在main.js弄成全局的組件,這個main.js實際上就是一個初始化的地方,我們可以在這里加各種全局用組件。

import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';

Vue.use(ElementUI);

接下來我們給這個中間的框加上賬號和密碼輸入框,在page下寫入,就會出現輸入框和密碼框了,這里的輸入框是用element做的:Input 輸入框

<div class="login">
    <el-input v-model="username" placeholder="郵箱賬號" style="margin-top:70px"></el-input>
    <el-input placeholder="請輸入密碼" v-model="password" show-password></el-input>
 </div>

但是你只寫這么點東西八成報錯,這里有個叫v-model的東西,他是用於綁定一個變量的,只要這個元素的值變化了,變量的值也相應發生變化,但是我們的變量在哪呢?所以我們這里得在script的export default下面加入如下的內容。

    data(){
        return{
            username: '',
            password: '',
        }
    },

這里的data是固定格式,在return中輸入變量即可,這樣上面就能拿到變量了,所以也就不會報錯了。

給輸入框弄成彈入彈出的效果

這段內容需要一點動畫基礎,不過實際上並不復雜,我會對其講解一下,首先我們先跟icloud一樣,在輸入框弄2個按鈕。

<el-input v-model="username" placeholder="郵箱賬號" style="margin-top:70px">
    <template slot="append"><el-button type="primary" icon="el-icon-check"></el-button></template>
</el-input>
<el-input placeholder="請輸入密碼" v-model="password" show-password v-if="showPwd">
    <template slot="append"><el-button type="primary" icon="el-icon-check"></el-button></template>
</el-input>

這里有2個知識點,slot和v-if,slot的話理解起來很復雜,現在可以理解成一個可以插入任何東西的地方,這里就把button插入到el-input的末尾,剛入門就理解到這里就好了。而v-if就很明顯,只有if里面的內容是true,他才會被渲染,false的時候他就會被移除出Dom,所以也要在data中加入相應的變量。

接下來我們給按鈕添加一個事件,當我們按下去的時候判斷郵箱格式是否正確,因此我們在button加入如下內容:

<el-button type="primary" icon="el-icon-check" @click="checkEmail">

這個@click就是點擊這個按鈕觸發里面的方法,以后看到@或者v-on就是事件的監聽器,所以@click顧名思義,就是監聽一個click事件,當被點擊就觸發里面的方法。因此我們也要寫這么一個方法,自然是寫在script下面了。

    methods:{
        checkEmail(){
            var pattern = /^([a-zA-Z0-9]+[_|\_|\.]?)*[a-zA-Z0-9]+@([a-zA-Z0-9]+[_|\_|\.]?)*[a-zA-Z0-9]+\.[a-zA-Z]{2,3}$/;
            if(pattern.test(this.username)){
                this.showPwd = true;
            }else{
                this.$message.error('郵箱格式錯了哦~');
            }
        },
    },

在script下面的methods是存放各種方法的,這里的方法都可以被template中的標簽所使用,所以我們在這里加入。這里可以講解一下郵箱驗證的方法:

首先你需要明白正則表達式,明白了基本就解決了,不明白的可以看:30分鍾正則表達式教程。因此這里就是拿正則表達式匹配,匹配了呢就讓v-if的變量為true,請注意,我們在方法中用到data中的變量都是this.變量名,而下面的那個this.$message是element中的錯誤提示框,詳情可以看消息提示

這還不夠,人家做的東西是有動畫的,你的咋就沒有呢?所以得給他加個動畫,那么這里可能要用到transition組件了,這個組件是通過檢測v-if和v-show的狀態,在狀態變化的時候給動畫的,我現在給密碼框加動畫就是如此:

<transition name="showpwd">
    <el-input placeholder="請輸入密碼" v-model="password" show-password v-if="showPwd" style="z-index:-2">
        <template slot="append"><el-button type="primary" icon="el-icon-check"></el-button></template>
    </el-input>
</transition>

這里name務必獨一無二,因為接下來要在css用到這個名字。

然后我們在css寫上動畫,css的名字是根據你的name屬性來取的,而他又分為進入和離開狀態,因為內容太多了,詳細請看:進入/離開 & 列表過渡。不過注意的是這里的translateY中的值要跟我們的input高度一致,這樣效果才可以出來。

.showpwd-enter,.showpwd-leave-to{
    transform:translateY(-40px);
}

.showpwd-enter-active,.showpwd-leave-active{ 
    transition:all .8s ease-out;
}

現在你輸入郵箱試一試,是不是能看到效果了呢?

讓注冊界面融入進來

說是讓注冊界面融入進來,但是我們好像連個注冊界面都還沒有。因此我們先寫一個注冊界面,先貼寫好的源碼:

<div class="register" v-else key="register">
    <el-form :model="register_form" status-icon :rules="rules" ref="ruleForm" label-width="70px">
    <el-form-item label="用戶名" prop="username" style="margin-top:70px">
        <el-input type="text" v-model="register_form.username"></el-input>
    </el-form-item>
     <el-form-item label="郵箱" prop="email" style="margin-top:40px">
        <el-input type="text" v-model="register_form.email"></el-input>
    </el-form-item>
    <el-form-item label="密碼" prop="pass" style="margin-top:40px">
        <el-input type="password" v-model="register_form.password" autocomplete="off"></el-input>
    </el-form-item>
     <el-form-item label="確認密碼" prop="checkPass" style="margin-top:40px">
        <el-input type="password" v-model="register_form.checkPass" autocomplete="off"></el-input>
     </el-form-item>
    <el-form-item style="margin-top:40px;">
        <el-button type="primary" @click="submitForm('ruleForm')">注冊</el-button>
    </el-form-item>
    </el-form>
 </div>

這個界面是一個form表單:element表單。這里呢他是一個帶有驗證機制的form,就是說你每次輸入一個內容的時候他都會去匹配規則,看看是否輸入了正確的內容。這里在el-form有個一個:rules的東西,這個就是規則列表,注意,這里的:代表的是里面的內容是變量,假設不加:,他的意思就是rules這個字符串,而加上了他會代表data()中的變量。接下來可以看一看rules是怎么寫的。

            rules: {
                username: [
                    {validator: (rule, value, callback) => {
                        if(value==""){
                            callback(new Error('請輸入用戶名'));
                        }
                        callback();
                    }, trigger: 'blur' }
                ],
                email: [
                    { validator: (rule, value, callback) => {
                        var pattern = /^([a-zA-Z0-9]+[_|\_|\.]?)*[a-zA-Z0-9]+@([a-zA-Z0-9]+[_|\_|\.]?)*[a-zA-Z0-9]+\.[a-zA-Z]{2,3}$/;
                        if(!pattern.test(value)){
                            callback(new Error('請輸入正確的郵箱格式'));
                        }
                        callback();
                    }, trigger: 'blur' }
                ],
                pass: [
                    { validator: (rule, value, callback) => {
                        if (value === '') {
                            callback(new Error('請輸入密碼'));
                        }
                        callback();
                    }, trigger: 'blur' }
                ],
                checkPass: [
                    { validator: (rule, value, callback) => {
                        if (value === '') {
                            callback(new Error('請再次輸入密碼'));
                        }else if (value !== this.register_form.password) {
                            callback(new Error('兩次輸入密碼不一致!'));
                        }
                        callback();
                    }, trigger: 'blur' }
                ],
            },

這里的代碼每一種驗證規則都是由validator: (rule, value, callback) 組成,接下來用一個匿名函數=>{}來寫內容,value代表的是值,而callback代表回調的內容,如果匹配不正確需要callback(new Error),正確的話回調一個空的即可。最后還有一個trigger屬性,這個表示觸發這個判斷的時機,這里我都使用了blur,就是焦點離開時觸發。最后只需要在你需要進行校驗的表單元素寫上prop="",里面的內容寫上你的校驗規則的名稱,就可以進行校驗了。最后強調一點,仔細看,他只是一個dict變量,因此我們要把它在data()里面

接下來有了注冊界面了,那我們怎么弄到頁面里面呢?我就想了想把他們做成一個翻轉的特效,讓他出現在這里面,所以我們最后的代碼結構如下:

 <div class="box_3d">
        <transition name="page" mode="out-in">
                    <div class="login" v-if="sideLogin" key="login">
                    </div>
                    <div class="register" v-else key="register">
                    </div>
        </transition>
</div>

為什么要作一個box_3d在這里呢,他其實是來控制一個3d的效果的,他的css如下:

.box_3d{
    perspective: 500px;
    -webkit-perspectiv: 500px;
    transform-style: preserve-3d;
}

使用perspective和transform-style可以給他的子物體獲得一個3d的效果,這里可能需要一些透視的知識,perspective代表是焦距,他的等於你的眼睛,而我們平時看到的畫面是你的眼睛觀察物體的投影,所以越大他越靠后,看到的物體會越小。而transform-style是選擇子物體的模式,這里選3d才可以讓子物體3d化,perspective要發揮效果必須設置成3d。只要設置了2者,你有了子物體的3d化,也有了自己的眼睛,因此就能看到3d的效果了。

其次這里的transition有個mode,選擇out-in的話就是先消失原物體,之后再載入新的物體,這里就會有2個動畫,對於下面的2個div,用v-if和v-else既可以控制2者的開關,並且key一定要設置,因為transition是通過key的不同區分物體的,最后貼一下2個頁面的css:

.page-enter-active, .page-leave-active {
  transition: all .5s linear;
}

.page-leave-to{
    transform: rotateY(-90deg);
}

.page-enter{
    transform: rotateY(90deg);
}

接下來的計划

做到這里界面差不多做完了,但是你會問,這就只有一個樣子啊,我又不能注冊又不能登陸的。那是必須的,我們后端都沒有哪來的登陸注冊可言,因此接下來應該用golang開始寫一套后端了,這會在接下來開始寫的。下面會貼出這里的全部源碼,如果按上面的思路沒做出來可以先復制下來看看效果,然后再研究哪里的思路有問題:

<template>
    <div class="main">
        <div class="bg">
        </div>
        <div class="box_3d">

        <transition name="page" mode="out-in">
            <div class="login" v-if="sideLogin" key="login">
            <el-input placeholder="郵箱賬號" v-model="username" style="margin-top:70px;z-index:18;" @input="checkEmailEmp" @keyup.enter.native="checkEmail">
                <template slot="append">
                    <el-button ttype="primary" icon="el-icon-check" circle @click="checkEmail" v-if="showButton"></el-button>
                </template>
            </el-input>
            <transition name="fade">
                <el-input type="password" placeholder="密碼" v-model="password" v-if="showpsd" key="pwd-open" @keyup.enter.native="dologin">
                    <template slot="append">
                      <el-button type="primary" icon="el-icon-check" circle @click="dologin" v-if="!showButton"></el-button>
                    </template>
                </el-input>
            </transition>
            </div>

            <div class="register" v-else key="register">
                <el-form :model="register_form" status-icon :rules="rules" ref="ruleForm" label-width="70px">
                <el-form-item label="用戶名" prop="username" style="margin-top:70px">
                    <el-input type="text" v-model="register_form.username"></el-input>
                </el-form-item>
                <el-form-item label="郵箱" prop="email" style="margin-top:40px">
                    <el-input type="text" v-model="register_form.email"></el-input>
                </el-form-item>
                <el-form-item label="密碼" prop="password" style="margin-top:40px">
                    <el-input type="password" v-model="register_form.password" autocomplete="off"></el-input>
                </el-form-item>
                <el-form-item label="確認密碼" prop="checkPass" style="margin-top:40px">
                    <el-input type="password" v-model="register_form.checkPass" autocomplete="off"></el-input>
                </el-form-item>
                <el-form-item style="margin-top:40px;">
                    <el-button type="primary" @click="submitForm('ruleForm')">注冊</el-button>
                </el-form-item>
                </el-form>
            </div>
        </transition>
        </div>
        <div class="footer">
            <p style="font" @click="changePage">{{sideLogin? "注冊賬號": "登錄賬號"}}</p >
        </div>
    </div>

</template>

<script>
export default {
    name:"login",
    data(){
        return{
            username: "",
            password: "",
            showpsd: false,
            showButton: true,
            sideLogin: true,
            view: 'login',
            register_form:{
                username:"",
                email:"",
                password:"",
                checkpass:"",
            },
            rules: {
                username: [
                    {validator: (rule, value, callback) => {
                        if(value==""){
                            callback(new Error('請輸入用戶名'));
                        }
                        callback();
                    }, trigger: 'blur' }
                ],
                email: [
                    { validator: (rule, value, callback) => {
                        var pattern = /^([a-zA-Z0-9]+[_|\_|\.]?)*[a-zA-Z0-9]+@([a-zA-Z0-9]+[_|\_|\.]?)*[a-zA-Z0-9]+\.[a-zA-Z]{2,3}$/;
                        if(!pattern.test(value)){
                            callback(new Error('請輸入正確的郵箱格式'));
                        }
                        callback();
                    }, trigger: 'blur' }
                ],
                password: [
                    { validator: (rule, value, callback) => {
                        if (value === '') {
                            callback(new Error('請輸入密碼'));
                        }
                        callback();
                    }, trigger: 'blur' }
                ],
                checkPass: [
                    { validator: (rule, value, callback) => {
                        if (value === '') {
                            callback(new Error('請再次輸入密碼'));
                        }else if (value !== this.register_form.password) {
                            callback(new Error('兩次輸入密碼不一致!'));
                        }
                        callback();
                    }, trigger: 'blur' }
                ],
            },
        }
    },
    methods:{
        checkEmail(){
            var pattern = /^([a-zA-Z0-9]+[_|\_|\.]?)*[a-zA-Z0-9]+@([a-zA-Z0-9]+[_|\_|\.]?)*[a-zA-Z0-9]+\.[a-zA-Z]{2,3}$/;
            if(pattern.test(this.username)){
                this.showpsd = true;
                this.showButton = false;
            }else{
                this.$message.error('郵箱格式不正確!');
            }
        },
        checkEmailEmp(newstr){
            if(newstr == ""){
                this.showpsd = false;
                this.showButton = true;
            }
        },
        dologin(){

        },
        changePage(){
            this.sideLogin = !this.sideLogin
            if(this.sideLogin){
                this.view = "login"
            }else{
                this.view = "register"
            }
        },
        submitForm(){

        },
        resetForm(){

        }
    }
}
</script>

<style>
.main{
    width:99vw;
    height:95vh;
    display: flex;
    align-items: center;
    justify-content: center;
}
.bg{
    width: 100%;
    height: 100%;
    background: url("https://i.loli.net/2019/09/28/ytGhbzr3Xe7TsAc.png") no-repeat;
    background-size: cover;
    position: absolute;
    -webkit-filter: blur(5px);
	-moz-filter: blur(5px);
	-ms-filter: blur(5px);
	-o-filter: blur(5px);
	filter: blur(5px);
}

.login{
    width: 300px;
    height: 300px;
    position: relative;
	border-radius: 8px;
    background-color: rgba(255,255,255,0.6);
	box-shadow: 0 10px 20px rgba(0,0,0,0.5);
	overflow: hidden;
	z-index: 2;
	padding: 30px;
	box-sizing: border-box;
}

.register{
    width: 400px;
    height: 500px;
    position: relative;
	border-radius: 8px;
    background-color: rgba(255,255,255,0.6);
	box-shadow: 0 10px 20px rgba(0,0,0,0.5);
	overflow: hidden;
	z-index: 2;
	padding: 10px 50px 10px 20px;
	box-sizing: border-box;
}

.fade-enter-active,.fade-leave-active{
  transition: all .5s ease;
}

.fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {
  transform: translateY(-40px);
  /* opacity: 0; */
}

.footer{
    width: 200px;
    height: 30px;
    position: absolute;
    top: 90%;
    left: 49%;
}

.footer > p{
    color: floralwhite;
    text-shadow:5px 2px 6px #000;
}

.footer >p:hover{
    cursor: pointer;
}

.page-enter-active, .page-leave-active {
  transition: all .5s linear;
}

.page-leave-to{
    transform: rotateY(-90deg);
}

.page-enter{
    transform: rotateY(90deg);
}

.box_3d{
    perspective: 500px;
    -webkit-perspectiv: 500px;
    transform-style: preserve-3d;
}
</style>


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM