Self-taught Vue to develop Dapp decentralized wallet (2)

Directory

foreword

1. Vue basic learning

2. Start using

1. Install Node.js

2. Install Taobao npm

 3. Install vue-cli

4. Create a Vue project

 6.idea to open the project

7. Install dependent environment

8. Install other

3. Use of some Vue components

1. Vue global loading

2.vue-router

3. element-ui component

4. vue-i18n component

Internationalized js file example

Example usage scenarios

5. vuex component

Modular

index.js

 state.js

mutations.js

 getter.js

 action.js

use of store

Effect

6.ethers.js

Summarize


foreword

The previous article determined the technology selection, and the portal uses Vue front-end development. This article mainly records the process of self-learning Vue and building the front-end framework through practical operation, as well as the front-end knowledge points and technical bottlenecks encountered (ps is not a problem for the big guys. ).


1. Vue basic learning

Learn Vue from scratch (the premise is jquery, js and other development experience), choose to learn through videos first, and follow the teacher to actually operate.

The video I watched came from Crazy God bilibili's video: [Crazy God Talks about Java] Vue's latest quick start tutorial is easy to understand_哔哩哔哩_bilibili

The teacher's explanation is quite interesting, in place, starting from scratch, learning the Vue framework, Vue's basic syntax v-bind, v-if, v-for and event click, etc., Vue's two-way binding, Vue component development, Vue asynchronous communication, etc.

2. Start using

1. Install Node.js

Download Node.js  Download | Node.js Chinese Network

After downloading, double-click to install next to the end.

After installation, test whether the installation is successful

cmd最好使用管理员模式

//显示安装的nodejs版本
node -v

//显示安装的npm版本
npm -v

2. Install Taobao npm

Install the domestic Taobao image, because npm-related resources on foreign nodes may fail.

cmd管理员模式

npm install cnpm

 3. Install vue-cli

//-g代表全局使用
npm install vue-cli -g

vue list

//npm未安装成功时使用
cnpm install vue-cli -g

4. Install webpack

npm install webpack -g
webpack -v
npm install webpack-cli -g
webpack-cli -v

//打包
webpack
//可实现监听文件发生变化自动打包
webpack--watch 

4. Create a Vue project

Packaging method webpack

cd d:
vue init webpack myvue
//确认项目名称后,后续选择否即可

Here you can directly choose to install the Vue-router route, or directly N, and install it manually after entering the project.

 

 Finally, choose to execute npm install yourself.

 6.idea to open the project

The directory structure should be like this

 

 The important files are package.json, which contains all installed dependencies and package versions;

The config mainly contains packaging-related parameters, access address settings, and browser cross-domain issues that may be used later are configured in the config/index.js file.

7. Install dependent environment

Use the idea terminal to operate

npm install
//运行
npm run dev

 Possible problems:

1. npm is not an internal or external command.

Solve the problem that the content in File-> Settings-> Tools-> Terminal-> Shell path is changed from cmd.exe to the full path of C:\Windows\System32\cmd.exe.

If it doesn’t work anymore, right click on the idea tool icon on the desktop -> Properties -> Compatibility -> Run this program as an administrator, and restart the idea.

2. The npm install fails, check whether the component version in package.json is too high or too low; try cnpm install

8. Install other

//安装vue-router,--save也可以写--S,指在本项目中安装
npm install vue-router --save

//安装axios
npm install axios

//安装element-ui
npm i element-ui -S

//安装vuex,vuex-persistedstate,后续会介绍使用此组件
cnpm install [email protected] vuex-persistedstate --save

//安装vue-i18n国际化
npm install [email protected]

9. Start after installation

npm run dev

3. Use of some Vue components

1. Vue global loading

 Load components globally in main.js

//main.js中全局加载

import Vue from 'vue'
import App from '@/App'
import router from '@/router'
import store from '@/store/index';
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import VueI18n from 'vue-i18n';
import { getMonthFirstDay,getFormatDate,getMonthLastDay,addNotBlankRule,parseTime, resetForm, addDateRange, selectDictLabel, selectDictLabels, handleTree } from "@/utils/yufu/commonUtils";

