About vue knowledge organization

The life cycle of VUE

  1. What is the vue life cycle?

  • The Vue life cycle refers to the process from the creation of the Vue instance object to its destruction. The realization of all functions of Vue is carried out around its life cycle. Calling the corresponding hook function at different stages of the life cycle can realize component data management and DOM rendering Two important functions.

1. beforeCreate (before creation) is a function triggered before the Vue object is created

2. created (after creation) a function triggered when the Vue object is created

3. beforeMount (before loading) is a function triggered when the Vue object starts to mount data

4. mounted (after loading) is a function triggered when the Vue object mounts data is completed

5. beforeUpdate (before update) is a function triggered before the data in the Vue object changes

6. updated (updated) The data data in the Vue object changes to complete the trigger function

7. beforeDestroy (before destruction) is a function triggered before the Vue object is destroyed

8. destroyed (after destruction) the function triggered by the completion of Vue object destruction

  1. The eight phases of the vue life cycle

  • 1.beforeCreate: It will be called immediately after the instance initialization is completed, after props is parsed, and before options such as data() and computed are processed. The DOM node cannot be obtained at this time.
  • 2.created: At this stage, the vue instance has been created, and the following content has been set: responsive data, computed properties, methods, and listeners. However, at this point the mount phase has not yet started, so the $el property is still not available. Still can't get the DOM element.
  • 3.beforeMount: A function that is automatically executed before the component content is rendered to the page. The component has completed its responsive state setting, but has not yet created a DOM node.
  • 4.mounted: A function that is automatically executed after the component is rendered. Generally, our asynchronous requests are written here. At this stage, both the data and the DOM have been rendered.
  • 5.beforeUpdate: A function that is automatically executed when the data changes. At this time, the changed data has not been rendered on the page.
  • 6.updated: A function that is automatically executed after the data changes, and the changed data has been rendered on the page at this time.
  • 7.beforeUnmount: A function that is automatically executed when the Vue application is destroyed.
  • 8.unmounted: A function that is automatically executed when the Vue application is destroyed and the dom is completely destroyed.
  1. The difference between computed and watch of vue

Both computed and watch are attributes used to monitor data changes in the vue framework

computed computed property

  1. If the property that the function depends on has not changed, read it from the cache

  1. There must be a return return

  1. The usage method is the same as the data in data, but similar to an execution method

watch listener

The function name of watch must be consistent with the data name in data

The function in watch has two parameters, old and new

The functions in watch do not need to be called

It will only monitor whether the value of the data has changed, but will not monitor whether the address of the data has changed. To monitor deeply, you need to cooperate with the deep:true attribute

immediate: true Do a monitoring when the page is first loaded

the difference

Function: computed is a computed attribute, watch is to monitor a value change and execute the corresponding callback

Whether to call the cache: the cache will be called when the properties on which the computed function depends remain unchanged; the callback will be called every time the monitored value of the watch changes

Whether to call return: computed must have; watch can not

Usage scenario: computed when an attribute is affected by multiple attributes; such as shopping cart product settlement; watch when one piece of data affects multiple pieces of data, such as a search box

Whether to support asynchrony: computed functions cannot have asynchrony; watch can

  1. Vue login process

Detailed implementation process of Vue login function

1. When logging in for the first time, the front-end adjusts the login interface of the back-end, and sends the user name and password

2. The backend receives the request, verifies the user name and password, and returns a token to the frontend if the verification is successful.

3. The front end gets the token, stores the token in localStorage and vuex, and jumps to the routing page

4. Every time the front end jumps to the route, it judges whether there is a token in localStorage. If there is no token, it will jump to the login page, and if it is, it will jump to the corresponding routing page

5. Every time you adjust the backend interface, you must add token in the request header

6、后端判断请求头中有无token,有token,就拿到token并验证token,验证成功就返回数据,验证失败(例如:token过期)就返回401,请求头中没有token也返回401

7、如果前端拿到状态码为401,就清除token信息并跳转到登录页面

补充:

  • 创建store是必须的!

  • token一定要存在storage缓存中,否则刷新一下,store会重新被加载,token就没了;

  • 那存在store是不是多余了,这个也是为了数据统一管理吧,也是数据可视化,因为缓存中的数据代码中是看不见的。(为了代码更容易让别人理解所以加上vuex,不加也不影响做登录)

npm install axios; // 安装axios
npm install vuex  // 安装vuex

