Vue3学习笔记(Vue+Vue Router+Vuex)【持续更新中】

vue3

创建

使用Vue CLI创建
// 安装
$ npm install -g @vue/gli
$ vue --version
// 创建
$ vue create [名字]

Vue Router

使用fetch获取数据

在单独组件的vue中使用
// fetch返回Promise对象
// 默认执行get请求
fetch('http://localhost:3000/banner').then((res)=>{
    // json()将响应的body,解析json的promise
    // console.log(ews.json());
    return res.json()
}).then((res)=>{
    console.log(res);
    // 这里通过变量可以获取res的值,从而之后渲染到界面上
    this.bannersList=res.banners
})
在状态集中管理中使用

store/index.js

import {reactive} from 'vue'
const store={
	store: reactive({// 定义状态
		msg: "hello world",
		bannersList: []
	}),
	updateMsg: function() {
		this.state.msg='你好'
	},
	updateBannersList(value) {
		this.state.bannersList=value
	},
}
export default store

Home.vue中

// fetch返回Promise对象
fetch('http://localhost:3000/banner').then((res)=>{
    // json()将响应的body,解析json的promise
    // console.log(ews.json());
    return res.json()
}).then((res)=>{
    console.log(res);
    // 这里改变了
    this.store.updateBannersList(res.bannersList)
})

使用axios获取数据

文档地址1:http://www.axios-js.com/zh-cn/docs/
文档地址2(官方):https://www.axios-http.cn/docs/intro

概念

axios是基于Promise的http库
axios与ajax关系:暂时理解为axios是ajax的子集

安装
$ npm install axios
使用

引入axios

// 引入
import axios from 'axios'
axios.get('http://localhost:3000/banner').then((res)=>{
	console.log(res);
})

支持并发请求及携带参数,具体见文档

vite通过proxy解决跨域问题

【引例】使用axios获取“猫眼电影”的数据
打开“猫眼电影”,右键检查,找到Network中对应请求,找到Headers中General的Request URL,用于axios中。
以下情况因为浏览器同源策略的保护机制,出现跨域请求问题。
Home.vue

import axios from 'axios'
axios.get('https://i.maoyan.com/api/mmdb/movie/v3/list/hot.json?ct=%E4%B8%8A%E6%B5%B7&ci=10&channelId=4').then((res)=>{
	console.log(res);
})

【解决方案】使用proxy
创建中转服务器(proxy),代理请求发送给服务端(返回数据的那个,如“猫眼电影”)
Home.vue

import axios from 'axios'
axios.get('/path/api/mmdb/movie/v3/list/hot.json?ct=%E4%B8%8A%E6%B5%B7&ci=10&channelId=4').then((res)=>{
	console.log(res);
})

vite.config.js

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

export default defineConfig({
	plugins: [vue()],
	server: {// 中转服务器
		proxy: {// 通过代理实现跨域
			'/path': { // 简单来说,这个的目的在于【提醒】看到/path就要去代理,对应上方Home.vue中的/path,代理的是下方target的内容
				target: 'https://i.maoyan.com', // 需要替换的服务端地址
				changeOrigin: true, // 开启代理
				rewrite: path=>path.replace(/^\/path, '')// 因为/path只为题型作用,/path为多余的,所以需要重写路径
			}
		}
	}
})

Vuex

文档地址(官方):https://vuex.vuejs.org/zh/

概念

可以理解为一个状态(其实就是数据)管理模式,简单来说就是作为一个仓库集中管理使得各个视图可以使用状态。
一般在大型项目中使用。

安装

  1. 一开始Vue CLI创建时选择;
  2. $ npm install vuex@next --save

基本使用——Store

(以Vue CLI创建后的文件为基础)
新建src/store/index.js

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

// 创建一个新的 store 实例
const store = createStore({
  state () {// 存放单一状态(基本数据)
    return {
      count: 0
    }
  }
})
export default store

main.js

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

HomeView.vue

<h2>{{$store.state.count}}</h2>

选项式情况下,JavaScript中要加this

改变store中的状态——Mutation

不建议直接更改store中的数据。
建议利用mutation改变,大概意思是可以跟踪到什么操作改变了什么数据。
index.js

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

// 创建一个新的 store 实例
const store = createStore({
  state () {// 存放单一状态(基本数据)
    return {
      count: 0
    }
  },
  // 新增内容
  mutations: {// 通过store.commit方法对应函数触发状态变更
    increment (state,value) {// state表示上面state返回的对象,value表示传过来的参数
      state.count+=value
    }
  }
})
export default store

main.js

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

HomeView.vue

<button @click="addCount(5)">count++</button>
methods: {
	addCount(num){
		this.$store.commit('increment',num)// 使用store.commit方法改变state状态
	}
}

也可以提交payload
可以以对象的形式进行提交
Mutation必须是同步函数,异步函数放在Action处理。

从State中派生状态——Getter

getter可以理解为store的计算属性。
index.js

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

// 创建一个新的 store 实例
const store = createStore({
  state () {// 存放单一状态(基本数据)
    return {
      count: 0,
      msg: 'helloworld'
    }
  },
  getters () {
  	reverMsg: function(state) {
  		return state.msg.split('').reverse.join('')
  	},
  	reverMsgLength: function(state, getters) {// getters表示当前store中的getters对象
  		return getters.reverMsg.length
  	}
  }
})
export default store

HomeView.vue

<h2>{{$store.getters.reversMsg}}</h2>
<h2>{{$store.getters.reversMsgLength}}</h2>

异步操作——Action

Action 类似于 mutation,不同在于:

  1. Action 提交的是 mutation,而不是直接变更状态;
  2. Action 可以包含任意异步操作,mutation必须是同步操作。
解决跨域问题方法

