Vue (3)-Ajax, Vuex, routing and UI component library in vue

course link

4. Ajax in Vue

4.1.vue scaffolding configuration agent

4.1.1. Method 1

​ Add the following configuration in vue.config.js:

devServer:{
    
    
  proxy:"http://localhost:5000"
}

illustrate:

  1. Advantages: The configuration is simple, and it can be sent directly to the front end (8080) when requesting resources.
  2. Disadvantages: Multiple proxies cannot be configured, and it is not possible to flexibly control whether requests go through proxies.
  3. Working method: If the proxy is configured as above, when a resource that does not exist in the front-end is requested, the request will be forwarded to the server (priority matching front-end resources [resources under public])

4.1.2. Method 2

​ Write vue.config.js to configure specific proxy rules:

module.exports = {
    
    
	devServer: {
    
    
      proxy: {
    
    
      '/api1': {
    
    // 匹配所有以 '/api1'开头的请求路径
        target: 'http://localhost:5000',// 代理目标的基础路径
        changeOrigin: true,//用于控制请求头中的host值
        pathRewrite: {
    
    '^/api1': ''}
      },
      '/api2': {
    
    // 匹配所有以 '/api2'开头的请求路径
        target: 'http://localhost:5001',// 代理目标的基础路径
        changeOrigin: true,//用于控制请求头中的host值
        pathRewrite: {
    
    '^/api2': ''}
      }
    }
  }
}
/*
   changeOrigin设置为true时,服务器收到的请求头中的host为:localhost:5000
   changeOrigin设置为false时,服务器收到的请求头中的host为:localhost:8080
   changeOrigin默认值为true
*/

illustrate:

  1. Advantages: Multiple proxies can be configured, and it is possible to flexibly control whether requests go through proxies.
  2. Disadvantages: The configuration is slightly cumbersome, and a prefix must be added when requesting resources.

4.2. Slots

  1. Function: Allow the parent component to insert the html structure to the specified position of the child component , and it is also a way of communication between components, which is suitable for parent components ===> child components .

  2. Categories: default slots, named slots, scoped slots

  3. How to use:

    1. Default slot:

      父组件中:
              <Category>
                 <div>html结构1</div>
              </Category>
      子组件中:
              <template>
                  <div>
                     <!-- 定义插槽 -->
                     <slot>插槽默认内容...</slot>
                  </div>
              </template>
      
    2. Named slots:

      父组件中:
              <Category>
                  <template slot="center">
                    <div>html结构1</div>
                  </template>
      
                  <!-- <template slot="footer"></template> -->
                  <template v-slot:footer><!--v-slot只能配合template使用-->
                     <div>html结构2</div>
                  </template>
              </Category>
      子组件中:
              <template>
                  <div>
                     <!-- 定义插槽 -->
                     <slot name="center">插槽默认内容...</slot>
                     <slot name="footer">插槽默认内容...</slot>
                  </div>
              </template>
      
    3. Scoped slots:

      1. Understanding: The data is in the component itself , but the structure generated according to the data needs to be determined by the user of the component. (The games data is in the Category component, but the structure traversed by using the data is determined by the App component)

      2. Specific encoding:

        父组件中:
        		<Category>
        			<template scope="scopeData">
        				<!-- 生成的是ul列表 -->
        				<ul>
        					<li v-for="g in scopeData.games" :key="g">{
                 
                 {g}}</li>
        				</ul>
        			</template>
        		</Category>
        
        		<Category>
        			<template slot-scope="scopeData">
        				<!-- 生成的是h4标题 -->
        				<h4 v-for="g in scopeData.games" :key="g">{
                 
                 {g}}</h4>
        			</template>
        		</Category>
        子组件中:
                <template>
                    <div>
                        <slot :games="games"></slot>
                    </div>
                </template>
        		
                <script>
                    export default {
                    
                    
                        name:'Category',
                        props:['title'],
                        //数据在子组件自身
                        data() {
                    
                    
                            return {
                    
                    
                                games:['红色警戒','穿越火线','劲舞团','超级玛丽']
                            }
                        },
                    }
                </script>
        

    How to understand the scope: mainly in the subcomponent slot tag: games='games' and parent component's scope='xxx'

5.Vuex

5.1. Understanding Vuex

5.1.1. Concept

​ A Vue plug- in that implements centralized state (data) management in Vue , and performs centralized management (read/write) on the shared state of multiple components in Vue applications . It is also a way of communication between components, and is suitable for Communication between arbitrary components.