创建store

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex);
// 用Vuex.Store对象用来记录token
const store = new Vuex.Store({
  state: {
    // 存储token
    token:"",
    userName:"" // 可选
  },
  getters: {
    getToken(state){
        return state.token || localStorage.getItem("token") || "";
    }
  },
  mutations: {
    // 修改token,并将token存入localStorage
    setToken(state,token) {
      state.token = token;
      localStorage.setItem('token', token);
      console.log('store、localstorage保存token成功!');
    },
    delToken(state) {
      state.token = "";
      localStorage.removeItem("token");
    },
    // 可选
    setUserInfo(state, userName) {
      state.userName = userName;
    }
  },
 actions: {
   // removeToken: (context) => {
     // context.commit('setToken')
   // }
 },
});
export default store;

引用到main.js

import store from './store'
new Vue({
  router,
  store,
  render: h => h(App),
}).$mount('#app')

封装axios

request.js文件用来封装我们的axios

qs vue 插件

里面有用到qs,这里我门讲解下他的作用:

get方法:我们通过定义一个get函数,get函数有两个参数,第一个参数表示我们要请求的url地址,第二个参数是我们要携带的请求参数。get函数返回一个promise对象,当axios其请求成功时resolve服务器返回 值,请求失败时reject错误值。最后通过export抛出get函数。

post方法:原理同get基本一样,但是要注意的是,post方法必须要使用对提交从参数对象进行序列化的操作,所以这里我们通过node的qs模块来序列化我们的参数。这个很重要,如果没有序列化操作,后台是拿不到你提交的数据的。这就是文章开头我们import QS from ‘qs’;的原因。

简单来说,qs 是一个增加了一些安全性的查询字符串解析和序列化字符串的库。

在项目中使用命令行工具输入:npm install qs

安装完成后在需要用到的组件中:import qs from 'qs’

具体使用中我查看了:qs.parse()和qs.stringify()

这两种方法虽然都是序列化,但是还是有区别的。

qs.parse()是将URL解析成对象的形式

qs.stringify()是将对象 序列化成URL的形式,以&进行拼接

// 封装axios
import axios from 'axios'
// 序列化
import QS from 'qs';
// vuex
import store from '../store/index'
//这一步的目的是判断出当前是开发环境还是生成环境,方法不止一种,达到目的就行
// if(process.env.NODE_ENV=="development"){
//   baseURL=''
// }else{
//   baseURL=''
// }
// 使用自定义的配置文件发送请求
const instance = axios.create({
    baseURL: '',
    timeout: 80000,
    headers: {
        // 'Content-Type': 'application/json;charset=UTF-8',
        // 'custome-header':'tianliangjiaoyu'
    }
});
// post请求的时候,我们需要加上一个请求头,所以可以在这里进行一个默认的设置,即设置post的请求头为
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8';
// 添加请求拦截器
instance.interceptors.request.use(function (config) {
    // 每次发送请求之前判断vuex中是否存在token        
    // 如果存在,则统一在http请求的header都加上token,这样后台根据token判断你的登录情况
    // 即使本地存在token,也有可能token是过期的,所以在响应拦截器中要对返回状态进行判断 
    const token = store.getters.getToken;
    if (token) {
        // 已经登录成功,统一添加token
        config.headers.Authorization = `Bearer ${token}`
    }
    // token && (config.headers.Authorization = token);
    return config;
}, function (error) {
    // 对请求错误做些什么
    return Promise.reject(error);
});
// 这里说一下token,一般是在登录完成之后,将用户的token通过localStorage或者cookie存在本地,
// 然后用户每次在进入页面的时候(即在main.js中),会首先从本地存储中读取token,如果token存在说明用户已经登陆过,
// 则更新vuex中的token状态。然后,在每次请求接口的时候,都会在请求的header中携带token,
// 后台人员就可以根据你携带的token来判断你的登录是否过期,如果没有携带,则说明没有登录过。
// 添加响应拦截器
instance.interceptors.response.use(function (response) {
    if (response.status === 200) {
        return Promise.resolve(response);
    } else {
        return Promise.reject(response);
    }
}, function (error) {
    // 对响应错误做点什么
    if (error.response.status) {
        switch (error.response.status) {
            // 401: 未登录
            // 未登录则跳转登录页面,并携带当前页面的路径
            // 在登录成功后返回当前页面,这一步需要在登录页操作。                
            case 401:
                router.replace({
                    path: '/login',
                    query: {
                        redirect: router.currentRoute.fullPath
                    }
                });
                break;
            // 403 token过期
            // 登录过期对用户进行提示
            // 清除本地token和清空vuex中token对象
            // 跳转登录页面                
            case 403:
                this.$message({
                    message: '登录过期,请重新登录',
                    duration: 1000,
                    type: 'success'
                });
                // 清除token
                localStorage.removeItem('token');
                store.commit('loginSuccess', null);
                // 跳转登录页面,并将要浏览的页面fullPath传过去,登录成功后跳转需要访问的页面 
                setTimeout(() => {
                    router.replace({
                        path: '/login',
                        query: {
                            redirect: router.currentRoute.fullPath
                        }
                    });
                }, 1000);
                break;
            // 404请求不存在
            case 404:
                this.$message({
                    message: '网络请求不存在',
                    duration: 1500,
                    type: 'success'
                });
                break;
            // 其他错误,直接抛出错误提示
            default:
                this.$message({
                    message: error.response.data.message,
                    duration: 1500,
                    type: 'success'
                });
        }
        return Promise.reject(error.response);
    }
});
/** 
 * get方法,对应get请求 
 * @param {String} url [请求的url地址] 
 * @param {Object} params [请求时携带的参数] 
 */
