Vue2的学习与比较Vue3

目录

 一、Vue2项目的创建

 二、搭建vue-router

1.Vue 2版本的创建语法:

2.Vue 3版本的创建语法:

3.在APP.vue中配置写出组件的出口 

三、使用vuex作为状态存储仓库

1.安装vuex

2.创建store

(1)创建实例

(2)挂载

(3)配置函数及用法

3.组件中使用vuex

4.vuex与pinia的比较

四、使用element作为组件库

1、引入组件

2、使工程组件化

五、router-link和router-view

六、vue2引入图片


 一、项目的创建

Vue2

1.全局安装脚手架

npm install -g @vue/cli

2.搭建项目

vue create 项目名称

运行后,将得到图

通过手动选择Vue2和Vue3选项,分别创建Vue2或Vue3项目 

3.运行项目

npm run serve

Vue3 

pnpm create vite projectname    # 创建项目
pnpm install                    # 安装依赖
pnpm run dev                    # 运行项目 


 二、搭建vue-router

1.Vue 2版本的创建语法:

(1)安装router

 npm install vue-router@3.4.7

(2)在src下创建文件夹components(放置一般组件)和pages (放置路由组件)

在pages下创建HomePage.vue文件

<template>
    <div>欢迎来到Home页面</div>
</template>

<style>
</style>

<script>
</script>

(3)在src下创建目录router,并在其下方创建index.js文件

import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from "@/pages/HomePage.vue";
import Essay from "@/pages/EssayPage.vue"
import TimeInfo from '@/components/TimeInfo.vue'
import EssInfo from "@/components/EssayInfo.vue"

Vue.use(VueRouter);

const routes = [
    {
        path: '/',
        name: 'Home',
        component: Home
    },
    {
        path: '/essay',
        name: 'Essay',
        component: Essay,
        children: [
            {
                path: '/essInfo',
                name: 'EssInfo',
                component: EssInfo,
            },
            {
                path: '/timeInfo',
                name: 'TimeInfo',
                component: TimeInfo,
            }
        ]
    }
]

const router = new VueRouter({
    mode: 'history', // mode设置路由模式,不配置这个参数时默认为hash模式。
    routes,
    linkActiveClass: 'active',
});

let originPush = VueRouter.prototype.push;  //备份原push方法

VueRouter.prototype.push = function (location, resolve, reject) {
    if (resolve && reject) {    //如果传了回调函数,直接使用
        originPush.call(this, location, resolve, reject);
    } else {                     //如果没有传回调函数,手动添加
        originPush.call(this, location, () => { }, () => { });
    }
}

export default router

注意:在页面中用<router-view></router-view>时,在script中的用法为this.$router.push('essInfo'),路径处没有斜杠‘/’。

(4)在文件mian.js中引入我们所写的index.js文件

import Vue from 'vue'
import App from './App.vue'
import router from "./router/index.js"

Vue.config.productionTip = false

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

2.Vue 3版本的创建语法:

(1)

·安装vue-router:pnpm i vue-router -D

·安装element-plus:pnpm i element-plus -D

        完整引入的方法就看官网介绍

        自动引入pnpm i -D unplugin-vue-components unplugin-auto-import

·安装pinia:pnpm i axios -D

在src下创建目录router,并在其下方创建index.ts文件

import {createRouter,createWebHashHistory,createWebHistory,RouteRecordRaw} from 'vue-router';

const routes:RouteRecordRaw[] = [
    {
        path:'/',
        name:'Home',        //在src下有component文件夹
        component:()=>import('../components/Home.vue'), //或者() => import('@/views/HomeView.vue')
        alias:'/index',
        children: [
            {
              path: '/singer',
              name: 'singer',
              component: ()=>import('../components/one.vue')
            },
            {
              path: '/all',
              name: 'all',
              component: ()=>import('../components/two.vue')
            }
        ]
    }
];

const router = createRouter({
    history:createWebHashHistory(),
    routes:routes
});


//全局前置路由
//    from为从哪个页面来,to为去到哪个页面,next表示是否往下执行
//    next():不跳转、next(true):允许跳转、next('login'):跳转到路径name为login的页面
router.beforeEach((to, from, next) =>{
    //写判断语句等等 
})


export default router;

(2)在文件mian.js引入我们所写的index.js文件

import { createApp } from "vue"
import './style.css'
import App from './App.vue'
import router from './router/index'
import 'element-plus/dist/index.css'
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
//pinia:状态管理工具
import {createPinia} from 'pinia'
//Axios:对Axios请求的封装
import Axios from './request/request';
 