5.1.2. When to use?

​ When multiple components need to share data

5.1.3. vuex principle

insert image description here

simile:
insert image description here

insert image description here

  • These three are managed by the store, and their data types are all objects , and all components must be able to see the store.

5.2. Use of vuex

5.2.1. Build the vuex environment

  1. Install vuex:
  npm i vuex//vue3版本所对应的vuex4版本

  npm i vuex@3//vue2版本下载vuex3版本
  1. Create a file:src/store/index.js

    //引入Vue核心库
    import Vue from 'vue'
    //引入Vuex
    import Vuex from 'vuex'
    //应用Vuex插件
    Vue.use(Vuex)
    
    //准备actions对象——响应组件中用户的动作
    const actions = {
          
          }
    //准备mutations对象——修改state中的数据
    const mutations = {
          
          }
    //准备state对象——保存具体的数据
    const state = {
          
          }
    
    //创建并暴露store
    export default new Vuex.Store({
          
          
    	actions,
    	mutations,
    	state
    })
    
  2. Pass in configuration items main.jswhen creating a vm instore

    ......
    //引入store
    import store from './store'
    ......
    
    //创建vm
    new Vue({
          
          
    	el:'#app',
    	render: h => h(App),
    	store
    })
    

5.2.2. Basic usage

  1. Initialize data, configure actions, configure mutations, manipulate filesstore.js

    //引入Vue核心库
    import Vue from 'vue'
    //引入Vuex
    import Vuex from 'vuex'
    //引用Vuex
    Vue.use(Vuex)
    
    const actions = {
          
          
        //响应组件中加的动作
    	jia(context,value){
          
          
    		// console.log('actions中的jia被调用了',miniStore,value)
    		context.commit('JIA',value)
    	},
    }
    
    const mutations = {
          
          
        //执行加
    	JIA(state,value){
          
          
    		// console.log('mutations中的JIA被调用了',state,value)
    		state.sum += value
    	}
    }
    
    //初始化数据
    const state = {
          
          
       sum:0
    }
    
    //创建并暴露store
    export default new Vuex.Store({
          
          
    	actions,
    	mutations,
    	state,
    })
    
  2. Read the data in vuex in the component:$store.state.sum

  3. Modify the data in vuex in the component: $store.dispatch('action中的方法名',数据)or$store.commit('mutations中的方法名',数据)

Remarks: If there is no network request or other business logic, actions can also be skipped in the component, that is, without writing dispatch, you can directly write commit
the html page without adding this when parsing the state, but it is required when writing vue in js

5.2.3. Use of getters

  1. Concept: When the data in the state needs to be processed before use, getters can be used for processing.

  2. store.jsAppend gettersconfiguration in

    ......
    
    const getters = {
          
          
    	bigSum(state){
          
          
    		return state.sum * 10
    	}
    }
    
    //创建并暴露store
    export default new Vuex.Store({
          
          
    	......
    	getters
    })
    
  3. Read data in the component:$store.getters.bigSum

5.2.4. The use of four map methods

  1. mapState method: used to help us map statethe data into computed properties

    computed: {
          
          
        //借助mapState生成计算属性:sum、school、subject(对象写法)
         ...mapState({
          
          sum:'sum',school:'school',subject:'subject'}),
             
        //借助mapState生成计算属性:sum、school、subject(数组写法)
        ...mapState(['sum','school','subject']),
    },
    
  2. mapGetters method: used to help us map gettersthe data into computed properties

    computed: {
          
          
        //借助mapGetters生成计算属性:bigSum(对象写法)
        ...mapGetters({
          
          bigSum:'bigSum'}),
    
        //借助mapGetters生成计算属性:bigSum(数组写法)
        ...mapGetters(['bigSum'])
    },
    
  3. mapActions method: the method used to help us generate and actionsdialogue, namely: the included $store.dispatch(xxx)function

    methods:{
          
          
        //靠mapActions生成:incrementOdd、incrementWait(对象形式)
        ...mapActions({
          
          incrementOdd:'jiaOdd',incrementWait:'jiaWait'})
    
        //靠mapActions生成:incrementOdd、incrementWait(数组形式)
        ...mapActions(['jiaOdd','jiaWait'])
    }
    
  4. mapMutations method: the method used to help us generate and mutationsdialogue, namely: $store.commit(xxx)the function contained

    methods:{
          
          
        //靠mapActions生成:increment、decrement(对象形式)
        ...mapMutations({
          
          increment:'JIA',decrement:'JIAN'}),
        
        //靠mapMutations生成:JIA、JIAN(对象形式)
        ...mapMutations(['JIA','JIAN']),
    }
    

