Aaron Ullal é um Desenvolvedor freelancer na FactoryMind, amante das pessoas e da vida, vivendo em beta permanente. Ele é um desenvolvedor full stack baseado na bela cidade de Trento, na Itália.
TI apaixonada por mais do que 7 anos, ele está atualmente focado no desenvolvimento móvel usando o NativeSe projetar soluções arquitetônicas para plataformas complexas.

O Couchbase é uma ótima ferramenta para manter os dados dentro do nosso aplicativo. Se você nunca ouviu falar dele, trata-se de um armazenamento de objetos de documentos que permite salvar seus dados.
Se você estiver usando NativeScript-Angular, já existem alguns tutoriais excelentes sobre como começar e alguns recursos mais avançados. Neste artigo, vamos nos concentrar no NativeScript com TypeScript.
O que abordaremos
Neste artigo simples, veremos como salvar e recuperar algumas informações do usuário:
- Instalação do Couchbase
- Criação de uma classe TypeScript que fornece uma camada de abstração sobre o Couchbase, tornando-o muito mais fácil de usar (sem instruções complexas para inserção e recuperação de dados)
- Implementação do padrão singleton na classe
Ao final do tutorial, seremos capazes de usar instruções como
|
1 2 3 |
userSettings.nome = "Frank" //boom! escrito em nosso banco de dados texto="{{ userSettings.nome }}" //boom! leitura de nosso banco de dados |
sem ter que escrever consultas extensas para ler e escrever!
Além disso, todo o código deste artigo está disponível em este repositório do GitHub. Sinta-se à vontade para fazer o clone e brincar com ele.
Sem mais delongas, vamos começar!
Instalar o plug-in do Couchbase
Vamos criar um novo aplicativo NativeScript usando o modelo TypeScript.
|
1 |
tns criar ns-couchbase-demonstração --tsc |
Na pasta raiz de nosso projeto NativeScript recém-criado, vamos dar o seguinte comando para adicionar o plug-in e salvá-lo em nossa lista de dependências:
|
1 |
tns plug-in adicionar nativescript-couchbase |
Depois que o plug-in for instalado com êxito, vamos criar uma classe que será usada para armazenar e recuperar as informações do usuário de que precisamos.
Classe de camada de abstração
OPCIONAL: Normalmente, é uma boa ideia criar uma interface para definir as propriedades que precisamos incluir.
Navegue até a pasta app do nosso projeto e crie uma pasta models. Aqui, definiremos nosso arquivo Models.ts (app/models/Models.ts):
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
exportação módulo Modelos{ exportação interface IUserSettings { nome de usuário :string; Nome completo :string; e-mail :string; } } |
Depois de definir nossa interface, vamos criar a classe que de fato a implementa. Chamaremos a classe de UserSettings.
Dentro dessa classe, também precisamos armazenar as informações relacionadas ao nosso banco de dados Couchbase.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
deixar CouchBaseModule = exigir("nativescript-couchbase"); importação { Modelos } de '../models/Models'; exportação classe Configurações do usuário implementa Modelos.IUserSettings{ privado NOME DO BANCO DE DADOS = 'appname-db'; privado DOCUMENTO DE CONFIGURAÇÕES DO USUÁRIO_ID = 'configurações de usuário'; privado _database; privado _userSettingsDocument: Modelos.IUserSettings; privado _userSettingsObj: Modelos.IUserSettings; privado _instância :Configurações do usuário; } |
Vamos detalhar isso:
Nas duas primeiras linhas, solicitamos o plug-in do Couchbase que instalamos anteriormente, juntamente com o módulo Models que usaremos para aproveitar a tipagem forte do TypeScript.
Em seguida, definimos algumas outras propriedades privadas que usaremos posteriormente:
DATABASE_NAME: Esse é o nome do banco de dados. Certifique-se de que ele não contenha letras maiúsculas (e que tenha menos de 240 caracteres).
USER_SETTINGS_DOC_ID: nome do documento do Couchbase.
banco de dados: Essa é a instância do conector de banco de dados.
_userSettingsDocument: O Couchbase é um banco de dados não orientado a documentos. Ele não tem tabelas, mas usa uma entidade de armazenamento primário conhecida como Document. Basicamente, um documento é uma coleção de pares chave-valor, em que o valor pode ser praticamente qualquer coisa (cadeia de caracteres, números, matrizes etc.). É isso que torna o Couchbase a solução número um se você precisar armazenar uma variedade de dados não relacionais: simplicidade e flexibilidade.
_userSettingsObj: este é o objeto JavaScript que usaremos para sincronizar as informações com o documento do Couchbase.
Abordaremos o motivo pelo qual declaramos a variável _instance mais tarde, quando implementarmos o padrão singleton.
Agora que já cobrimos isso, vamos ver como funciona o construtor da nossa classe:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
construtor() { este._database = novo CouchBaseModule.Couchbase(este.NOME DO BANCO DE DADOS); este._userSettingsDocument = este._database.getDocument(este.USER_SETTINGS_DOC_ID); se (!este._userSettingsDocument) { console.registro("O documento ainda não existe :)"); este._userSettingsObj = { nome de usuário: "", e-mail: "", Nome completo: "", } este._database.createDocument(este._userSettingsObj, este.USER_SETTINGS_DOC_ID); este._userSettingsDocument = este._database.getDocument(este.USER_SETTINGS_DOC_ID); } } |
Mais uma vez, vamos ver em detalhes o que está acontecendo em nosso construtor:.
this._database = new CouchBaseModule.Couchbase(this.DATABASE_NAME);
Aqui estamos instanciando o Couchbase e informando a qual banco de dados queremos nos conectar.
this._userSettingsDocument = this._database.getDocument(this.USER_SETTINGS_DOC_ID);
Essa linha diz ao Couchbase para obter nosso documento (a coleção que usamos para armazenar nossas informações).
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
se (!este._userSettingsDocument) { console.registro("O documento ainda não existe :)"); este._userSettingsObj = { nome de usuário: "", e-mail: "", Nome completo: "", } este._database.createDocument(este._userSettingsObj, este.USER_SETTINGS_DOC_ID); este._userSettingsDocument = este._database.getDocument(este.USER_SETTINGS_DOC_ID); } |
Se o nosso documento ainda não existir (por exemplo, pela primeira vez), criaremos um objeto vazio do tipo UserSettings e também criaremos um novo documento. O segundo parâmetro que atribuímos à função createDocument é o id do documento. Se não fornecermos esse parâmetro, o Couchbase atribuirá ao documento um UUID automaticamente.
Fantástico! Agora que nosso construtor está pronto, vamos ver como podemos definir e recuperar informações sobre nosso usuário.
Vamos configurar alguns getters e setters para conseguir exatamente isso.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
/*====== GETTER E SETTER DE NOME DE USUÁRIO ======*/ obter nome de usuário(): string { este._userSettingsObj = este._database.getDocument(este.DOCUMENTO DE CONFIGURAÇÕES DO USUÁRIO_ID ); deixar nome de usuário = este._userSettingsObj.nome de usuário; retorno nome de usuário; } definir nome de usuário(valor: string) { este._userSettingsObj = este._database.getDocument(este.DOCUMENTO DE CONFIGURAÇÕES DO USUÁRIO_ID ); este._userSettingsObj.nome de usuário = valor; este._database.updateDocument(este.DOCUMENTO DE CONFIGURAÇÕES DO USUÁRIO_ID , este._userSettingsObj); } |
Como de costume, vamos detalhar o código.
No getter, fazemos três coisas:
1) Lemos os dados de nosso documento em nosso objeto
2) Obtenha o valor desejado (nesse caso, o nome de usuário)
3) Devolva-o
Fácil de fazer :)
No setter, fazemos o seguinte:
1) Obtemos a versão mais recente de nosso userSettingsObject, lendo-a no banco de dados
2) Definimos a propriedade username como o valor passado para a função
3) Atualizamos nosso documento no banco de dados. Ao contrário da função createDocument, o primeiro parâmetro é o ID do documento e o segundo é o próprio objeto.
Mas... por que precisamos obter o getDocument primeiro? Por que não podemos simplesmente atualizar o documento com o objeto?
Fico feliz que você tenha perguntado!
Basicamente, sempre que atualizamos um documento, o Couchbase mantém o registro da alteração. Cada documento tem uma propriedade _rev; esse valor é atualizado pelo Couchbase sempre que ocorre uma operação de gravação no documento. Se tentarmos atualizar um documento com um _rev mais antigo, o Couchbase o rejeitará.
Padrão Singleton
Quem não gosta de padrões de design? Hoje vamos implementar um padrão muito simples, porém eficaz: o singleton. O padrão singleton, quando implementado corretamente, "restringe a instanciação de um classe para um objeto. Isso é útil quando é necessário exatamente um objeto para coordenar as ações em todo o sistema", que é exatamente o nosso caso.
Basicamente, garantimos que tenhamos apenas uma instância da nossa classe lendo e gravando no nosso banco de dados.
Como podemos fazer isso? Uma maneira simples de conseguir isso é com as duas etapas a seguir:
1) Tornar nosso construtor privado (Introduzido no ts 2.0)
2) Implementar um método getInstance que retorna a instância atual, se ela existir, ou uma nova instância, se for a primeira chamada
ETAPA 1:
|
1 |
privado construtor() {....} |
ETAPA 2:
Agora podemos ir em frente e criar nosso método getInstance(), que terá a seguinte aparência:
|
1 2 3 4 5 6 7 8 9 10 11 |
público estático getInstance() :Configurações do usuário{ se(!este._instância){ este._instância = novo Configurações do usuário(); } retorno este._instância; } |
Ótimo! Abstraímos os dados e implementamos o padrão singleton. Vamos ver como podemos usar nossa nova e brilhante classe UserSettings.
Editaremos os arquivos main-page.xml e main-page.ts existentes.
Primeiro, definiremos um layout básico da interface do usuário. Para esta demonstração, usaremos um campo de texto para obter a entrada do usuário, um botão para salvar o valor no banco de dados e um rótulo para exibir o valor atual no banco de dados. Como você pode ver, se nenhum dado estiver armazenado no banco de dados, o rótulo exibirá simplesmente "Nenhum dado armazenado no banco de dados".
Esta é a aparência do nosso arquivo main-page.xml:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<Página xmlns="http://schemas.nativescript.org/tns.xsd" navigatingTo="navigatingTo"> <Página.barra de ação> <Barra de ação título="Meu aplicativo" ícone="" classe="barra de ação"> </Barra de ação> </Página.barra de ação> <Layout de pilha> <TextField dica="nome de usuário" texto="{{ nome de usuário }}" /> <Botão texto="SALVAR MEU NOME DE USUÁRIO" toque="onTap" classe="btn btn-primary btn-active"/> <Rótulo texto="{{ dbusername || 'nenhum dado armazenado no banco de dados' }}" textWrap="true" (verdadeiro)/> </Layout de pilha> </Página> |
Muito bem! Agora que temos um layout básico, podemos continuar adicionando alguma lógica à interface do usuário.
Esta é a aparência do nosso arquivo main-page.ts:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
importação { Observável } de 'data/observable' (dados/observáveis); //vinculação de dados à nossa exibição importação { Configurações do usuário } de './UserSettings'; //woohoo nossa incrível camada de interação com o banco de dados importação { Dados do evento } de 'data/observable' (dados/observáveis); //use com typescript para intellisense importação { Página } de 'ui/page'; //use com typescript para intellisense deixar userSettings = Configurações do usuário.getInstance(); deixar mainPageViewModel; classe Modelo do MainPageView se estende Observável{ público nome de usuário; público nome de usuário construtor(){ super(); este.nome de usuário = userSettings.nome de usuário; } } exportação função navigatingTo(argumentos: Dados do evento) { deixar página = <Página>argumentos.objeto; mainPageViewModel = novo Modelo do MainPageView(); página.bindingContext = mainPageViewModel; } exportação função onTap(){ userSettings.nome de usuário = mainPageViewModel.nome de usuário; mainPageViewModel.definir("dbusername",userSettings.nome de usuário); } |
O que fizemos? Nas primeiras linhas, apenas importamos um monte de coisas, verificando os comentários para ver o que os módulos fazem. Em seguida, temos:
|
1 |
deixar userSettings = Configurações do usuário.getInstance(); |
É assim que obtemos a instância da nossa classe UserSettings.
Continuando, declaramos outra classe pequena:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
classe Modelo do MainPageView se estende Observável{ público nome de usuário; público nome de usuário construtor(){ super(); este.nome de usuário = userSettings.nome de usuário; } } |
Como você pode ver, o MainPageViewModel estende a classe Observable. Se você não estiver familiarizado com Observables, saiba que eles são basicamente objetos JavaScript que acionam uma notificação se uma das propriedades for alterada. Você pode saber mais aqui.
Nosso modelo de visualização tem duas propriedades: nome de usuário (que vinculamos ao nosso campo de texto) e nome de usuário (que vinculamos ao nosso rótulo). Sempre que criamos uma nova instância de nossa classe, atribuímos ao dbusername qualquer valor presente em nossa instância userSettings, que, por sua vez, vai e lê os dados em nosso banco de dados (lembra-se do método get username() getter?).
|
1 2 3 4 5 6 7 8 9 |
exportação função navigatingTo(argumentos: Dados do evento) { deixar página = <Página>argumentos.objeto; mainPageViewModel = novo Modelo do MainPageView(); página.bindingContext = mainPageViewModel; } |
Essa função é chamada sempre que navegamos em nossa página. Instanciamos nossa classe MainPageViewModel e a atribuímos à variável mainPageViewModel e a vinculamos à nossa página. De forma simples e direta.
Por último, mas não menos importante, definimos o comportamento para o clique do botão:
|
1 2 3 4 5 6 7 |
exportação função onTap(){ userSettings.nome de usuário = mainPageViewModel.nome de usuário; mainPageViewModel.definir("dbusername",userSettings.nome de usuário); } |
Mais uma vez, é muito simples: Gravamos no banco de dados o valor que o campo de texto contém (mainPageViewModel.username está vinculado ao campo de texto) e, em seguida, atualizamos o valor de dbusername para atualizar o rótulo. Uma imagem vale mais que mil palavras, portanto, aqui vai um GIF!

Esta postagem faz parte do Programa de Redação da Comunidade Couchbase
Obrigado, Laura, pelo blog detalhado.
Podemos ter um blog semelhante para o Nativescript-vue couchbase sobre como persistir os dados?