export function get(url, params) {
    return new Promise((resolve, reject) => {
        instance.get(url, {
            params: params
        })
            .then(res => {
                resolve(res.data);
            })
            .catch(err => {
                reject(err.data)
            })
    });
}
/** 
 * post方法,对应post请求 
 * @param {String} url [请求的url地址] 
 * @param {Object} params [请求时携带的参数] 
 */
export function post(url, params, headers) {
    return new Promise((resolve, reject) => {
        instance.post(url, QS.stringify(params), headers)
            .then(res => {
                resolve(res.data);
            })
            .catch(err => {
                reject(err.data)
            })
    });
}

要注意的是,上面的this.$message方法,是引入的element库中的轻提示组件,你根据你的ui库,对应使用你的一个提示组件。

这里说一下token,一般是在登录完成之后,将用户的token通过localStorage或者cookie存在本地,然后用户每次在进入页面的时候(即在main.js中),会首先从本地存储中读取token,如果token存在说明用户已经登陆过,则更新vuex中的token状态。然后,在每次请求接口的时候,都会在请求的header中携带token,后台人员就可以根据你携带的token来判断你的登录是否过期,如果没有携带,则说明没有登录过。

axios.get()方法和axios.post()在提交数据时参数的书写方式还是有区别的。区别就是,get的第二个参数是一个{},然后这个对象的params属性值是一个参数对象的。而post的第二个参数就是一个参数对象。两者略微的区别要留意哦

api.js的作用

这里我们补充一个知识点:

api文件的作用就是接口统一管理

这里我们定义了一个postLogin方法,这个方法有一个参数p,p是我们请求接口时携带的参数对象。而后调用了我们封装的post方法,post方法的第一个参数是我们的接口地址,第二个参数是postLogin的p参数,即请求接口时携带的参数对象。最后通过export统一导出apiFun对象

import {get,post} from './request'
let apiFun = null;
apiFun.postLogin = p => post('api/v1/users/my_address/address_edit_before', p)
export default apiFun;

然后在我们的mian.js文件中定义成全局变量,方便调用

import apiFun from "./network/api";
Vue.prototype.$apiFun = apiFun;//请求接口api

然后在我们的页面中可以这样调用我们的api接口:

// 调用api接口,并且提供了两个参数                
           this.$apiFun.postLogin({                    
                type: 0,                    
                sort: 1                
            }).then(res => {
                // 获取数据成功后的其他操作
                ………………                
            })

api接口管理的一个好处就是,我们把api统一集中起来,如果后期需要修改接口,我们就直接在api.js中找到对应的修改就好了,而不用去每一个页面查找我们的接口然后再修改会很麻烦.

路由拦截