Remarks: When using mapActions and mapMutations, if you need to pass parameters, you need to pass the parameters when binding the event in the template, otherwise the parameters are event objects.

5.2.5. Modularity + Namespace

  1. Purpose: Make the code easier to maintain, and make the classification of various data more clear.

  2. Revisestore.js

    const countAbout = {
          
          
      namespaced:true,//开启命名空间
      state:{
          
          x:1},
      mutations: {
          
           ... },
      actions: {
          
           ... },
      getters: {
          
          
        bigSum(state){
          
          
           return state.sum * 10
        }
      }
    }
    
    const personAbout = {
          
          
      namespaced:true,//开启命名空间
      state:{
          
           ... },
      mutations: {
          
           ... },
      actions: {
          
           ... }
    }
    
    const store = new Vuex.Store({
          
          
      modules: {
          
          
        countAbout,
        personAbout
      }
    })
    
  3. After the namespace is enabled, the state data is read in the component:

    //方式一:自己直接读取
    this.$store.state.personAbout.list
    //方式二:借助mapState读取:
    ...mapState('countAbout',['sum','school','subject']),
    
  4. After the namespace is enabled, getters data is read in the component:

    //方式一:自己直接读取
    this.$store.getters['personAbout/firstPersonName']
    //方式二:借助mapGetters读取:
    ...mapGetters('countAbout',['bigSum'])
    
  5. After the namespace is enabled, dispatch is called in the component

    //方式一:自己直接dispatch
    this.$store.dispatch('personAbout/addPersonWang',person)
    //方式二:借助mapActions:
    ...mapActions('countAbout',{
          
          incrementOdd:'jiaOdd',incrementWait:'jiaWait'})
    
  6. After the namespace is enabled, commit is called in the component

    //方式一:自己直接commit
    this.$store.commit('personAbout/ADD_PERSON',person)
    //方式二:借助mapMutations:
    ...mapMutations('countAbout',{
          
          increment:'JIA',decrement:'JIAN'}),
    

6. Routing

6.1. Related understanding

6.1.1. Understanding of routing

  1. Understanding: A route is a set of mapping relationships (key-value), and multiple routes need to be managed by a router.
  2. Front-end routing: the key is the path, and the value is the component. (backend routing value is function)

6.1.2. vue-router understanding

A plug-in library for Vue, specially used to implement SPA applications

What is a SPA application:

  1. Single page web application (single page web application, SPA)
  2. There is only one full page for the entire application
  3. Clicking the navigation link in the page will not refresh the page, only a partial update of the page
  4. The data needs to be obtained through ajax request.

6.2. Basic Routing

6.2.1. Basic usage

  1. Install vue-router, command: npm i vue-router
    vue2 needs to download npm i vue-router@3version 3

  2. Apply plugin:Vue.use(VueRouter)

  3. Write router configuration items:

    //引入VueRouter
    import VueRouter from 'vue-router'
    //引入Luyou 组件
    import About from '../components/About'
    import Home from '../components/Home'
    
    //创建router实例对象,去管理一组一组的路由规则
    const router = new VueRouter({
          
          
    	routes:[
    		{
          
          
    			path:'/about',
    			component:About
    		},
    		{
          
          
    			path:'/home',
    			component:Home
    		}
    	]
    })
    
    //暴露router
    export default router
    
  4. Implement switching (active-class can configure highlighting style)

    <router-link active-class="active" to="/about">About</router-link>
    
  5. target placements

    <router-view></router-view>
    

6.2.2. Several Notes

  1. Routing components are usually stored in pagesfolders, and general components are usually stored in componentsfolders.
  2. By switching, the "hidden" routing components are destroyed by default , and then mounted when needed .
  3. Each component has its own $routeproperties, which store its own routing information.
  4. The entire application has only one router, which can $routerbe obtained through the properties of the component.

6.3. Nested (multi-level) routing

  1. To configure routing rules, use the children configuration item:

    routes:[
    	{
          
          
    		path:'/about',
    		component:About,
    	},
    	{
          
          
    		path:'/home',
    		component:Home,
    		children:[ //通过children配置子级路由
    			{
          
          
    				path:'news', //此处一定不要写:/news
    				component:News
    			},
    			{
          
          
    				path:'message',//此处一定不要写:/message
    				component:Message
    			}
    		]
    	}
    ]
    
  2. Jump (to write the full path):

    <router-link to="/home/news">News</router-link>
    