// 全局方法挂载
Vue.prototype.parseTime = parseTime
Vue.prototype.resetForm = resetForm
Vue.prototype.addDateRange = addDateRange
Vue.prototype.selectDictLabel = selectDictLabel
Vue.prototype.selectDictLabels = selectDictLabels
Vue.prototype.handleTree = handleTree
Vue.prototype.addNotBlankRule = addNotBlankRule
Vue.prototype.getMonthLastDay = getMonthLastDay
Vue.prototype.getFormatDate = getFormatDate
Vue.prototype.getMonthFirstDay = getMonthFirstDay

Vue.prototype.msgSuccess = function (msg) {
  this.$message({ showClose: true, message: msg, type: "success" });
}

Vue.prototype.msgError = function (msg) {
  this.$message({ showClose: true, message: msg, type: "error" });
}

Vue.prototype.msgInfo = function (msg) {
  this.$message.info(msg);
}
Vue.prototype.myConfirm = function(msg,f1,f2){
  this.$confirm(msg,"Warning", {
    confirmButtonText: "Yes",
    cancelButtonText: "No",
    type: "warning"
  }).then(f1).then(f2).catch(()=>{
    //this.msgInfo("已取消");
  });
}
Vue.prototype.myConfirm2 = function(msg,title){
  return this.$confirm(msg,title||"操作信息", {
    confirmButtonText: "确定",
    cancelButtonText: "取消",
    type: "warning"
  }).catch(()=>{
    this.msgInfo("已取消");
  });
}
//设置全局缓存常量
window.cacheData = {}

/*---------挂载全局使用-----------*/
Vue.use(ElementUI);
Vue.use(VueI18n);

const i18n = new VueI18n({
  locale: 'en', //切换语言
  messages: {
    zh: require('@/language/zh.js'),
    en: require('@/language/en.js'),
  },
});

new Vue({
  el: '#app',
  router,
  store,
  i18n,
  render: h => h(App),
  components: { App },
  template: '<App/>'
})

2.vue-router

Create index.js: the routing component of vue, create index.js under the router directory

//项目目录下创建router目录,router目录下创建index.js

//index.js
//导入依赖
import Vue from 'vue'
import Router from 'vue-router'
//页面组件
import TransferAccounts from '@/views/TransferAccounts'

//Vue加载使用
Vue.use(Router);


//解决因版本问题多次点击后前端console报错问题
const originalPush = Router.prototype.push
Router.prototype.push = function push (location) {
  return originalPush.call(this, location).catch(err => err)
}


export default new Router({
  mode: 'history', // 去掉url中的#
  routes: [
    {
        path:'/transferAccounts',//指定路由路径
        name:"transferAccounts",//起个别名,可忽略
        component: TransferAccounts//这个是路由的组件,就是需要跳转到的组件页面
    }
  ]
})

 For other places, main.js needs to be mounted globally before use, see 3.1Vue Global Loading

//js代码调用时
this.$router.push('/login')

//template中使用
//import先引入组件,然后template中使用router-link  to路由路径。
//必须加上<router-view></router-view>

<div id="app">
  <h1>Hello App!</h1>
  <p>
    <!-- use the router-link component for navigation. -->
    <!-- specify the link by passing the `to` prop. -->
    <!-- `<router-link>` will render an `<a>` tag with the correct `href` attribute -->
    <router-link to="/">Go to Home</router-link>
    <router-link to="/about">Go to About</router-link>
  </p>
  <!-- route outlet -->
  <!-- component matched by the route will render here -->
  <router-view></router-view>
</div>

3. element-ui component

Document path: Element - The world's most popular Vue UI framework

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

Vue.use(ElementUI);

new Vue({
  el: '#app',
  render: h => h(App)
});

4. vue-i18n component

import Vue from 'vue'
import VueI18n from 'vue-i18n'

Vue.use(VueI18n)