const app = createApp(App)
const pinia = createPinia()
app.use(pinia)
app.use(router)
app.use(Axios)
app.mount('#app')
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
    app.component(key, component)
  }

 (3)在配置文件vite.config.js进行配置

import { defineConfig } from 'vite'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'

export default defineConfig({
  // ...
  plugins: [
    // ...
    AutoImport({
      resolvers: [ElementPlusResolver()],
    }),
    Components({
      resolvers: [ElementPlusResolver()],
    }),
  ],
})

(4) 编写axios配置文件

在src下创建文件夹request,在文件夹request下创建文件request.ts

/**axios封装
 * 请求拦截、相应拦截、错误统一处理
 */
import axios from 'axios';
import router from '../router/index'
//  let protocol = window.location.protocol; //协议
//  axios.defaults.baseURL = protocol + "//" + host;
//  let host = window.location.host; //主机

axios.defaults.baseURL = 'http://localhost:2001/vue_stu';
axios.defaults.headers.post['Content-Type']='application/json'

axios.interceptors.request.use( //响应拦截
        async config => {
            // 每次发送请求之前判断vuex中是否存在token        
            // 如果存在,则统一在http请求的header都加上token,这样后台根据token判断你的登录情况
            // 即使本地存在token,也有可能token是过期的,所以在响应拦截器中要对返回状态进行判断 
            config.headers.token = sessionStorage.getItem('token')
            return config;
        },
        error => {
            return Promise.reject(error);
        })
    // 响应拦截器
axios.interceptors.response.use(
    response => {
        if (response.status === 200) {
            return Promise.resolve(response); //进行中        
        } else {
            return Promise.reject(response); //失败       
        }
    },
    // 服务器状态码不是200的情况    
    error => {
        if (error.response.status) {
            switch (error.response.status) {
                // 401: 未登录                
                // 未登录则跳转登录页面,并携带当前页面的路径                
                // 在登录成功后返回当前页面,这一步需要在登录页操作。                
                case 401:
                    break
                    // 403 token过期                
                    // 登录过期对用户进行提示                
                    // 清除本地token和清空vuex中token对象                
                    // 跳转登录页面                
                case 403:
                    sessionStorage.clear()
                    router.push('/login')
                    break
                    // 404请求不存在                
                case 404:
                    break;
                    // 其他错误,直接抛出错误提示                
                default:
            }
            return Promise.reject(error.response);
        }
    }
);
/** 
 * get方法,对应get请求 
 * @param {String} url [请求的url地址] 
 * @param {Object} params [请求时携带的参数] 
 */
const $get = (url:any, params:any) => {
        return new Promise((resolve, reject) => {
            axios.get(url, {
                    params: params,
                })
                .then(res => {
                    resolve(res.data);
                })
                .catch(err => {
                    reject(err.data)
                })
        });
    }
/** 
 * post方法,对应post请求 
 * @param {String} url [请求的url地址] 
 * @param {Object} params [请求时携带的参数] 
 */
const $post = (url:any, params:any) => {
        return new Promise((resolve, reject) => {
            axios.post(url, JSON.stringify(params)) //JSON.stringify()方法用于将 JavaScript 值转换为 JSON 字符串   
                .then(res => {
                    resolve(res.data);
                })
                .catch(err => {
                    reject(err.data)
                })
        });
    }
/**
 * put方法,对应put请求 
 * @param {String} url
 * @param {Object} params
 * @returns {Promise}
 */
const $put = (url:any, params:any, type = 'application/json')=> {
    return new Promise((resolve, reject) => {
      axios.put(url, params)
        .then(response => {
          resolve(response.data)
        }, err => {
          reject(err)
        })
    })
}
/**
 * del方法,对应delet请求
 * @param {String} url
 * @param {Object} params
 * @returns {Promise}
 */
const $del = (url:any, params:any, type = 'application/json')=> {
    return new Promise((resolve, reject) => {
      console.log(params)
      axios.delete(url, {
        params: params,
        headers: {
          'Content-Type': type
        }
      })
        .then(response => {
          resolve(response.data)
        })
        .catch(err => {
          reject(err)
        })
    })
}
//下面是vue3必须加的,vue2不需要,只需要暴露出去get,post方法就可以
export default {
    install: (app:any) => {
        app.config.globalProperties['$get'] = $get;
        app.config.globalProperties['$post'] = $post;
        app.config.globalProperties['$put'] = $put;
        app.config.globalProperties['$del'] = $del;
        app.config.globalProperties['$axios'] = axios;
    }
}

 在src下创建文件shime-vue.d.ts

