Framework7はWeb用のUIフレームワークです。主にモバイルを対象としており、VueやReactなどでも利用できます。
そんなFramework7にはログイン画面というコンポーネントがあるのですが、今回は認証が必要な画面の判定処理を入れつつ、良い感じにルーティングを処理してみました。
実際の認証処理
動画にすると以下のようになります。ログインしていなければログイン画面が出て、ログイン完了すると本来表示したかった画面が表示されます。
NCMBの初期化
NCMBのJavaScriptはncmb.min.jsやnpmなどを使ってインストールできます。
初期化はNCMBで取得できるアプリケーションキー、クライアントキーを使います。
const ncmb = new NCMB('APPLICATION_KEY', 'CLIENT_KEY');
Framework7のルーティング
Framework7はパスで指定したルーティングをサポートしています。その中で、 beforeEnter
キーにて画面遷移する前の判定を入れられます。
const routes = [
{
path: '/',
url: './index.html',
},
{
path: '/home/',
componentUrl: './pages/home.html',
beforeEnter, // 認証処理
},
beforeEnter
は以下のように変数を受け取ります。
const beforeEnter = async ({resolve, reject, router}) => {
};
そのまま画面遷移して良い場合は resolve()
を呼び、リダイレクトなど別な画面への移動を行う場合には reject()
を実行します。実際の画面遷移は router
で指定します。
beforeEnterでの処理
beforeEnterではNCMBの認証状態をチェックします。もしログイン前だったり、ログイン情報はあるもののセッションの有効期限が切れている場合には認証処理を行います。
openLoginScreen
がユーザー登録&ログイン処理を行うのですが、ログイン画面が消えるまでをawaitで待っています。こうすることで、リダイレクトのような処理もなく、本来表示したかった画面を表示するだけになります。
// 認証が必要な画面にアクセスした時の処理
const beforeEnter = async ({resolve, reject, router}) => {
// 現在ログインしているユーザー情報を取得
const currentUser = ncmb.User.getCurrentUser();
// 認証していない場合はnullになる
if (!currentUser) {
// 認証画面を出して、処理が完了するのを待つ
await openLoginScreen();
// resolveを実行(元々指定されている画面を表示)
resolve();
}
try {
// データストアにダミーアクセス
await ncmb.DataStore('Hello').fetch();
// アクセスできればresolveを実行(元々指定されている画面を表示)
resolve();
} catch (e) {
// 駄目だった場合は認証情報を削除
localStorage.removeItem("NCMB/"+ncmb.apikey+"/currentUser");
// 認証画面を出して、処理が完了するのを待つ
await openLoginScreen();
// resolveを実行(元々指定されている画面を表示)
resolve();
}
};
openLoginScreenの処理
openLoginScreen
ではログイン画面の表示と、ログイン画面のイベント処理を行っています。アプリが立ち上がった直後は app.loginScreen
がないので、それができるまで処理を待ちます。
ログインボタンを押したタイミングで loginOrSignup
を実行し、その結果がうまくいったらログイン画面を閉じて処理を完了します。
// ログイン画面を表示する処理
const openLoginScreen = () => {
return new Promise((res, rej) => {
const id = setInterval(() => {
// ログイン画面の準備ができるのを待つ
if (!app.loginScreen) {
return;
}
// 準備できていたらインターバル処理を止める
clearInterval(id);
// ログイン画面を表示
app.loginScreen.open('#login-screen');
// ログイン画面が開いた時の処理
$('.login-screen').on('loginscreen:opened', (_) => {
$('.login-screen .login-button').on('click', async (e) => {
e.preventDefault();
try {
// ログイン&新規登録処理
await loginOrSignup();
// ログイン画面を閉じる
app.loginScreen.close();
res();
} catch (_) {
// ログインに失敗した場合はエラーメッセージを表示
app.toast.create({
text: 'ログインに失敗しました',
position: 'center',
closeTimeout: 2000,
}).open();
}
});
});
}, 100);
});
};
loginOrSignupの処理
loginOrSignup
はNCMBの認証処理になります。最初にユーザー登録処理を行い、その結果いかんに関わらずログイン処理を行います。もしすでにユーザーがいる場合にはユーザー登録処理はエラーになりますが、そのままログインを行うことでユーザー登録とログイン処理を一つの処理でできます。
// ログイン&新規登録処理
const loginOrSignup = async () => {
// フォームからユーザー名とパスワードを取得
const params = app.form.convertToData($('.login-screen #login-form'));
try {
// ユーザー登録
const user = new ncmb.User;
await user
.set("userName", params.username)
.set("password", params.password)
.signUpByAccount();
} catch (_) {
// 失敗した場合はすでにユーザーが存在する場合
}
// ログイン処理
await ncmb.User.login(params.username, params.password);
return true;
};
まとめ
Framework7のログインコンポーネントとNCMBを組み合わせることで、アプリの認証処理を手軽に実装できます。ルーティング処理の部分だけで実現できるので、ぜひトライしてください。