const i18n = new VueI18n({
  locale: 'en', //切换语言
  messages: {
    zh: require('@/language/zh.js'),
    en: require('@/language/en.js'),
  },
});

new Vue({
  el: '#app',
  router,
  store,
  i18n,
  render: h => h(App),
  components: { App },
  template: '<App/>'
})

Internationalized js file example

 zh.js

//zh.js

export const lang = {
  swap1: '转账',
  swap2: '充值',
  
};

en.js

//en.js

export const lang = {
  swap1: 'Transfer',
  swap2: 'Recharge',
  
};

Example usage scenarios

1.标签中
<h1>{
    
    { $t('lang.swap1') }}</h1>

2.script中
this.$message.error(this.$t('lang.swap5')+'');

3.标签上,使用`:`绑定使用
<el-input :placeholder="$t('lang.swap58')" show-word-limit v-model="ruleForm.to"></el-input>

<el-dialog :title="$t('lang.swap74')" :visible.sync="dialogVisible" width="30%">
   <AddBindAcctDialog :visible.sync="dialogVisible" @getList="getList"/>
</el-dialog>

5. vuex component

Vuex is a state management pattern + library specially developed for Vue.js applications . It uses centralized storage to manage the state of all components of the application and solve multi-component data communication . What is Vuex? | Vuex

Why do I want to use this wallet portal I made to design the switching of multiple account addresses in the Fox Wallet, monitor the switching in real time and refresh the display page data. Because the store can store the data state, when a change occurs, only the actual state of the data needs to be managed to achieve the uniqueness and real-time performance of the data in all components.

 The simplest store provided by the official

import { createApp } from 'vue'
import { createStore } from 'vuex'

// 创建一个新的 store 实例
const store = createStore({
  state () {
    return {
      count: 0
    }
  },
  mutations: {
    increment (state) {
      state.count++
    }
  }
})

const app = createApp({ /* 根组件 */ })

// 将 store 实例作为插件安装
app.use(store)

Modular

├── index.html
├── main.js
├── api
│   └── ... # 抽取出API请求
├── components
│   ├── App.vue
│   └── ...
└── store
    ├── index.js          # 我们组装模块并导出 store 的地方
    ├── actions.js        # 根级别的 action
    ├── mutations.js      # 根级别的 mutation
    └── modules
        ├── cart.js       # 购物车模块
        └── products.js   # 产品模块

Modular structure in my project

actual code

index.js

//index.js

import Vue from 'vue';
import Vuex from 'vuex';
import state from '@/store/state';
import * as actions from '@/store/actions';
import * as mutations from '@/store/mutations';
import * as getters from '@/store/getters';
import createPersistedState from 'vuex-persistedstate';

Vue.use(Vuex);

const store = new Vuex.Store({
  state,
  actions,
  mutations,
  getters,
  plugins: [
    createPersistedState({
      paths: ['isConnectWallet', 'account'],
    }),
  ],
});

export default store

 state.js

export default {
  //provider对象
  provider: {},
  //合约对象
  contracts: {},
  //签名对象
  signer: {},
  //小狐狸钱包的账户address
  account: '',
  net: 0,
  //gas费,后续可能要用
  gasPrice: 0,
  //钱包余额
  balance: '0.0',
  //作为是否链接登录到小狐狸钱包的标志
  isConnectWallet: false,
  //绑卡列表数据,用于下拉框
  accountList: [],
  //交易计数,用于发生交易时同步刷新交易记录列表
  tradeCounter: 0,
};

mutations.js


  export const saveProviderStore = (state, provider) => {
    state.provider = provider;
  };

  export const saveContractsStore = (state, contracts) => {
    state.contracts = contracts;
  };

  export const  saveAccountStore = (state, account) => {
    state.account = account;
  };

  export const  saveBalanceStore = (state, balance) => {
    state.balance = balance;
  };

  export const  saveNetStore = (state, net) => {
    state.net = net;
  };

  export const  saveGasPriceStore = (state, gasPrice) =>  {
    state.gasPrice = gasPrice;
  };
  export const  saveIsConnectWallet = (state, isConnectWallet) =>  {
    state.isConnectWallet = isConnectWallet;
  };
  export const  saveSigner = (state, signer) =>  {
    state.signer = signer;
  };
  export const  saveAccountList = (state, accountList) =>  {
    state.accountList = accountList;
  };
  export const  saveTradeCounter = (state, tradeCounter) =>  {
    state.tradeCounter = tradeCounter;
  };

 getter.js