declare module 'qs'

3.在APP.vue中配置写出组件的出口 

<template>
  <div id="app">
    <!-- Router-view:路由的出口 -->
      <router-view></router-view>
  </div>
</template>
 
<style>
</style>

<script>

export default {
  name: 'App',
}
 
</script>

三、使用vuex作为状态存储仓库

1.安装vuex

npm install vuex --save

这时如果直接安装vuex,不指定版本的话,就会直接安装最新的vuex的版本。所以会出现报错。

vuex分3.x版本和4.x版本,分别对应vue2.0与3.0,因此上面的是安装vue3.0版本的。

vue2.0需要带上版本号

npm install --save vuex@3

2.创建store

1、Vuex的状态存储是响应式的:若store中的状态发生变化,那么相应的组件也会被更新

2、不能直接改变store中的状态:改变store中的状态的唯一途径是提交(commit)mutation

(1)创建实例

在 src下创建store的文件夹,并在这个文件夹下创建index.js文件

import Vue from 'vue'
import Vuex from 'vuex'

//Vue.useAttrs(Vuex)
Vue.use(Vuex)

//创建仓库
const store = new Vuex.Store({
    state: {
        name: "Meier",
        age: 18,
        imgURL: "http://xxxxxx",
        friends: [
            { id: 1, name: "a", age: 20 },
            { id: 2, name: "b", age: 30 },
            { id: 3, name: "c", age: 40 }
        ]
    },
    getters: {},
    mutations: {},
    actions: {},
    modules: {}
})

export default store

踩坑注意: 创建store对象时“const store = new Vuex.Store”,如果遇到“报错:vuex__WEBPACK_IMPORTED_MODULE_1__.default.store is not a constructor”,则是因为“Vuex.Store”的S不能小写

(2)挂载

将仓库挂载到vm对象。在main.js文件中:

import Vue from 'vue'
import App from './App.vue'
import router from "./router/index.js"
import store from "./store/index.js"

Vue.config.productionTip = false

new Vue({
  router,
  render: h => h(App),
  store,
}).$mount('#app')
(3)配置函数及用法
  •  getters:类似于计算属性,作用是对外输出
getters:{
	// 输出属性给组件
	total(state){
		return  state.age;
	},
}
  • mutations:如果要修改state中数据,必须通过mutations进行修改(同步的),专门负责直接修改state中的数据,不能进行异步操作
mutations: {
    //默认第一个参数传state
    changeAge(state,age){
        //变更状态
        state.age = age
    }
},

在组件中使用: 

$store.commit('事件名称',参数) 

//this.$store.commit('changeAge',100)

  •  actions:异步处理修改state中的数据

组件调用当前actions中的 方法,actions方法调用mutations的方法,修改state数据。

actions: {
	// 默认第一个参数传一个跟store一样的对象
	increment(context,name){
        //假设fnAsync是一个异步业务函数
		fnAsync(()=>{
			context.commit('changeName',name);
		},2000)
	}
}

在组件中使用:

this.$store.dispatch('事件名称',参数)

//this.$store.dispatch('increment','aaa')

  •  modules:由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。为了解决以上问题,Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter
//分块设计:
const moduleA = {
  namespaced: true,//局部命名空间(让state的中变量与其他模块中的同名变量不冲突)	
  state: { msg:1 },
  mutations: { change(state,n){state.msg=n} },
  actions: { change(context,n){context.commit("change",n)} },
  getters: { x(state){return state.msg} }
}

const moduleB = {
   namespaced: true,//局部命名空间	
   state: {  msg:1 },
   mutations: { change(state,n){state.msg=n} },
   actions: { change(context,n){context.commit("change",n)} },
   getters: { x(state){return state.msg} }
}
const store = new Vuex.Store({
  modules: {
    a: moduleA,
    b: moduleB
  }
})

在组件中使用:

this.$store.state.a.msg // -> moduleA 的状态
this.$store.state.b.msg // -> moduleB 的状态
this.$store.commit("a/change",100)-> moduleA 的mutations
this.$store.commit("b/change",200)-> moduleB 的mutations
this.$store.getters["a/x"]-> moduleA 的getters
this.$store.getters["b/x"]-> moduleB 的getters
this.$store.dispatch("a/change",100)-> moduleA 的actions
this.$store.dispatch("b/change",200)-> moduleB 的actions

3.组件中使用vuex