import Vue from "vue"
import Router from "vue-router"
import Home from '../views/Home.vue'
import store from '../store/index'
Vue.use(Router)
let routes = [
    {
        path: '/',
        name: 'Home',
        component: Home,
        // 重定向
        redirect: '/publiccloud',
        children: [
            {
                path: '/publiccloud',
                name: '公有云用户管理',
                component: () => import('../views/publicCloud/PublicCloud.vue')
            },
            {
                path: '/admin',
                name: '管理员管理',
                component: () => import('../views/admin/Admin.vue')
            }
        ]
    },
    // 登陆页面
    {
        path: "/Login",
        name: "登录页面",
        component: () => import('../views/login/Login.vue')
    },
];
let router = new Router({
    routes,
    mode: 'history',
    // 全局配置激活路由的class类名,处与活跃(动态)就会用上这个类名
    linkActiveClass: 'active'
})
// 设置路由守卫,在进页面之前,判断有token,才进入页面,否则返回登录页面
if (storage.get("token")) {
    store.commit("setToken", localStorage.getItem("token"));
  }
router.beforeEach((to, from, next) => {
    // 设置路由守卫,在进页面之前,判断有token,才进入页面
        if (token) {
            next('/')
        } else {
            // 没有token就调用后端接口,跳转地址
            getAddress().then((res) => {
              if (res.data.code === 200) {
                location.href = res.data.data.redirectUri
              }
            })
        }
});
export default router

登录页面实际使用

submitForm(formName) {
      this.$refs[formName].validate(valid => {
        if (valid) {
          let that = this;
          // console.log('username',this.loginForm.username)
          // 通过校验规则后进入校验用户名密码是否正确
          // 没有后台接口可以自定义一个函数来模拟,替换postLogin
          this.$apiFun.postLogin(this.loginForm.username, this.loginForm.password)
            .then(res => {
              console.log(res);
               that.$store.commit("setToken", res.data.token);
               that.$store.commit("setUserInfo", res.data.account);
              this.$notify({
                title: "登录成功",
                type: "success",
                showClose: false,
                duration: 1000
              });
              setTimeout(() => {
                // 此时要判断/login后面的参数redirect,若无参数,进入主页;
                this.$router.push("/index");
                // 若有参数则参数为未有权限的那个路由,跳转到那个路由
                // this.$router.push(***); -- 具体要自己在这实现
              }, 1000);
            })
            .catch(error => {
            // 错误分为 status-请求错误 和 code-账号密码错误
              this.$message.error(error);
              console.log(error);
            });
        } else {
        // 不符合前端校验
          this.$message.error('format error:'+error);
          console.log('format error:',error);
          return false;
        }
      });
    }
  1. Vue+Vux实现登录功能

准备工作

  1. 安装 NodeJS

  1. 安装 vue-cli

1.vue-cli 2.x 升级到 3.x

(1)卸载 2.x 版本

npm uninstall -g vue-cli

(2)安装

npm install-g @vue/cli

(3)查看版本

vue -V
vue -V@vue/cli5.0.8

创建项目

1.vue-cli 2.x 项目

(1)创建

vue init webpack test2.0

创建完成后,项目目录结构如下:

(2)启动

cd test2.0
npm install
npm run dev

(3)安装 vux ①不使用模板安装

npm install vux --save
npm install vux-loader --save-dev
npm install less less-loader --save-dev

修改 build\webpack.base.conf.js :

const vuxLoader = require('vux-loader')
 
const originalConfig = {
...
 
const webpackConfig = originalConfig // 原来的 module.exports 代码赋值给变量 webpackConfig
 
module.exports = vuxLoader.merge(webpackConfig, {
  plugins: ['vux-ui']
})

src 下创建 views 目录,新建 test.vue 文件:

<template>
  <div style="padding: 15px;">
    <button-tab>
      <button-tab-item selected>{
    
    { today }}</button-tab-item>
      <button-tab-item>{
    
    { week }}</button-tab-item>
      <button-tab-item>{
    
    { month }}</button-tab-item>
    </button-tab>
  </div>
</template>

<script>
  import {ButtonTab, ButtonTabItem} from 'vux'
  export default {
    components: {
      ButtonTab,
      ButtonTabItem
    },
    data () {
      return {
        today: '今天',
        week: '本周',
        month: '本月'
      }
    }
  }
</script>

<style scoped>

</style>

配置路由 router\index.js :

import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'
import Test from '@/views/test'

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/',
      name: 'HelloWorld',
      component: HelloWorld
    },
    {
      path: '/test',
      name: 'test',
      component: Test
    }
  ]
})

常见错误:

  1. Module build failed: TypeError: this.getOptions is not a function