// 获取最终的状态信息
export const provider = state => state.provider;
export const contracts = state => state.contracts;
export const signer = state => state.signer;
export const account = state => state.account;
export const net = state => state.net;
export const gasPrice = state => state.gasPrice;
export const balance = state => state.balance;
export const isConnectWallet = state => state.isConnectWallet;
export const accountList = state => state.accountList;
export const tradeCounter = state => state.tradeCounter;

 action.js


// 触发保存方法
export const SET_PROVIDER = ({ commit }, payload) => {
  commit('saveProviderStore', payload);
};
export const SET_CONTRACTS = ({ commit }, payload) => {
  commit('saveContractsStore', payload);
};
export const SET_ACCOUNT = ({ commit }, payload) => {
  commit('saveAccountStore', payload);
};
export const SET_BALANCE = ({ commit }, payload) => {
  commit('saveBalanceStore', payload);
};
export const SET_NET = ({ commit }, payload) => {
  commit('saveNetStore', payload);
};
export const SET_GAS_PRICE = ({ commit }, payload) => {
  commit('saveGasPriceStore', payload);
};

export const SET_IS_CONNECT_WALLET = ({ commit }, payload) => {
  commit('saveIsConnectWallet', payload);
};

export const SET_SIGNER = ({ commit }, payload) => {
  commit('saveSigner', payload);
};

export const SET_ACCOUNT_LIST = ({ commit }, payload) => {
  commit('saveAccountList', payload);
};
export const SET_TRADE_COUNTER = ({ commit }, payload) => {
  commit('saveTradeCounter', payload);
};


.........其他代码

export const setProvider = ({commit},address) => {
  let web3Provider;
  if (window.ethereum) {
    web3Provider = window.ethereum;

    .....获取web3钱包中的一些熟悉,地址,provider,合约对象等

    //commit('saveAccountStore', address);//另外一种方式
    SET_ACCOUNT({commit},address);
    SET_PROVIDER({commit},provider);
    SET_CONTRACTS({commit},daiContract);
    SET_IS_CONNECT_WALLET({commit},true);
    SET_SIGNER({commit},signer);

  }
};


use of store

1.action.js中要改变数据状态时

//commit('saveAccountStore', address);//另外一种方式
SET_ACCOUNT({commit},address);

2.组件中,使用语法糖获取值

import {mapState} from "vuex";

export default {
  computed: {
    ...mapState(['account']),
    getAccount() {
      if (this.account) {
        return '0x...' + this.account.substring(this.account.length - 4,                 this.account.length);
      } else {
        return '';
      }
    },
  },
}

3.组件中,不使用语法糖获取值

this.$store.getter.account;

4.组件中使用语法糖调用方法
methods: {
    handleLogin() {
      this.$store.dispatch('connectWallet');
    },
  }

5.组件中改变store数据状态
let balanceStr = '0.0';
this.$store.dispatch('SET_BALANCE', balanceStr);

Effect

6.ethers.js

1.install安装
2.js文件中引入即可使用

import * as ethers from 'ethers';

获取钱包余额

const balance = await daiContract.balanceOf(address);
let balanceStr = ethers.utils.formatUnits(balance, 18);


Summarize

Mainly learn to use the basic grammar of Vue, then follow the teacher to practice, and finally build the overall framework of the Vue front-end by yourself. Install dependent components and learn the usage of each component. The following article introduces the problems and solutions encountered in the use of the Vue framework. face to be continued

Guess you like

Origin blog.csdn.net/xieedeni/article/details/126303187