以”猫眼电影“为例。
Warning:以下有跨域问题。
store/index.js

const store = createStore({
  state: {
    count: 0
  },
  mutations: {
    increment (state) {
      state.count++
    }
  },
  actions: {
    getHot: function() {// 需要通过dispatch触发
    	fetch('https://i.maoyan.com/api/mmdb/movie/v3/list/hot.json?ct=%E4%B8%8A%E6%B5%B7&ci=10&channelId=4').then((res)=>{
    		console.log(res)
    	})
    }
  }
})

HomeView.vue

mounted() {
	this.$sttore.dispatch('getHot')
}

【解决方案】
vue.config.js
注意:rewrite写法有所不同!

module.exports = defineConfig({
	transpileDependencies: true,
	devServer: {
		proxy: {
			'/path': {
				target: 'https://i.maoyan.com',
				changeOrigin: true,
				//注意!有所不同!
				pathRewrite: {
					'^/path': ''
				}
			}
	}
})

store/index.js

 getHot: function() {// 需要通过dispatch触发
 	fetch('/path/api/mmdb/movie/v3/list/hot.json?ct=%E4%B8%8A%E6%B5%B7&ci=10&channelId=4').then((res)=>{
 		console.log(res.json())
 	})
 }
要接收请求数据

store/index.js

mutations: {
	updateHotList: function(state, value) {
		state.hotList=value
	}
},
actions: {
	getHot: function(context) { // context与store实例具有相同的属性和方法的对象
		axios.get('/path/api/mmdb/movie/v3/list/hot.json?ct=%E4%B8%8A%E6%B5%B7&ci=10&channelId=4').then(res=>{
		context.commit('updateHotList', res.data.data.hot)
		console.log(context.store.hotList)
	})
}
实现传参

HomeView.vue

mounted() {
	this.$store.dispatch('getHot', 'hhh')
}

store/index.js

actions: {
	getHot: function(context, payload) { // context与store实例具有相同的属性和方法的对象
		axios.get('/path/api/mmdb/movie/v3/list/hot.json?ct=%E4%B8%8A%E6%B5%B7&ci=10&channelId=4').then(res=>{
		context.commit('updateHotList', res.data.data.hot)
		console.log(context.store.hotList)
		console.log(payload)// 打印出hhh
	})
}

模块化——Module

文档跳转

模块化处理

store/index.js

const moduleA = {
  state: () => ({
  	userName: "用户张三"
  }),
  mutations: { ... },
  actions: { ... },
  getters: {
  	userNameAge: function(state) {// state是局部状态
  		return state.userName+',今年18岁'
  	}
  }
}

const moduleB = {
  state: () => ({ ... }),
  mutations: { ... },
  actions: { ... }
}

const store = createStore({
  modules: {
    a: moduleA,// 也可以直接写moduleA(moduleA: moduleA)
    b: moduleB
  }
})

store.state.a // -> moduleA 的状态
store.state.b // -> moduleB 的状态
获取数据方式

注意:state比较特殊!
getters、mutations、actions通过 s t o r e 直接获取, s t a t e 通过 store直接获取,state通过 store直接获取,state通过store.state.模块名.状态名获取。
HomeView.vue

<h2>{{$store.getters.userName}}</h2>
<h2>{{$store.state.a.userName}}</h2>
获取根节点实例state的状态

store/index.js

const moduleA = {
  state: () => ({
  	userName: "用户张三"
  }),
  mutations: { ... },
  actions: { ... },
  getters: {
  	userNameAge: function(state, getters, rootState) {// state是局部状态
  		console.log(getters)// 获取store实例中的getters对象
  		console.log(rootState)// 获取根节点实例state的状态
  		return state.userName+',今年18岁'
  	}
  }
}

const moduleB = {
  state: () => ({ ... }),
  mutations: { ... },
  actions: { ... }
}

const store = createStore({
  modules: {
    a: moduleA,// 也可以直接写moduleA(moduleA: moduleA)
    b: moduleB
  }
})

store.state.a // -> moduleA 的状态
store.state.b // -> moduleB 的状态
store结构优化

新建store/userua
新建store/user/index.js
store/user/index.js

const user = {
  state: () => ({
  	userName: "用户张三"
  }),
  mutations: { ... },
  actions: { ... },
  getters: {
  	userNameAge: function(state, getters, rootState) {// state是局部状态
  		console.log(getters)// 获取store实例中的getters对象
  		console.log(rootState)// 获取根节点实例state的状态
  		return state.userName+',今年18岁'
  	}
  }
}
export default user// 在别的地方引入
命名空间

store/user/index.js

const user = {
  namespaced: true,
  state: () => ({
  	userName: "用户张三"
  }),
  mutations: { ... },
  actions: { ... },
  getters: {
  	userNameAge: function(state, getters, rootState) {
  		console.log(getters)
  		console.log(rootState)
  		return state.userName+',今年18岁'
  	}
  }
}
export default user

HomeView.vue

<h2>{{$store.getters[]'a/userNameAge'}}</h2>

methods中也要对应改变(actions、mutations……)。

this.$store.commit('a/updateUserName')

如果要用辅助函数

...mapMutations('a', ['updataUserName'])

辅助函数

文档跳转
HomeView.vue

import {MapState} from 'vuex'
export default {
	// 省略
	computed: mapState({
		// 方式一
		count: state => state.count
		// 方式二
		count: "count"
	})
}
// 方式三
computed: mapState(['count','msg'])
<h2>{{ count }}</h2>

缺点在于如果原本需要有computed,就出现不能同时有两个computed的情况。此时采用对象展开运算符的方法。

computed:
	addNum: function() {
		return this.num*10
	},
	...mapState(['count','msg'])

getters、actions、mutations用法均一致,只需最开始引入。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值