解决方法:

less 和 less-loader 版本过高,安装低版本:

npm install [email protected] [email protected] --save-dev
  1. You may use special comments to disable some warnings.

Use // eslint-disable-next-line to ignore the next line.

Use /* eslint-disable */ to ignore all warnings in a file.

解决方法:

原因是开启了 eslint 编码规范检查,修改 build\webpack.base.conf.js ,注释掉以下一行代码:

//...(config.dev.useEslint ? [createLintingRule()] : []),

②使用模板安装

vue init airyland/vux2 test-t2.0

官网模板的路由是以常量的形式写在 main.js 中,我们改造到 router/index.js 中去:

修改 main.js:

// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import FastClick from 'fastclick'
import router from './router'
// import VueRouter from 'vue-router'
import App from './App'
// import Home from './components/HelloFromVux'
//
// Vue.use(VueRouter)
//
// const routes = [{
//   path: '/',
//   component: Home
// }]
//
// const router = new VueRouter({
//   routes
// })

FastClick.attach(document.body)

Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({
  router,
  render: h => h(App)
}).$mount('#app-box')

修改 index.js:

import Vue from 'vue'
import Router from 'vue-router'
// import HelloWorld from '@/components/HelloWorld'
import Hello from '@/components/HelloFromVux'
import Test from '@/views/test'
 
Vue.use(Router)
 
export default new Router({
  routes: [
    {
      path: '/',
      name: 'Hello',
      component: Hello
    },
    {
      path: '/test',
      name: 'test',
      component: Test
    }
  ]
})

启动:

cd test-t2.0
npm install
npm run dev

(4)安装 axios

npm install axios --save-dev

(5)安装 vuex

npm install vuex --save-dev
  1. vue-cli 3.x 项目

(1)创建

vue create test

创建登录页

  1. main.js 中引入全局 ToastPlugin、LoadingPlugin 插件

import  { ToastPlugin, LoadingPlugin } from 'vux'
Vue.use(ToastPlugin)
Vue.use(LoadingPlugin)
  1. views 下创建 login\login.vue

import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'
import Test from '@/views/test'
Vue.use(Router)
export default new Router({
  routes: [
    {
      path: '/',
      name: 'HelloWorld',
      component: HelloWorld
    },
    {
      path: '/test',
      name: 'test',
      component: Test
    }
  ]
})
  1. localstorage和sessionstorage的区别

localStorage(本地存储)和sessionStorage(会话存储)。

1、生命周期:localStorage:localStorage的生命周期是永久的,关闭页面或浏览器之后localStorage中的数据也不会消失。localStorage除非主动删除数据,否则数据永远不会消失。

作用域: 相同浏览器的不同标签在同源情况下可以共享localStorage

sessionStorage的生命周期是在仅在当前会话下有效。sessionStorage引入了一个“浏览器窗口”的概念,sessionStorage是在同源的窗口中始终存在的数据。只要这个浏览器窗口没有关闭,即使刷新页面或者进入同源另一个页面,数据依然存在。但是sessionStorage在关闭了浏览器窗口后就会被销毁。同时独立的打开同一个窗口同一个页面,sessionStorage也是不一样的。

作用域:只在当前标签可用,当前标签的iframe中且同源可以共享

2、存储大小:localStorage和sessionStorage的存储数据大小一般都是:5MB

3、存储位置:localStorage和sessionStorage都保存在客户端,不与服务器进行交互通信。

4、存储内容类型:localStorage和sessionStorage只能存储字符串类型,对于复杂的对象可以使用ECMAScript提供的JSON对象的stringify和parse来处理

5、获取方式:localStorage:window.localStorage;;sessionStorage:window.sessionStorage;。

6、应用场景:localStoragese:常用于长期登录(+判断用户是否已登录),适合长期保存在本地的数据。sessionStorage:敏感账号一次性登录;

常用的四个 API 也很简单 :

JavaScript 代码:
// 增加了一个 localStorage ‘myCat’ 数据项
localStorage.setItem('myCat', 'Tom');
 
// 读取 localStorage ‘myCat’ 数据项
let cat = localStorage.getItem('myCat');
 
// 移除 localStorage ‘myCat’ 数据项
localStorage.removeItem('myCat');
 
// 移除所有的 localStorage 数据项
localStorage.clear();

Guess you like

Origin blog.csdn.net/snow_living/article/details/128904014