6.4. The query parameter of the route

  1. pass parameters

    <!-- 跳转并携带query参数,to的字符串写法 -->
    <router-link :to="/home/message/detail?id=666&title=你好">跳转</router-link>
    				
    <!-- 跳转并携带query参数,to的对象写法 -->
    <router-link 
    	:to="{
    		path:'/home/message/detail',
    		query:{
    		   id:666,
                title:'你好'
    		}
    	}"
    >跳转</router-link>
    
  2. Receive parameters:

    $route.query.id
    $route.query.title
    

6.5. Naming Routes

  1. Function: It can simplify the routing jump.

  2. how to use

    1. Give the route a name:

      {
              
              
      	path:'/demo',
      	component:Demo,
      	children:[
      		{
              
              
      			path:'test',
      			component:Test,
      			children:[
      				{
              
              
                            name:'hello' //给路由命名
      					path:'welcome',
      					component:Hello,
      				}
      			]
      		}
      	]
      }
      
    2. Simplified jump:

      <!--简化前,需要写完整的路径 -->
      <router-link to="/demo/test/welcome">跳转</router-link>
      
      <!--简化后,直接通过名字跳转 -->
      <router-link :to="{name:'hello'}">跳转</router-link>
      
      <!--简化写法配合传递参数 -->
      <router-link 
      	:to="{
      		name:'hello',
      		query:{
      		   id:666,
                  title:'你好'
      		}
      	}"
      >跳转</router-link>
      

6.6. The params parameter of the route

  1. Configure routing, declare to receive params parameters

    {
          
          
    	path:'/home',
    	component:Home,
    	children:[
    		{
          
          
    			path:'news',
    			component:News
    		},
    		{
          
          
    			component:Message,
    			children:[
    				{
          
          
    					name:'xiangqing',
    					path:'detail/:id/:title', //使用占位符声明接收params参数
    					component:Detail
    				}
    			]
    		}
    	]
    }
    
  2. pass parameters

    <!-- 跳转并携带params参数,to的字符串写法 -->
    <router-link :to="/home/message/detail/666/你好">跳转</router-link>
    				
    <!-- 跳转并携带params参数,to的对象写法 -->
    <router-link 
    	:to="{
    		name:'xiangqing',
    		params:{
    		   id:666,
                title:'你好'
    		}
    	}"
    >跳转</router-link>
    

    Special attention: When the route carries params parameters, if you use the object writing method of to, you cannot use the path configuration item, you must use the name configuration !

  3. Receive parameters:

    $route.params.id
    $route.params.title
    

6.7. Routing props configuration

​ Role: Make it easier for routing components to receive parameters

{
    
    
	name:'xiangqing',
	path:'detail/:id',
	component:Detail,

	//第一种写法:props值为对象,该对象中所有的key-value的组合最终都会通过props传给Detail组件
	// props:{a:900}

	//第二种写法:props值为布尔值,布尔值为true,则把路由收到的所有params参数通过props传给Detail组件
	// props:true
	
	//第三种写法:props值为函数,该函数返回的对象中每一组key-value都会通过props传给Detail组件
	props(route){
    
    
		return {
    
    
			id:route.query.id,
			title:route.query.title
		}
	}
}

6.8. <router-link>The replace attribute

  1. Role: control the mode of operating browser history when routing jumps
  2. There are two ways to write browser history: pushand respectively replace. When the route jumps, the default is push
    pushto append the history record
    replaceor replace the current record
  3. How to turn on replacethe mode:<router-link replace .......>News</router-link>
    insert image description here

6.9. Programmatic Routing Navigation

  1. <router-link> Function: Make routing jumps more flexible without the help of routing jumps

  2. Specific encoding:

    //$router的两个API
    this.$router.push({
          
          
    	name:'xiangqing',
    		params:{
          
          
    			id:xxx,
    			title:xxx
    		}
    })
    
    this.$router.replace({
          
          
    	name:'xiangqing',
    		params:{
          
          
    			id:xxx,
    			title:xxx
    		}
    })
    this.$router.forward() //前进
    this.$router.back() //后退
    
    //传数字 正数就是前进几步 负数就是后退几步
    this.$router.go() //可前进也可后退 
    
    