(1)在模板中使用

可以直接拿,但这样比较繁琐,所以还是在computed里面封装一下再使用比较好

<template>
    <div v-show="$store.state.showSearch">
        <div>Home当前昵称:{{ $store.state.name }}</div>
        <div>Computed当前昵称:{{ storeName }}</div>
        <div>Setup当前昵称:{{ name }}</div>
    </div>
</template>

 (2)setup中使用

必须要加toRefs才是响应式,数据的改变还是要commit到store中去改变

<script setup>
    import {toRefs} from 'vue'
    import { useStore } from 'vuex'
    
    const store = useStore()
    const { name } = toRefs(store.state)

</script>

·数据的改变 

//因为已经在main.js全局引入了,所以在页面中不需要import vuex
//数据的同步改变 需要在mutations中定义一个mutation函数 
state: {
    showSearch: false,
},
mutations: {
    changeShowSearch(state, showSearch) {
        state.showSearch = showSearch;
    }
},
//在页面中,需要通过调用commit来执行mutation函数
this.$store.commit('changeShowSearch',false);

(3)options api中使用

<script>
    export default{
        computed:{
            storeName(){
                return this.$store.state.name      
            }
        }
    }
</script>

4.vuex与pinia的比较

  • pinia 没有mutation,只有state,getters,action【同步、异步】使用 action 来修改state数据。
  • pinia 语法上比 vuex 更容易理解和使用,有完整的 TypeScript 支持,比 vux 更容易添加
  • pinia 没有 modules 配置,每一个独立的仓库都是 definStore 生成出来的。
  • pinia state 是一个对象返回一个对象和组件的data是一样的语法。
  • pinia store 的 action 被调度为常规的函数调用,vuex 是使用 dispatch 方法或 MapAction 辅助函数
  • vuex 支持调试功能,如时间旅行和编辑。pinia 不支持。

四、使用element作为组件库

1、引入组件

npm i element-ui -S

(1)完整引入(在 main.js 中写入以下内容)

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)
});

(2)按需引入 (借助 babel-plugin-component,我们可以只引入需要的组件,以达到减小项目体积的目的)

npm install babel-plugin-component -D

  • 将 .babelrc 修改为 
{
  "presets": [["es2015", { "modules": false }]],
  "plugins": [
    [
      "component",
      {
        "libraryName": "element-ui",
        "styleLibraryName": "theme-chalk"
      }
    ]
  ]
}
  • 如果只希望引入部分组件,比如 Button 和 Select,那么需要在 main.js 中写入以下内容 :
import Vue from 'vue';
import { Button, Select } from 'element-ui';
import App from './App.vue';

Vue.component(Button.name, Button);
Vue.component(Select.name, Select);
/* 或写为
 * Vue.use(Button)
 * Vue.use(Select)
 */

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

2、使工程组件化

因此不会再app.vue里面直接开发,而是新开一个页面组件。注意:.vue文件采用的驼峰命名法,否则语法检查会报错。

直接到官网处,看中什么就复制什么过来直接用。

然后在需要用到的.vue文件当中引入该页面组件,在组件当中增加以下三个地方即可。


五、router-link和router-view

router-link设置路由跳转,router-view根据路由显示组件

1、router-link

<router-link to="/url">
    <li>
        <a>goto</a>
    </li>
</router-link>

2、router-view

首先在router/index.js上设置路由

import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from "@/pages/HomePage.vue";
import Essay from "@/pages/EssayPage.vue"

Vue.use(VueRouter)

const routes = [
    {
        path: '/',
        name: 'Home',
        component: Home
    }, {
        path: '/essay',
        name: 'Essay',
        component: Essay
    }
]

const router = new VueRouter({
    mode: 'history', // mode设置路由模式,不配置这个参数时默认为hash模式。
    routes,
    linkActiveClass: 'active',
})

export default router

 在router-view上显示(就是根据路由显示B组件还是C组件)

<router-view>

</router-view>

六、vue2引入图片

<template>
    <div class="demo-type" :style="backgroundDiv">
        <div>
            <el-avatar :src="headDiv" :size="100"/>
        </div>
    </div>
</template>
  
<script >
export default{
  data(){
    return {
        // 1、绑定在标签样式中
        backgroundDiv: {
            backgroundImage: 'url(' + require('@/assets/image/mainPic.png') + ')'
        },
        // 2、在element-ui中自带的路径属性
        headDiv:  require('@/assets/image/head.png')        
    };
  },
  methods:{}
}
</script>

持续更新中... 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值