首先來看看qq的登陸界面:
css
import {BrowserWindow, webContents, app, ipcMain} from 'electron' LoginWindow(); //暫時調用 ipcMain.on('quitApp', () => { app.quit(); }); function LoginWindow() { const loginURL = process.env.NODE_ENV === 'development' ? `http://localhost:9080/#/login` : `file://${__dirname}/index.html/#/login`; const loginWindow = new BrowserWindow({ width: 430, height: 328, alwaysOnTop: true, modal: true, frame: false, darkTheme: true, resizable: false, minimizable: false, maximizable: false, transparent: true, webPreferences: { devTools: false, } }); loginWindow.setMenu(null); loginWindow.loadURL(loginURL); }
咱們先大概作一個這樣的界面
html
<template> <div class="mainWindow"> <header class="header"></header> <main> <div class="bg"></div> <div class="body"></div> </main> <footer class="footer"></footer> </div> </template> <script> import '@/assets/css/login.css' export default { } </script>
/** 取消所有的外邊距和內邊距 */ * { padding: 0; margin: 0; } /*設置窗口的樣式*/ .mainWindow { cursor: pointer; /*設置手型*/ border: 1px solid red; /*加一個邊框 調試樣式 最後要刪除或者更改**/ width: 428px; /*設置寬度 必需要和主進程中設置的同樣 不能大於主進程中設置的寬度 不然會出現滾動條*/ height: 326px; /*設置高度 必需要和主進程中設置的同樣 不能大於主進程中設置的高度 不然會出現滾動條*/ position: relative; /*設置爲相對定位*/ border-radius: 4px; /*設置圓角*/ } /** header的樣式 header中只會有一個關閉按鈕 處於右上角 */ .mainWindow header.header { position: absolute; /*設置絕對定位 由於背景在他下面*/ height: 30px; /*設置高度*/ background: rgba(0, 0, 0, 0.5); /*暫時設置的 後面要刪除或者更改*/ border-radius: 4px 4px 0 0; /*給header的左上角 右上角設置圓角 否則會出現很尷尬的頁面*/ width: 428px; /* 由於設置了絕對定位 設置寬度*/ } /** 背景 */ .mainWindow main .bg { height: 124px; /*設置高度*/ width: 428px; /*設置寬度 也能夠不用設置 由於這個元素沒有設置絕對定位 因此默認就是100%*/ border-radius: 4px 4px 0 0; /*給左上角 右上角設置圓角 否則會出現很尷尬的頁面 這裏和header重合在一塊兒了*/ background: blue; /*暫時設置的 後面要刪除或者更改*/ } /** 放置表單的元素 */ .mainWindow main .body { width: 428px; /*設置寬度 也能夠不用設置 由於這個元素沒有設置絕對定位 因此默認就是100%*/ height: 172px; /*設置高度 這裏的高度是 主窗口(326) - footer(30) - 背景(124) 由於header設置了絕對定位 因此不用關 */ background: green; /*暫時設置的 後面要刪除或者更改*/ } .mainWindow footer.footer { position: absolute; /* 設置絕對定位 要讓他處於窗口的最底部*/ height: 30px; /*設置高度 */ background: red; /*暫時設置的 後面要刪除或者更改*/ bottom: 0; /*讓footer處於底部*/ width: 428px; /* 由於設置了絕對定位 設置寬度*/ }
注意 不要使用內置的拖動 咱們要本身實現!
在頁面中加入如下代碼就能夠實現拖動了!vue
data() { return { windowX: 0, windowY: 0, } }, mounted() { let win = this.$electron.remote.getCurrentWindow(); document.addEventListener('mousedown', function (e) { this.windowX = e.x; this.windowY = e.y; document.addEventListener('mousemove', moveEvent); }); document.addEventListener('mouseup', function () { this.windowX = 0; this.windowY = 0; document.removeEventListener('mousemove', moveEvent) }); function moveEvent(e) { win.setPosition(e.screenX - this.windowX, e.screenY - this.windowY) } }
將css裏面的 .bg修改爲:git
.mainWindow main .bg { height: 124px; /*設置高度*/ width: 428px; /*設置寬度 也能夠不用設置 由於這個元素沒有設置絕對定位 因此默認就是100%*/ border-radius: 4px 4px 0 0; /*給左上角 右上角設置圓角 否則會出現很尷尬的頁面 這裏和header重合在一塊兒了*/ background: url("../images/login-back.gif") 10px; background-size: 100%; }
完成以後效果如以下:github
頂部的logo和最小化就不作了 只作一個關閉的按鈕
去阿里巴巴圖標庫下載字體文件以後放到assets/fonts目錄中
在頁面中加入:web
import '@/assets/fonts/iconfont.css'
header代碼:vuex
<header class="header"> <span class="iconfont icon-guanbi1"></span> </header>
css文件
注意 在css .mainWindow header.header 添加
因爲我背景圖的關係 按鈕可能不太明顯 這問題不大 你們能夠本身換一個圖!app
background: rgba(255, 255, 255, 0.2); /*暫時設置的 後面要刪除或者更改*/ text-align: right;
.mainWindow header.header span{ display: inline-block; height: 30px; width:30px; text-align: center; line-height: 30px; color:#E4393c; } .mainWindow header.header span:hover{ background-color: rgba(255,255,255,0.6); }
建立一個子組件 login.vue
寫入以下代碼:electron
<template> <div class="form"> <form> <div class="form_item"><i class="iconfont icon-1zhanghu"></i><input type="text"></div> <div class="form_item"><i class="iconfont icon-mima1"></i><input type="password"></div> </form> <div class="buttons"> <button>登陸</button> </div> </div> </template> <script> export default { name: "login" } </script>
須要將 .mainWindow main .body 的背景顏色調成#FFFFFF佈局
.form form{ padding:10px 90px 0 90px; } .form_item{ height: 40px; position: relative; } .form_item i.iconfont{ position: absolute; top:5px; } .form_item input{ outline: none; border:none; padding-left: 20px; font-size: 16px; width: 230px; height: 30px; border-bottom: 1px solid #CCC; } .buttons{ text-align: center; } .buttons button{ background-color: #CF000E; border: none; width: 250px; color: #FFFFFF; height: 35px; cursor: pointer; font-size: 14px; border-radius: 4px; outline: none; }
最後看到是這樣的
<div class="login_options"> <label><div class="option_item"><input type="checkbox"><span class="checked"><img src="@/assets/images/checked.png" alt=""></span></div><i class="text">自動登陸</i></label> <label><div class="option_item"><input type="checkbox"><span class="checked"><img src="@/assets/images/checked.png" alt=""></span></div><i class="text">記住密碼</i></label> <i class="text">忘記密碼</i> </div>
.login_options{ margin-bottom: 10px; margin-top: 5px; } .login_options .option_item { display: inline-block; width: 13px; height: 13px; margin-right: 5px; position: relative; border: 1px solid orange; vertical-align: middle; cursor: pointer; top: -2px; } .login_options .option_item input { opacity: 0; } .login_options i.text{ display: inline-block; margin-right: 14px; font-size: 13px; font-style: normal; } .login_options .option_item span.checked { position: absolute; top: -4px; right: -3px; font-weight: bold; display: inline-block; width: 20px; height: 20px; cursor: pointer; } .option_item span.checked img { width: 100%; height: 100%; } input[type="checkbox"] + span { opacity: 0; } input[type="checkbox"]:checked + span { opacity: 1; }
咱們改進一點 由於qq的註冊是一個鏈接到web頁面去申請qq號碼的 不過我作的是點擊註冊將界面切換到註冊界面,只不過是
在寫註冊界面代碼以前先將父組件種的login註釋掉備用 (別刪除哦) 在父組件中引入Register組件
註冊的邏輯是這樣的 在註冊界面輸入手機號和圖形驗證碼 獲取到短信驗證碼輸入以後跳轉到下一步輸入密碼
若是將所有的邏輯寫到一個組件中會致使太長 雖然有辦法解決 可是以後使用動畫就很難看了!
<template> <div class="form"> <form> <div class="form_item"><i class="iconfont icon-phone_icon"></i><input type="text"></div> <div class="form_item"> <i class="iconfont icon-yanzhengma2"></i> <input type="password"> <div class="captcha"> <img src="@/assets/images/captcha.png" alt=""> </div> </div> <div class="form_item"> <i class="iconfont icon-yanzhengma5"></i> <input type="password"> <div class="send_sms_captcha"><button>獲取短信驗證碼</button></div> </div> </form> <div class="buttons"> <button>下一步</button> </div> </div> </template> <script> export default { name: "register" } </script>
.captcha { position: absolute; width: 120px; height: 30px; top: -2px; right: 0; } .captcha img { width: 100%; height: 100%; } .send_sms_captcha { position: absolute; top: -2px; right: 0; } .send_sms_captcha button{ width:120px; height: 30px; border:none; outline: none; cursor: pointer; border-radius: 4px; }
部分代碼:
<main> <div class="bg"></div> <div class="body"> <!--<Login></Login>--> <Register></Register> </div> </main>
<template> <div class="form"> <form> <div class="form_item"><i class="iconfont icon-zaicishurumima"></i><input type="text"></div> <div class="form_item"><i class="iconfont icon-mima1"></i><input type="password"></div> <div class="login_options" style="text-align: center"> <label><div class="option_item"><input type="checkbox"><span class="checked"><img src="@/assets/images/checked.png" alt=""></span></div><i class="text">自動登陸</i></label> <label><div class="option_item"><input type="checkbox"><span class="checked"><img src="@/assets/images/checked.png" alt=""></span></div><i class="text">記住密碼</i></label> </div> </form> <div class="buttons"> <button>登陸</button> </div> </div> </template> <script> export default { name: "steps2" } </script>
在上面中footer裏面顯示了註冊帳號
其實這只是暫時的方案 爲了方便截圖
首先來分析一下 在登陸頁面的時候在底部顯示註冊帳號 在註冊第一步的時候在底部左側顯示已經帳號,在第二步驟的時候顯示返回上一步
咱們有不少辦法在子組件通知父組件去顯示不一樣的文字
做者給出兩個方案:
1: 經過子組件給父組件傳值
2: 使用vuex
3: 將footer拆分到各個組件中
咱們代碼中使用拆分就好了 比較簡單點
將父組件的footer刪除
往組件login.vue steps1.vue steps2.vue 組件中加入footer
<template> <div class="form"> <form> <div class="form_item"><i class="iconfont icon-1zhanghu"></i><input type="text"></div> <div class="form_item"><i class="iconfont icon-mima1"></i><input type="password"></div> <div class="login_options"> <label><div class="option_item"><input type="checkbox"><span class="checked"><img src="@/assets/images/checked.png" alt=""></span></div><i class="text">自動登陸</i></label> <label><div class="option_item"><input type="checkbox"><span class="checked"><img src="@/assets/images/checked.png" alt=""></span></div><i class="text">記住密碼</i></label> <i class="text">忘記密碼</i> </div> </form> <div class="buttons"> <button>登陸</button> </div> <footer class="footer"> <span @click="toggleWindow">註冊帳號</span> </footer> </div> </template> <script> export default { name: "login", methods:{ toggleWindow(){ this.$store.dispatch('toggleLogin'); } } } </script>
<template> <div class="form"> <form> <div class="form_item"><i class="iconfont icon-phone_icon"></i><input type="text"></div> <div class="form_item"> <i class="iconfont icon-yanzhengma2"></i> <input type="password"> <div class="captcha"> <img src="@/assets/images/captcha.png" alt=""> </div> </div> <div class="form_item"> <i class="iconfont icon-yanzhengma5"></i> <input type="password"> <div class="send_sms_captcha"><button>獲取短信驗證碼</button></div> </div> </form> <div class="buttons"> <button @click="toggleSteps">下一步</button> </div> <footer class="footer"> <span @click="toggleWindow">已有帳號</span> </footer> </div> </template> <script> export default { name: "steps1", methods:{ toggleWindow(){ this.$store.dispatch('toggleLogin'); }, toggleSteps(){ this.$store.dispatch('toggleSteps'); }, } } </script>
<template> <div class="form"> <form> <div class="form_item"><i class="iconfont icon-zaicishurumima"></i><input type="text"></div> <div class="form_item"><i class="iconfont icon-mima1"></i><input type="password"></div> <div class="login_options" style="text-align: center"> <label><div class="option_item"><input type="checkbox"><span class="checked"><img src="@/assets/images/checked.png" alt=""></span></div><i class="text">當即登陸</i></label> <label><div class="option_item"><input type="checkbox"><span class="checked"><img src="@/assets/images/checked.png" alt=""></span></div><i class="text">記住密碼</i></label> </div> </form> <div class="buttons"> <button>註冊</button> </div> <footer class="footer"> <span @click="toggleSteps">返回上一步</span> </footer> </div> </template> <script> export default { name: "steps2", methods:{ toggleSteps(){ this.$store.dispatch('toggleSteps'); }, } } </script>
const state = { steps: true, login: true, }; const actions = { toggleSteps: function ({state, commit}) { // state.steps = true; state.steps = !state.steps; }, toggleLogin({state, commit}){ state.login = !state.login; } }; export default ({ state, actions });
上面這些完成以後有點單調 尤爲是切換的時候 咱們能夠用到 animateCss
animateCss 下載地址:https://daneden.github.io/ani...
子組件加入:
import '@/assets/css/animate.css'
以後咱們在代碼中加入效果就好了
將父組件改爲:
<main> <div class="bg"></div> <transition :duration="500" :enter-active-class="'animated ' + (login ? 'bounceInRight' : 'bounceInLeft')" :leave-active-class="'animated ' + (login ? 'bounceOutLeft' : 'bounceOutRight')" > <Login v-if="login === true" key="login"></Login> <Register v-else key="register"></Register> </transition> </main>
子組件 register.vue改爲:
<transition :duration="500" :enter-active-class="'animated ' + (steps ? 'bounceInRight' : 'bounceInLeft')" :leave-active-class="'animated ' + (steps ? 'bounceOutLeft' : 'bounceOutRight')" > <Steps1 v-if="steps === true" key="steps"></Steps1> <Steps2 v-else key="steps"></Steps2> </transition>
修改下css 由於要使用動畫就要將main定位才能用
加入:
.mainWindow main { position: absolute; }
效果展現:
到這裏就差很少了 代碼太多無法一一發布上來 若是有須要的能夠去github下載或者加QQ羣 814270669
github地址:https://github.com/lihaotian0...
碼雲地址: https://gitee.com/leehaotian/...
個人github帳號出了問題 一直登陸不上去 因此就先發布到碼雲了