Nativescript-Vue: Firebase/Firestore Confusion w/nativescrip



我知道这只是我在这一点上缺乏理解,但我不知道还能去哪里,我觉得我现在需要一个ELI5。现在我没有犯任何错误,但我也不确定该朝哪个方向去完成下一个问题/任务。

这是我第一次使用Firebase开发Nativescript应用程序。我能够关注这篇有用的文章(https://hub.packtpub.com/firebase-nativescript-cross-platform-app-development/)以使我通过Firebase的身份验证,但现在我正尝试使用Firestore访问我的集合,以便显示其中的数据文档。Home.vue是一个选项卡式布局(后面还有一些额外的代码(,在这些选项卡式视图中,我试图添加功能来CRUD firestore数据。

我目前正在处理两个页面,用于nativescript-pluginfirebase的CloudFirestore页面(https://github.com/EddyVerbruggen/nativescript-plugin-firebase/blob/master/docs/FIRESTORE.md)和Google Firebase文档(https://firebase.google.com/docs/firestore/quickstart)。

我觉得我现在没有正确初始化Firebase/Firestore,为什么我很难理解,我只是不知道。在这一点上,任何指导或帮助都将不胜感激。

  • 我想知道的一件事是,即使我使用了nativescript-pluginfirebase插件,我是否仍然必须添加我唯一的Initialize代码。如果是这样的话,我觉得我应该有一个单独的*.js文件来满足我所有的Firebase需求。任何建议都将不胜感激

app.js


import VueDevtools from 'nativescript-vue-devtools';
import Vue from "nativescript-vue";
import LoginPage from './components/LoginPage';
//import DashboardPage from "./components/DashboardPage.vue";
import FloatLabel from './components/FloatLabel';
Vue.component('FloatLabel', FloatLabel);
Vue.use(VueDevtools)
// Initialize Firebase
var firebase = require("nativescript-plugin-firebase");
//Addig the code on the line below makes the debugger crrash (unaccepted app.js)
var db = require("nativescript-plugin-firebase/app/firestore");
firebase.init({}).then((instance) => {
console.log("[*] Firebase was successfully initialised");
}, (error) => {
console.log("[*] Huston we've an initialization error: " + error);
});
//var db = require("firebase/firestore"); 
// Integrate Firestore
//var bulkyCollection = firebase.firestore().collection("bulktrash")
//const backendService = new BackendService();
//Vue.prototype.$backendService = backendService;
new Vue({
render: h => h('frame', [h(LoginPage)])
}).$start()

登录页面.vue


<template>
<Page>
<FlexboxLayout class="page">
<StackLayout class="form">
<Image class="logo" src="~/images/logo.png" />
<Label class="header" text="BULKY" />
<StackLayout class="input-field" marginBottom="25">
<TextField class="input" hint="Email" keyboardType="email" autocorrect="false" autocapitalizationType="none" v-model="user.email"
returnKeyType="next" @returnPress="focusPassword" fontSize="18" />
<StackLayout class="hr-light" />
</StackLayout>
<StackLayout class="input-field" marginBottom="25">
<TextField ref="password" class="input" hint="Password" secure="true" v-model="user.password" :returnKeyType="isLoggingIn ? 'done' : 'next'"
@returnPress="focusConfirmPassword" fontSize="18" />
<StackLayout class="hr-light" />
</StackLayout>
<StackLayout v-show="!isLoggingIn" class="input-field">
<TextField ref="confirmPassword" class="input" hint="Confirm password" secure="true" v-model="user.confirmPassword" returnKeyType="done"
fontSize="18" />
<StackLayout class="hr-light" />
</StackLayout>
<Button :text="isLoggingIn ? 'Log In' : 'Sign Up'" @tap="submit" class="btn btn-primary m-t-20" />
<Label v-show="isLoggingIn" text="Forgot your password?" class="login-label" @tap="forgotPassword" />
</StackLayout>
<Label class="login-label sign-up-label" @tap="toggleForm">
<FormattedString>
<Span :text="isLoggingIn ? 'Don’t have an account? ' : 'Back to Login'" />
<Span :text="isLoggingIn ? 'Sign up' : ''" class="bold" />
</FormattedString>
</Label>
</FlexboxLayout>
</Page>
</template>
<script>
// Firebase authenticates users.
import firebase from "nativescript-plugin-firebase";
import Home from "./Home";
// App did not ccrash, but it didnnt seem right either
// const db = firebase.firestore;
//App crahses with line belows...iunno
//const bulkyCollection = firebase.firestore().collection("bulktrash");
const userService = {
async register(user) {
return await firebase.createUser({
email: user.email,
password: user.password
});
},
async login(user) {
return await firebase.login({
type: firebase.LoginType.PASSWORD,
passwordOptions: {
email: user.email,
password: user.password
}
});
},
async resetPassword(email) {
return await firebase.resetPassword({
email: email
});
}
};
// A stub for the main page of your app. In a real app you’d put this page in its own .vue file.
const HomePage = {
template: `
<Page>
<Label class="m-20" textWrap="true" text="You have successfully authenticated. This is where you build your core application functionality."></Label>
</Page>
`
};
var LoadingIndicator = require("nativescript-loading-indicator")
.LoadingIndicator;
var loader = new LoadingIndicator();
export default {
data() {
return {
isLoggingIn: true,
user: {
email: "yao@ming.com",
password: "basbhat01",
confirmPassword: "basbhat01"
}
};
},
methods: {
toggleForm() {
this.isLoggingIn = !this.isLoggingIn;
},
submit() {
if (!this.user.email || !this.user.password) {
this.alert("Please provide both an email address and password.");
return;
}
loader.show();
if (this.isLoggingIn) {
this.login();
} else {
this.register();
}
},
login() {
userService
.login(this.user)
.then(() => {
loader.hide();
this.$navigateTo(Home);          
})
.catch(err => {
console.error(err);
loader.hide();          
this.alert(err);
});
},
register() {
var validator = require("email-validator");
if (!validator.validate(this.user.email)) {
loader.hide();
this.alert("Please enter a valid email address.");
return;
}
if (this.user.password != this.user.confirmPassword) {
loader.hide();
this.alert("Your passwords do not match.");
return;
}
if (this.user.password.length < 6) {
loader.hide();
this.alert("Your password must at least 6 characters.");
return;
}
userService
.register(this.user)
.then(() => {
loader.hide();
this.alert("You may now login.");
this.isLoggingIn = true;
})
.catch(err => {
console.error(err);
loader.hide();
this.alert(err);
});
},
forgotPassword() {
prompt({
title: "Forgot Password",
message:
"Enter the email address you used to register for APP NAME to reset your password.",
inputType: "email",
defaultText: "",
okButtonText: "Ok",
cancelButtonText: "Cancel"
}).then(data => {
if (data.result) {
loader.show();
userService
.resetPassword(data.text.trim())
.then(() => {
loader.hide();
this.alert(
"Your password was successfully reset. Please check your email for instructions on choosing a new password."
);
})
.catch(() => {
loader.hide();
this.alert(err);
});
}
});
},
focusPassword() {
this.$refs.password.nativeView.focus();
},
focusConfirmPassword() {
if (!this.isLoggingIn) {
this.$refs.confirmPassword.nativeView.focus();
}
},
alert(message) {
return alert({
title: "Account Created!",
okButtonText: "OK",
message: message
});
}
}
};
</script>
<style scoped>
.page {
align-items: center;
flex-direction: column;
}
.form {
margin-left: 30;
margin-right: 30;
flex-grow: 2;
vertical-align: middle;
}
.logo {
margin-bottom: 12;
height: 90;
font-weight: bold;
}
.header {
horizontal-align: center;
font-size: 25;
font-weight: 600;
margin-bottom: 70;
text-align: center;
color: #D51A1A;
}
.input-field {
margin-bottom: 25;
}
.input {
font-size: 18;
placeholder-color: #A8A8A8;
}
.input-field .input {
font-size: 54;
}
.btn-primary {
height: 50;
margin: 30 5 15 5;
background-color: #D51A1A;
border-radius: 5;
font-size: 20;
font-weight: 600;
color: #FFFFFF;
}
.login-label {
horizontal-align: center;
color: #A8A8A8;
font-size: 16;
}
.sign-up-label {
margin-bottom: 20;
}
.bold {
color: #000000;
}
</style>

主页.vue


<template>
<Page class="page">
<ActionBar 
title=" " flat="true" v-bind:class="{ completed: activeTabIndex == 1 }">
</ActionBar>
<TabView :selectedIndex="activeTabIndex" @selectedIndexChange="onTabChange">
<TabViewItem title="Requests">
<GridLayout rows="auto, auto, *">
<Label row="0" text="Requests" class="header" />
<TextField row="1" ref="taskInput" v-model="textFieldValue"
hint="Enter text..." returnKeyType="done" @returnPress="onReturnPress" />
<ListView row="2" class="list-group" for="todo in todos">
<v-template>
<GridLayout columns="auto, *">
<Label col="0" v-on:tap="onTodoCircleTap(todo)"
text=" " />
<Label col="1" v-on:tap="onTodoItemTap(todo)"
:text="todo.name" textWrap="true" />
</GridLayout>
</v-template>
</ListView>
</GridLayout>
</TabViewItem>
<TabViewItem title="History">
<GridLayout rows="auto, *">
<Label row="0" text="History" class="header" />
<ListView row="1" class="list-group" for="done in dones"
@itemTap="onItemTap">
<v-template>
<GridLayout columns="auto, *">
<Label col="0" text="✓" />
<Label col="1" :text="done.name" textWrap="true" />
</GridLayout>
</v-template>
</ListView>
</GridLayout>
</TabViewItem>
<TabViewItem title="Profile">
<GridLayout rows="auto, auto, *">
<Label row="0" text="Profile" class="header" />
<TextField row="1" ref="taskInput" v-model="textFieldValue"
hint="+ New request" returnKeyType="done" @returnPress="onReturnPress" />
<ListView row="2" class="list-group" for="todo in todos">
<v-template>
<GridLayout columns="auto, *, auto, *"
rows="auto, auto" class="list-entry">
<!-- Circle Icon 
<Label col="0" row="0" v-on:tap="onTodoCircleTap(todo)" class="circle" text=" " />             -->
<!-- Formated Requested Date -->
<Label col="0" row="0"
v-on:tap="onTodoItemTap(todo)"
textWrap="true">
<FormattedString ios.fontFamily="system">
<Span class="fas t-18"></Span>
<Span text=" Requested: "
color="gray">
</Span>
<Span :text=" todo.requested"> </Span>
</FormattedString>
</Label>
<!-- Formated Pickup Date -->
<Label col="0" row="1"
v-on:tap="onTodoItemTap(todo)"
textWrap="true">
<FormattedString ios.fontFamily="system">
<Span class="fas t-18"></Span>
<Span text=" Pickup: " color="gray">
</Span>
<Span :text=" todo.pickup"> </Span>
</FormattedString>
</Label>
<!-- Formated Bulk Type -->
<Label col="2" row="0"
v-on:tap="onTodoItemTap(todo)"
textWrap="true">
<FormattedString ios.fontFamily="system">
<Span class="fas t-18"></Span>
<Span text=" Type: " color="gray">
</Span>
<Span :text=" todo.type"> </Span>
</FormattedString>
</Label>
<!-- Formated Bulk Status -->
<Label col="2" row="1"
v-on:tap="onTodoItemTap(todo)"
textWrap="true">
<FormattedString ios.fontFamily="system">
<Span class="fas t-18"></Span>
<Span text=" Status: " color="gray">
</Span>
<Span :text=" todo.status"> </Span>
</FormattedString>
</Label>
<!-- Extra Label -->

</GridLayout>
</v-template>
</ListView>
</GridLayout>
</TabViewItem>
<TabViewItem title="Add Requests">
<!-- CREATE a Grid Layout with 5 (0, 1, 2, 3, 4) rows -->
<GridLayout rows="auto, auto, auto, auto, auto">
<!-- ROW 0: Add Label "Add Request" -->
<Label row="0" text="New Request" class="header" />
<!-- ROW 1: Add Text Field "Request Type" -->
<TextField row="1" ref="taskInput" v-model="bulk.bulk_type"
hint="Request Type" returnKeyType="done" @returnPress="onReturnPress" />
<!-- ROW 2: Add Text Field "Request Name" -->
<TextField row="2" ref="taskInput" v-model="bulk.bulk_requestor"
hint="Pickup Date" returnKeyType="done" @returnPress="onReturnPress" />
<!-- ROW 3: Add Text Field "Description" -->
<TextField row="3" ref="taskInput" v-model="bulk.bulk_description"
hint="Description" returnKeyType="done" @returnPress="onReturnPress" />
<!-- ROW 4: Add Button "save" -->
<Button row="4" text="save" @tap="saveData" backgroundColor="green" class="btn btn-primary m-t-20" />
</GridLayout>
</TabViewItem>

</TabView>
</Page>
</template>
<script>
import firebase from "nativescript-plugin-firebase";
import LoginPage from "./LoginPage";

export default {
methods: {
saveData() {
db.collection("bulktrash").add(this.bulk)
.then((docRef) => {
console.log("Document written with ID: ", docRef.id);
})
.catch(function(error) {
console.error("Error adding document: ", error);
});
},
onTodoItemTap(item) {
const index = this.todos.indexOf(item);
action("What do you want to do with this task?", "Cancel", ["Mark completed", "Delete forever"]).then(result => {
console.log(result);
switch (result) {
case "Mark completed":
this.dones.unshift(item);
this.todos.splice(index, 1);
this.activeTabIndex = 1;
break;
case "Delete forever":
this.todos.splice(index, 1);
break;
case "Cancel" || undefined:
break;
}
});
},
onTodoCircleTap(item) { 
const index = this.todos.indexOf(item); 
this.dones.unshift(item);
this.todos.splice(index, 1);
this.activeTabIndex = 1;
},
onReturnPress() {
if (this.textFieldValue.trim() === "") {
this.$refs.taskInput.nativeView.focus();
return;
}
console.log("New task added: " + this.textFieldValue + ".");
this.todos.unshift({
name: this.textFieldValue
});
this.textFieldValue = "";
},
onTabChange(tab) {
this.activeTabIndex = tab.value;
}
},
/*         created() {
db.collection("bulktrash").get().then(function(querySnapshot) {
querySnapshot.forEach(function(doc) {
// doc.data() is never undefined for query doc snapshots
console.log(doc.id, " => ", doc.data());
});
});
}, */
data() {
return {
bulks: [],
bulk: {
bulk_id:null,
bulk_type:null,
bulk_location:null,
bulk_zone: null,
bulk_description: null,
bulk_dnotes: null,
bulk_requestor: null,
bulk_phone: null,
bulk_email: null,
//bulk_requested: null,
},
todos: [{
name: "John Smith",
type: "Aluminum",
requested: "10/04/19",
pickup: "10/23/19",
status: "Pending"
},
{
name: "Christine Tarbone",
type: "Cardboard",
requested: "10/07/19",
pickup: "10/23/19",
status: "Pending"
},
{
name: "Jamie Trotter",
type: "Aluminum",
requested: "10/02/19",
pickup: "10/12/19",
status: "Pending"
},
{
name: "Chris Evans",
type: "Electronics",
requested: "10/04/19",
pickup: "10/23/19",
status: "Pending"
}
],
dones: [],
bulkRequestType: "",
textFieldValue2: "",
textFieldValue3: "",
activeTabIndex: 0
};
}
};
</script>
<style scoped>
ActionBar {
background-color: #35495e;
}
.header {
background-color: #35495E;
color: white;
font-size: 34;
font-weight: 600;
padding: 0 15 15 15;
margin: 0;
}
.completed {
background-color: #42B883;
}
.reminder {
background-color: #42B883;
}
.logo {
margin-bottom: 12;
height: 90;
font-weight: bold;
background-color: #35495e;
}
TextField {
width: 100%;
font-size: 17;
color: black;
placeholder-color: #C1C1C1;
padding: 17;
border-width: 0 0 1 0;
border-color: #E0E0E0;
}
.list-entry {
padding: 0 15;
color: #42B883;
}
.circle {
width: 30;
height: 30;
padding: 0;
color: #42B883;
font-size: 25;
border-color: #42B883;
border-width: 2;
border-radius: 50;
}
.list-entry .circle {
margin: 0 10 0 0;
}
.list-entry Label {
font-weight: bold;
font-size: 17;
vertical-align: middle;
padding: 17 0;
margin: 0;
}
.list-entry-completed .circle {
color: white;
background-color: #42B883;
text-align: center;
padding: 0;
}
</style>

请告诉我,如果我还应该包括其他可能有帮助的内容。非常感谢大家。

在Home.vue中添加/替换:

import firebase from "nativescript-plugin-firebase";
import LoginPage from "./LoginPage";
import firestore from "nativescript-plugin-firebase/app/firestore";
const db = firebase.firestore;

相关内容

最新更新