6.10. Cache Routing Components

  1. Function: keep the routing components that are not displayed mounted and not destroyed.

  2. Specific encoding:

 <!-- 缓存一个时 -->
  <!--  <keep-alive include="News">  --><!--缓存哪个路由<写组件名>的内容,不写则都缓存-->

  <!-- 缓存多个时 -->
   <keep-alive :include="[News, Message]"> 
       <router-view></router-view>
   </keep-alive>

6.11. Two new lifecycle hooks

  1. Function: Two hooks unique to routing components, used to capture the activation status of routing components.
  2. specific name:
    1. activatedFired when the routing component is activated.
    2. deactivatedTriggered when the routing component is deactivated.
      PS: The nextTick mentioned before is also a hook

6.12. Route Guard

  1. Role: to control the authority of the route

  2. Category: global guard, exclusive guard, component guard

  3. Global Guard:

    //全局前置守卫:初始化时执行、每次路由切换前执行
    router.beforeEach((to,from,next)=>{
          
          
    	console.log('beforeEach',to,from)
    	if(to.meta.isAuth){
          
           //判断当前路由是否需要进行权限控制
    		if(localStorage.getItem('school') === 'atguigu'){
          
           //权限控制的具体规则
    			next() //放行
    		}else{
          
          
    			alert('暂无权限查看')
    			// next({name:'guanyu'})
    		}
    	}else{
          
          
    		next() //放行
    	}
    })
    
    //全局后置守卫:初始化时执行、每次路由切换后执行
    router.afterEach((to,from)=>{
          
          
    	console.log('afterEach',to,from)
    	if(to.meta.title){
          
           
    		document.title = to.meta.title //修改网页的title
    	}else{
          
          
    		document.title = 'vue_test'
    	}
    })
    
  4. Exclusive Guard:

    beforeEnter(to,from,next){
          
          
    	console.log('beforeEnter',to,from)
    	if(to.meta.isAuth){
          
           //判断当前路由是否需要进行权限控制
    		if(localStorage.getItem('school') === 'atguigu'){
          
          
    			next()
    		}else{
          
          
    			alert('暂无权限查看')
    			// next({name:'guanyu'})
    		}
    	}else{
          
          
    		next()
    	}
    }
    
  5. Guards inside the component:

    //进入守卫:通过路由规则,进入该组件时被调用
    beforeRouteEnter (to, from, next) {
          
          
    },
    //离开守卫:通过路由规则,离开该组件时被调用
    beforeRouteLeave (to, from, next) {
          
          
    }
    

6.13. Two working modes of the router

6.13.1.hash & history

  1. For a url, what is the hash value? —— #及其后面的内容就是hash值.
  2. The hash value will not be included in the HTTP request, that is: the hash value will not be brought to the server.
  3. hash mode:
    1. There is always a # sign in the address, which is not beautiful.
    2. If the address is shared through a third-party mobile app in the future, if the app verification is strict, the address will be marked as illegal.
    3. Compatibility is better.
  4. history mode:
    1. The address is clean and beautiful.
    2. Compatibility is slightly worse than hash mode.
    3. When the application is deployed and launched, it needs the support of the back-end personnel to solve the problem of refreshing the page server 404.

6.13.2. nodejs deployment project (simple version)

The general process of nodejs deploying a project:

  1. Package the project npm run buildand pay attention to whether the difference is hash or history mode
  2. initialize a projectnpm init
  3. Install express in nodejsnpm i express
  4. Write server.js
    (may need to download npm install --save connect-history-api-fallback)
//使用nodejs部署项目server.js
const express = require('express')
//hash模式不用这样
//history模式下,使用connect-history-api-fallback来解决 单独复制并新建一个页面填入http://localhost:5005/home/message等页面不出现内容的问题
const history = require('connect-history-api-fallback');
const app = express()
//history模式下
app.use(history())

//指定路径
app.use(express.static(__dirname+'/static'))

/* app.get('/person',(req,res)=>{
    res.send({
        name:'tom',
        age:18,
    })
}) */

app.listen(5005,(err)=>{
    
    
    if(!err) console.log('服务器启动成功了')
})

  1. run projectnode server

7.VUE UI Group Library

7.1. Commonly used UI component libraries on the mobile terminal

  1. Vant https://youzan.github.io/vant
  2. Cube UI https://didi.github.io/cube-ui
  3. Mint UI http://mint-ui.github.io

7.2. Commonly used UI component library on PC

  1. Element UI https://element.eleme.cn
  2. IView UI https://www.iviewui.co

Guess you like

Origin blog.csdn.net/m0_43416592/article/details/129720450