[记录学习]自学尚硅谷张天禹Vue2+3框架_vue_test

首先感谢尚硅谷和张天禹老师的教学分享!Respect!

学习来源:B站
https://www.bilibili.com/video/BV1Zy4y1K7SH?p=1&vd_source=07c8a1a7d89af39fe20c3a6894f5ff6a
资料来源:百度网盘
链接:https://pan.baidu.com/s/1Y7mTMXzlBXqKve8KWSPwtg?pwd=7bna
提取码:7bna

文章目录

    • 首先感谢尚硅谷和张天禹老师的教学分享!Respect!
    • vue_test
      • 1. 分析脚手架
        • 安装脚手架
        • 脚手架文件结构
        • 关于不同版本的Vue
        • vue.config.js配置文件
      • 2. ref属性
      • 3.props配置
      • 4. mixin(混入)
      • 5. 插件
      • 6. scoped样式
      • 7. 总结TodoList案例
      • 8. 浏览器本地存储webStorage
      • 9. TodoList_本地存储
      • 10. 组件的自定义事件
      • 11. TodoList_自定义事件
      • 12. 全局事件总线(GlobalEventBus)
      • 13. TodoList_事件总线
      • 14. 消息订阅与发布(pubsub)
      • 15. TodoList_pubsub
      • 16. TodoList_nextTick
      • 17. Vue封装的过度与动画
      • 18. TodoList_动画
      • 19. vue脚手架配置代理
        • 方法一
        • 方法二
      • 20. GitHub搜索案例
      • 21. GitHub搜索案例_vue-resource
      • 22. 插槽
        • 默认插槽
        • 具名插槽
        • 作用域插槽
      • 23. 求和案例_纯vue版
      • Vuex
        • 1.概念
        • 2.何时使用?
        • 3.搭建vuex环境
        • 4.基本使用
      • 24. 求和案例_vuex版
        • 5.getters的使用
      • 25. 求和案例_getters
        • 6.四个map方法的使用
      • 26. 求和案例_mapState与mapGetters
      • 27. 求和案例_mapMutations与mapActions
      • 28. 求和案例_多组件共享数据
        • 7.模块化+命名空间
      • 29. 求和案例_vuex模板化编码
      • 路由
        • 1.基本使用
      • 30. 路由的基本使用
        • 2.几个注意点
        • 3.多级路由(多级路由)
      • 31. 多级路由
        • 4.路由的query参数
      • 32. 路由的query参数
        • 5.命名路由
      • 33. 命名路由
        • 6.路由的params参数
      • 34. 路由的params参数
        • 7.路由的props配置
      • 35. 路由的props配置
        • 8.``的replace属性
      • 36. ``的replace属性
        • 9.编程式路由导航
      • 37. 编程式路由导航
        • 10.缓存路由组件
      • 38. 缓存路由组件
        • 11.两个新的生命周期钩子
      • 39. 两个新的生命周期钩子
        • 12.路由守卫
      • 40. 全局路由守卫
      • 41. 独享路由守卫
      • 42. 组件内路由守卫
        • 13.路由器的两种工作模式
      • 43. history模式与hash模式
      • 44. element-ui组件库
        • 完整引入
        • 按需引入

vue_test

1. 分析脚手架

安装脚手架

  1. (仅第一次执行)全局安装@vue/cli

    npm install -g @vue/cli

  2. 切换到要创建项目的目录,然后使用命令创造项目

    vue create 项目名

  3. 启动项目

    npm run serve

脚手架文件结构

├── node_modules

├── public

│ ├── favicon.ico: 页签图标

│ └── index.html: 主页面

├── src

│ ├── assets: 存放静态资源

│ │ └── logo.png

│ │── component: 存放组件

│ │ └── HelloWorld.vue

│ │── App.vue: 汇总所有组件

│ │── main.js: 入口文件

├── .gitignore: git版本管制忽略的配置

├── babel.config.js: babel的配置文件

├── package.json: 应用包配置文件

├── README.md: 应用描述文件

├── package-lock.json:包版本控制文件

关于不同版本的Vue

  1. vue.js与vue.runtime.xxx.js的区别:

    1. vue.js是完整版的Vue,包含:核心功能 + 模板解析器。
    2. vue.runtime.xxx.js是运行版的Vue,只包含:核心功能;没有模板解析器。
  2. 因为vue.runtime.xxx.js没有模板解析器,所以不能使用template这个配置项,需要使用render函数接收到的createElement函数去指定具体内容。

vue.config.js配置文件

  1. 使用vue inspect > output.js可以查看到Vue脚手架的默认配置。

  2. 使用vue.config.js可以对脚手架进行个性化定制,详情见:https://cli.vuejs.org/zh

  • components\Student.vue

    
    
    
    
  • components\School.vue

    
    
    
    
    
    
  • App.vue

    
    
    
    
    
    
  • main.js

    /*
      该文件是整个项目的入口文件
    */
    // 引入Vue
    import Vue from 'vue'
    // 引入App组件,它是所有组件的父组件
    import App from './App.vue'
    
    // 创建Vue实例对象——vm
    new Vue({
        el:'#app',
        render: h => h(App)
    })
    

2. ref属性

ref属性

  1. 被用来给元素或子组件注册引用信息(id的替代者)
  2. 应用在html标签上获取的是真实DOM元素,应用在组件标签上是组件实例对象(vc)
  3. 使用方式:
    1. 打标识:

      .....

    2. 获取:this.$refs.xxx
  • components\School.vue

    
    
    
    
    
    
  • App.vue

    
    
    
    
    
    
  • 控制台输出

    [记录学习]自学尚硅谷张天禹Vue2+3框架_vue_test_第1张图片

3.props配置

props配置项

  1. 功能:让组件接收外部传过来的数据

  2. 传递数据:

  3. 接收数据:

    1. 第一种方式(只接收):props:['name']

    2. 第二种方式(限制类型):props:{name:String}

    3. 第三种方式(限制类型、限制必要性、指定默认值):

      props:{
      	name:{
      	type:String, //类型
      	required:true, //必要性
      	default:'老王' //默认值
      	}
      }
      

    备注:props是只读的,Vue底层会监测你对props的修改,如果进行了修改,就会发出警告,若业务需求确实需要修改,那么请复制props的内容到data中一份,然后去修改data中的数据。

  • components\Student.vue

    <template>
        <div>
            <h1>{{msg}}h1>
            <h2>学生姓名:{{name}}h2>
            <h2>学生性别:{{sex}}h2>
            <h2>学生年龄:{{myAge+1}}h2>
            <button @click="updateAge">尝试修改收到的年龄button>
        div>
    template>
    
    <script>
        export default {
            name: 'Student',
            data() {
                console.log(this);
                return {
                    msg:'我是一个学Vue的学生',
                    myAge:this.age
                }
            },
            methods:{
                updateAge(){
                    this.myAge++
                }
            },
            // 简单声明接收
            // props:['name', 'age', 'sex']
    
            // 接收的同时对数据进行类型限制
            // props:{
            //     name:String,
            //     age:Number,
            //     sex:String
            // }
    
            // 接收的同时对数据进行:类型限制+默认值的指定+必要的限制
            props:{
                name:{
                    // name的类型是字符串
                    type:String,
                    // name是必要的, 如果不提供会警告
                    required:true
                },
                age:{
                    type:Number,
                    // 默认值
                    default:99
                }, 
                sex:{
                    type:String,
                    required:true,
                }
            }
    
        }
    script>
    
  • App.vue

    <template>
        <div>
            
            <Student name="李四" sex="" :age="18">Student>    
        div>
    template>
    
    <script>
        // 引入组件
        import Student from './components/Student.vue'
    
        export default {
            name: 'App',
            components:{
                Student
            }
        };
    script>
    
    <style>
    
    style>
    

4. mixin(混入)

  1. 功能:可以把多个组件共用的配置提取成一个混入对象

  2. 使用方式:

    第一步定义混合:

    {
        data(){....},
        methods:{....}
        ....
    }
    

    第二步使用混入:

    全局混入:Vue.mixin(xxx)
    局部混入:mixins:['xxx']

  • src\mixin.js

    export const hunhe = { 
        methods: {
            showName(){
                alert(this.name)
            }
        },
        mounted() {
            console.log('你好啊!')
        },
    }
    export const hunhe2 = {
        data(){
            return {
                x:100,
                y:200
            }
        }
    }
    
  • src\components\Student.vue

    
    
    
    
  • src\components\School.vue

    
    
    
    
  • src\App.vue

    
    
    
    
    
    
  • src\main.js

    /*
      该文件是整个项目的入口文件
    */
    // 引入Vue
    import Vue from 'vue'
    // 引入App组件,它是所有组件的父组件
    import App from './App.vue'
    // 引入mixin插件
    import { hunhe, hunhe2 } from './mixin'
    // 关闭Vue的生产提示
    Vue.config.productionTip = false
    
    // 全局加入混合mixin,每一个组件都有
    Vue.mixin(hunhe)
    Vue.mixin(hunhe2)
    
    // 创建Vue实例对象——vm
    new Vue({
        el:'#app',
        render: h => h(App)
    })
    

5. 插件

  1. 功能:用于增强Vue

  2. 本质:包含install方法的一个对象,install的第一个参数是Vue,第二个以后的参数是插件使用者传递的数据。

  3. 定义插件:

    对象.install = function (Vue, options) {
        // 1. 添加全局过滤器
        Vue.filter(....)
    
        // 2. 添加全局指令
        Vue.directive(....)
    
        // 3. 配置全局混入(合)
        Vue.mixin(....)
    
        // 4. 添加实例方法
        Vue.prototype.$myMethod = function () {...}
        Vue.prototype.$myProperty = xxxx
    }
    
  4. 使用插件:Vue.use()

  • src\plugins.js

    // const plugins = {
    export default {
        install(Vue, x, y, z){
            console.log(x, y, z)
            // 全局过滤器
            Vue.filter('mySlice', function(value){
                return value.slice(0, 4)
            })
    
            // 定义全局指令
            Vue.directive('fbind', {
                bind(element, binding){
                    element.value = binding.value
                },
                inserted(element, binding){
                    element.focus()
                },
                update(element, binding){
                    element.value = binding.value
                }
            })
    
            // 定义混入mixin
            Vue.mixin({
                data(){
                    return {
                        x:100,
                        y:200
                    }
                }
            })
    
            // 给Vue原型上添加一个方法(vm和vc就都能用了)
            Vue.prototype.hello = ()=>{
                alert('你好啊!')
            }
        }
    }
    
    // export default plugins
    
  • src\components\Student.vue

    
    
    
    
  • src\components\School.vue

    
    
    
    
  • src\App.vue

    
    
    
    
    
    
  • src\main.js

    /*
      该文件是整个项目的入口文件
    */
    // 引入Vue
    import Vue from 'vue'
    // 引入App组件,它是所有组件的父组件
    import App from './App.vue'
    // 引入插件
    import plugins from './plugins'
    // 关闭Vue的生产提示
    Vue.config.productionTip = false
    
    // 应用插件
    Vue.use(plugins, 1, 2, 3)
    
    
    // 创建Vue实例对象——vm
    new Vue({
        el:'#app',
        render: h => h(App)
    })
    

6. scoped样式

  1. 作用:让样式在局部生效,防止冲突。
  2. 写法:需要根据webpack版本安装less-loader

    我的webpack版本为5.7.*,安装的less-loader版本为6

    npm install less-loader@6

  • src\components\Student.vue

    
    
    
    
    
    
  • src\components\School.vue

    
    
    
    
    
    
  • src\App.vue

    
    
    
    
    
    

7. 总结TodoList案例

  1. 组件化编码流程:

    (1).拆分静态组件:组件要按照功能点拆分,命名不要与html元素冲突。

    (2).实现动态组件:考虑好数据的存放位置,数据是一个组件在用,还是一些组件在用:

       	1).一个组件在用:放在组件自身即可。
    
       	2). 一些组件在用:放在他们共同的父组件上(状态提升)。
    

    (3).实现交互:从绑定事件开始。

  2. props适用于:

    (1).父组件 ==> 子组件 通信

    (2).子组件 ==> 父组件 通信(要求父先给子一个函数)

  3. 使用v-model时要切记:v-model绑定的值不能是props传过来的值,因为props是不可以修改的!

  4. props传过来的若是对象类型的值,修改对象中的属性时Vue不会报错,但不推荐这样做。

  • src\App.vue

    
    
    
    
    
    
  • src\components\Header.vue

    
    
    
    
    
    
  • src\components\Footer.vue

    
    
    
    
    
    
  • src\components\List.vue

    
    
    
    
    
    
  • src\components\Item.vue

    
    
    
    
    
    

8. 浏览器本地存储webStorage

  1. 存储内容大小一般支持5MB左右(不同浏览器可能还不一样)

  2. 浏览器端通过 Window.sessionStorage 和 Window.localStorage 属性来实现本地存储机制。

  3. 相关API:

    1. xxxxxStorage.setItem('key', 'value');
      该方法接受一个键和值作为参数,会把键值对添加到存储中,如果键名存在,则更新其对应的值。

    2. xxxxxStorage.getItem('person');

      该方法接受一个键名作为参数,返回键名对应的值。
      
    3. xxxxxStorage.removeItem('key');

      该方法接受一个键名作为参数,并把该键名从存储中删除。
      
    4. xxxxxStorage.clear()

      该方法会清空存储中的所有数据。
      
  4. 备注:

    1. SessionStorage存储的内容会随着浏览器窗口关闭而消失。
    2. LocalStorage存储的内容,需要手动清除才会消失。
    3. xxxxxStorage.getItem(xxx)如果xxx对应的value获取不到,那么getItem的返回值是null。
    4. JSON.parse(null)的结果依然是null。
  • 08_浏览器本地存储webStorage\sessionStorage.html

    DOCTYPE html>
    <html>
        <head>
            <meta charset="UTF-8" />
            <title>sessionStoragetitle>
        head>
        <body>
            <h2>sessionStorageh2>
            <button onclick="saveData()">点我保存一个数据button>
            <button onclick="readData()">点我读取一个数据button>
            <button onclick="deleteData()">点我删除一个数据button>
            <button onclick="deleteAllData()">点我清空数据button>
            
            <script type="text/javascript">
                let p = {name:'张三', age:18}
    
                function saveData(){
                    sessionStorage.setItem('msg', 'hello!!!!')    
                    sessionStorage.setItem('msg2', 666)    
                    sessionStorage.setItem('person', JSON.stringify(p))    
                }
                function readData(){
                    console.log(sessionStorage.getItem('msg'));
                    console.log(sessionStorage.getItem('msg2'));
                    const result = sessionStorage.getItem('person')
                    console.log(JSON.parse(result));
                }
                function deleteData(){
                    sessionStorage.removeItem('msg2')
                }
                function deleteAllData(){
                    sessionStorage.clear()
                }
            script>
        body>
    html>
    
  • 08_浏览器本地存储webStorage\localStorage.html

    DOCTYPE html>
    <html>
        <head>
            <meta charset="UTF-8" />
            <title>localStoragetitle>
        head>
        <body>
            <h2>sessionStorageh2>
            <button onclick="saveData()">点我保存一个数据button>
            <button onclick="readData()">点我读取一个数据button>
            <button onclick="deleteData()">点我删除一个数据button>
            <button onclick="deleteAllData()">点我清空数据button>
            
            <script type="text/javascript">
                let p = {name:'张三', age:18}
    
                function saveData(){
                    localStorage.setItem('msg', 'hello!!!!')    
                    localStorage.setItem('msg2', 666)    
                    localStorage.setItem('person', JSON.stringify(p))    
                }
                function readData(){
                    console.log(localStorage.getItem('msg'));
                    console.log(localStorage.getItem('msg2'));
                    const result = localStorage.getItem('person')
                    console.log(JSON.parse(result));
                }
                function deleteData(){
                    localStorage.removeItem('msg2')
                }
                function deleteAllData(){
                    localStorage.clear()
                }
            script>
        body>
    html>
    

9. TodoList_本地存储

  • src\App.vue

    
    
    
    
    
    
  • 测试结果

    [记录学习]自学尚硅谷张天禹Vue2+3框架_vue_test_第2张图片

10. 组件的自定义事件

  1. 一种组件间通信的方式,适用于:子组件 ===> 父组件

  2. 使用场景:A是父组件,B是子组件,B想给A传数据,那么就要在A中给B绑定自定义事件(事件的回调在A中)。

  3. 绑定自定义事件:

    1. 第一种方式,在父组件中:

    2. 第二种方式,在父组件中:

      <Demo ref="demo"/>
      ......
      mounted(){
         this.$refs.xxx.$on('atguigu',this.test)
      }
      
    3. 若想让自定义事件只能触发一次,可以使用once修饰符,或$once方法。

  4. 触发自定义事件:this.$emit('atguigu',数据)

  5. 解绑自定义事件this.$off('atguigu')

  6. 组件上也可以绑定原生DOM事件,需要使用native修饰符。

  7. 注意:通过this.$refs.xxx.$on('atguigu',回调)绑定自定义事件时,回调要么配置在methods中,要么用箭头函数,否则this指向会出问题!

  • src\App.vue

    
    
    
    
    
    
  • src\components\School.vue

    
    
    
    
    
    
  • src\components\Student.vue

    
    
    
    
    
    

11. TodoList_自定义事件

  • src\App.vue

    
    
    
    
    
    
  • src\components\Header.vue

    
    
    
    
    
    
  • src\components\Footer.vue

    
    
    
    
    
    

12. 全局事件总线(GlobalEventBus)

  1. 一种组件间通信的方式,适用于任意组件间通信。

  2. 安装全局事件总线:

    new Vue({
    	......
    	beforeCreate() {
    		Vue.prototype.$bus = this //安装全局事件总线,$bus就是当前应用的vm
    	},
        ......
    }) 
    
  3. 使用事件总线:

    1. 接收数据:A组件想接收数据,则在A组件中给$bus绑定自定义事件,事件的回调留在A组件自身。

      methods(){
        demo(data){......}
      }
      ......
      mounted() {
        this.$bus.$on('xxxx',this.demo)
      }
      
    2. 提供数据:this.$bus.$emit('xxxx',数据)

  4. 最好在beforeDestroy钩子中,用$off去解绑当前组件所用到的事件。

  • src\main.js

    /*
      该文件是整个项目的入口文件
    */
    // 引入Vue
    import Vue from 'vue'
    // 引入App组件,它是所有组件的父组件
    import App from './App.vue'
    // 关闭Vue的生产提示
    Vue.config.productionTip = false
    
    // 创建Vue实例对象——vm
    new Vue({
        el:'#app',
        render: h => h(App),
        beforeCreate(){
          // 测试在Vue原型上绑定数据,组件能否读取
          // Vue.prototype.x = 88
          // 安装全局事件总线
          Vue.prototype.$bus = this
        }
    })
    
  • src\App.vue

    
    
    
    
    
    
  • src\components\School.vue

    
    
    
    
    
    
  • src\components\Student.vue

    
    
    
    
    
    

13. TodoList_事件总线

  • src\App.vue

    
    
    
    
    
    
  • src\components\List.vue

    
    
    
    
    
    
  • src\components\Item.vue

    
    
    
    
    
    

14. 消息订阅与发布(pubsub)

  1. 一种组件间通信的方式,适用于任意组件间通信。

  2. 使用步骤:

    1. 安装pubsub:npm i pubsub-js

    2. 引入: import pubsub from 'pubsub-js'

    3. 接收数据:A组件想接收数据,则在A组件中订阅消息,订阅的回调留在A组件自身。

      methods(){
        demo(data){......}
      }
      ......
      mounted() {
        this.pid = pubsub.subscribe('xxx',this.demo) //订阅消息
      }
      
    4. 提供数据:pubsub.publish('xxx',数据)

    5. 最好在beforeDestroy钩子中,用PubSub.unsubscribe(pid)去取消订阅。

  • src\components\Student.vue

    
    
    
    
    
    
  • src\components\School.vue

    
    
    
    
    
    

15. TodoList_pubsub

  • src\components\Item.vue

    
    
    
    
    
    
  • src\App.vue

    
    
    
    
    
    

16. TodoList_nextTick

nextTick

  1. 语法:this.$nextTick(回调函数)
  2. 作用:在下一次 DOM 更新结束后执行其指定的回调。
  3. 什么时候用:当改变数据后,要基于更新后的新DOM进行某些操作时,要在nextTick所指定的回调函数中执行。
  • src\components\Item.vue

    
    
    
    
    
    
  • src\App.vue

    
    
    
    
    
    

17. Vue封装的过度与动画

  1. 作用:在插入、更新或移除 DOM元素时,在合适的时候给元素添加样式类名。

  2. 图示:

    [记录学习]自学尚硅谷张天禹Vue2+3框架_vue_test_第3张图片

  3. 写法:

    1. 准备好样式:

      • 元素进入的样式:
        1. v-enter:进入的起点
        2. v-enter-active:进入过程中
        3. v-enter-to:进入的终点
      • 元素离开的样式:
        1. v-leave:离开的起点
        2. v-leave-active:离开过程中
        3. v-leave-to:离开的终点
    2. 使用包裹要过度的元素,并配置name属性:

      
      	

      你好啊!

    3. 备注:若有多个元素需要过度,则需要使用:,且每个元素都要指定key值。

  4. 使用样式插件实现动画

    1. 安装animate.css

      npm install animate.css --save

    2. 增加标签属性

      
      
      
      • enter-active-class:进入动画class
      • leave-active-class:离开动画class
      • 可以从官网寻找需要的动画类型:https://animate.style/
    3. **官网基础用法:**在安装animation .css之后,将animate__animated类添加到一个元素中,同时添加任意一个动画名称(不要忘记animate__前缀!):

      <h1 class="animate__animated animate__bounce">An animated elementh1>
      
  • src\App.vue

    
    
    
    
    
    
  • src\components\Test.vue

    
    
    
    
    
    
  • src\components\Test2.vue

    
    
    
    
    
    
  • src\components\Test3.vue

    
    
    
    
    
    

18. TodoList_动画

  • src\components\List.vue

    
    
    
    
    
    

19. vue脚手架配置代理

  • 安装axios

    npm install vue-axios --save

方法一

  在vue.config.js中添加如下配置:
devServer:{
	proxy:"http://localhost:5000"
}

说明:

  1. 优点:配置简单,请求资源时直接发给前端(8080)即可。
  2. 缺点:不能配置多个代理,不能灵活的控制请求是否走代理。
  3. 工作方式:若按照上述配置代理,当请求了前端不存在的资源时,那么该请求会转发给服务器 (优先匹配前端资源)

方法二

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

说明:

  1. 优点:可以配置多个代理,且可以灵活的控制请求是否走代理。
  2. 缺点:配置略微繁琐,请求资源时必须加前缀。
  • vue.config.js

    const { defineConfig } = require('@vue/cli-service')
    module.exports = defineConfig({
      transpileDependencies: true,
      // 关闭语法检查
      lintOnSave: false,
      // 开启代理服务器(方法一)
      // devServer: {
      //   proxy: 'http://localhost:5000'
      // }
      // 开启代理服务器(方法二)
      devServer: {
        proxy: {
          '/atguigu': {
            target: 'http://localhost:5000',
            pathRewrite: {
              '^/atguigu':'',
              // // 用于支持websocket
              // ws: true,
              // // 用于控制请求头中的host值
              // changeOrigin: true
            }
          },
          '/demo': {
            target: 'http://localhost:5001',
            pathRewrite: {
              '^/demo': '',
              // // 用于支持websocket
              // ws: true,
              // // 用于控制请求头中的host值
              // changeOrigin: true
            }
          }
        }
      }
    })
    
  • src\App.vue

    
    
    
    
    
    

20. GitHub搜索案例

  • src\App.vue

    
    
    
    
    
    
  • src\components\SearchList.vue

    
    
    
    
    
    
  • src\components\SearchBox.vue

    
    
    
    
    
    

21. GitHub搜索案例_vue-resource

  • vue-resource作用与用法和axios相同,vue1.0中常用,了解即可,现在已经很少用了

  • 使用该插件后,vc中会多一个$http,用法和axios相同

    [记录学习]自学尚硅谷张天禹Vue2+3框架_vue_test_第4张图片

  • src\main.js

    /*
      该文件是整个项目的入口文件
    */
    // 引入Vue
    import Vue from 'vue'
    // 引入App组件,它是所有组件的父组件
    import App from './App.vue'
    // 引入vue-resource插件
    import vueResource from 'vue-resource'
    // 关闭Vue的生产提示
    Vue.config.productionTip = false
    
    // 使用vue-resource
    Vue.use(vueResource)
    
    // 创建Vue实例对象——vm
    new Vue({
        el:'#app',
        render: h => h(App),
        beforeCreate(){
          // 安装全局事件总线
          Vue.prototype.$bus = this
        }
    })
    
  • src\components\SearchBox.vue

    
    
    
    
    
    

22. 插槽

  1. 作用:让父组件可以向子组件指定位置插入html结构,也是一种组件间通信的方式,适用于 父组件 ===> 子组件

  2. 分类:默认插槽、具名插槽、作用域插槽

  3. 使用方式:

    1. 默认插槽:

      父组件中:
              
                 
      html结构1
      子组件中:
    2. 具名插槽:

      父组件中:
              
                  
      
                  
              
      子组件中:
              
      
    3. 作用域插槽:

      1. 理解:数据在组件的自身,但根据数据生成的结构需要组件的使用者来决定。(games数据在Category组件中,但使用数据所遍历出来的结构由App组件决定)

      2. 具体编码:

        父组件中:
        		
        			
        		
        
        		
        			
        		
        子组件中:
                
        
                
        

默认插槽

  • src\components\Category.vue

    <
    
    
    
    
    
  • src\App.vue

    
    
    
    
    

具名插槽

  • src\components\Category.vue

    <
    
    
    
    
    
  • src\App.vue

    
    
    
    
    

作用域插槽

  • src\components\Category.vue

    <
    
    
    
    
    
  • src\App.vue

    
    
    
    
    

23. 求和案例_纯vue版

  • src\App.vue

    
    
    
    
    
    
  • src\components\Count.vue

    <
    
    
    
    
    

Vuex

1.概念

在Vue中实现集中式状态(数据)管理的一个Vue插件,对vue应用中多个组件的共享状态进行集中式的管理(读/写),也是一种组件间通信的方式,且适用于任意组件间通信。

[记录学习]自学尚硅谷张天禹Vue2+3框架_vue_test_第5张图片

2.何时使用?

多个组件需要共享数据时

3.搭建vuex环境

  1. 安装vuex插件

    • vue默认vue3版本,vuex默认vuex4版本,vuex4只能在vue3中使用,

    • 在vue2中能使用vuex3,那么不能默认下载最新的版本

      npm install vuex@3 --save

  2. 创建文件: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
    })
    
  3. main.js中创建vm时传入store配置项

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

4.基本使用

  1. 初始化数据、配置actions、配置mutations,操作文件store.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. 组件中读取vuex中的数据:$store.state.sum

  3. 组件中修改vuex中的数据:$store.dispatch('action中的方法名',数据)$store.commit('mutations中的方法名',数据)

    备注:若没有网络请求或其他业务逻辑,组件中也可以越过actions,即不写dispatch,直接编写commit

24. 求和案例_vuex版

  • src\store\index.js

    // 该文件用于创建Vuex中最为核心的store
    
    // 引入Vue
    import Vue from 'vue'
    // 应用Vuex插件
    import Vuex from 'vuex'
    
    // 使用Vuex插件
    Vue.use(Vuex)
    
    // 准备actions——用于响应组件中的动作
    const actions = {
        // 由于没有进行多余操作,外界可以直接调用commit函数,使用mutations进行处理
        // jia(context, value){
        //     console.log('actions中的jia被调用了')
        //     context.commit('JIA', value)
        // },
        // jian(context, value){
        //     console.log('actions中的jian被调用了')
        //     context.commit('JIAN', value)
        // },
        jiaOdd(context, value){
            console.log('actions中的jiaOdd被调用了')
            if (context.state.sum % 2) {
                context.commit('JIA', value)
            }
        },
        jiaWait(context, value){
            console.log('actions中的jiaWait被调用了')
            setTimeout(()=>{
                context.commit('JIA', value)
            }, 1000)
        },
    }
    
    // 准备mutations——用于操作数据(state)
    const mutations = {
        JIA(state, value){
            console.log('mutations中的JIA被调用了')
            state.sum += value
        },
        JIAN(state, value){
            console.log('mutations中的JIAN被调用了')
            state.sum -= value
        },
    }
    
    // 准备state——用于存储数据
    const state = {
        // 当前的和
        sum:0
    }
    
    // 创建并暴露store
    export default new Vuex.Store({
        actions,
        mutations,
        state,
    })
    
    
  • src\main.js

    /*
      该文件是整个项目的入口文件
    */
    // 引入Vue
    import Vue from 'vue'
    // 引入App组件,它是所有组件的父组件
    import App from './App.vue'
    // 引入store
    import store from './store'
    // 关闭Vue的生产提示
    Vue.config.productionTip = false
    
    // 创建Vue实例对象——vm
    new Vue({
        el:'#app',
        render: h => h(App),
        store,
        beforeCreate(){
          // 安装全局事件总线
          Vue.prototype.$bus = this
        }
    })
    
  • src\App.vue

    
    
    
    
    
    
  • src\components\Count.vue

    <
    
    
    
    
    

5.getters的使用

  1. 概念:当state中的数据需要经过加工后再使用时,可以使用getters加工。

  2. store.js中追加getters配置

    ......
    
    const getters = {
    	bigSum(state){
    		return state.sum * 10
    	}
    }
    
    //创建并暴露store
    export default new Vuex.Store({
    	......
    	getters
    })
    
  3. 组件中读取数据:$store.getters.bigSum

25. 求和案例_getters

  • src\store\index.js

    // 该文件用于创建Vuex中最为核心的store
    
    // 引入Vue
    import Vue from 'vue'
    // 应用Vuex插件
    import Vuex from 'vuex'
    
    // 使用Vuex插件
    Vue.use(Vuex)
    
    // 准备actions——用于响应组件中的动作
    const actions = {
        // 由于没有进行多余操作,外界可以直接调用commit函数,使用mutations进行处理
        // jia(context, value){
        //     console.log('actions中的jia被调用了')
        //     context.commit('JIA', value)
        // },
        // jian(context, value){
        //     console.log('actions中的jian被调用了')
        //     context.commit('JIAN', value)
        // },
        jiaOdd(context, value){
            console.log('actions中的jiaOdd被调用了')
            if (context.state.sum % 2) {
                context.commit('JIA', value)
            }
        },
        jiaWait(context, value){
            console.log('actions中的jiaWait被调用了')
            setTimeout(()=>{
                context.commit('JIA', value)
            }, 1000)
        },
    }
    
    // 准备mutations——用于操作数据(state)
    const mutations = {
        JIA(state, value){
            console.log('mutations中的JIA被调用了')
            state.sum += value
        },
        JIAN(state, value){
            console.log('mutations中的JIAN被调用了')
            state.sum -= value
        },
    }
    
    // 准备state——用于存储数据
    const state = {
        // 当前的和
        sum:0
    }
    
    // 准备getters——用于将state中的数据进行加工
    const getters = {
        bigSum(state){
            return state.sum * 10
        }
    }
    
    // 创建并暴露store
    export default new Vuex.Store({
        actions,
        mutations,
        state,
        getters,
    })
    
  • src\components\Count.vue

    <
    
    
    
    
    

6.四个map方法的使用

  1. mapState方法:用于帮助我们映射state中的数据为计算属性

    computed: {
        //借助mapState生成计算属性:sum、school、subject(对象写法)
         ...mapState({sum:'sum',school:'school',subject:'subject'}),
    
        //借助mapState生成计算属性:sum、school、subject(数组写法)
        ...mapState(['sum','school','subject']),
    },
    
  2. mapGetters方法:用于帮助我们映射getters中的数据为计算属性

    computed: {
        //借助mapGetters生成计算属性:bigSum(对象写法)
        ...mapGetters({bigSum:'bigSum'}),
    
        //借助mapGetters生成计算属性:bigSum(数组写法)
        ...mapGetters(['bigSum'])
    },
    
  3. mapActions方法:用于帮助我们生成与actions对话的方法,即:包含$store.dispatch(xxx)的函数

    methods:{
        //靠mapActions生成:incrementOdd、incrementWait(对象形式)
        ...mapActions({incrementOdd:'jiaOdd',incrementWait:'jiaWait'})
    
        //靠mapActions生成:incrementOdd、incrementWait(数组形式)
        ...mapActions(['jiaOdd','jiaWait'])
    }
    
  4. mapMutations方法:用于帮助我们生成与mutations对话的方法,即:包含$store.commit(xxx)的函数

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

备注:mapActions与mapMutations使用时,若需要传递参数需要:在模板中绑定事件时传递好参数,否则参数是事件对象。

注意:加上 … 的意思是把对象展开

26. 求和案例_mapState与mapGetters

  • src\store\index.js

    // 该文件用于创建Vuex中最为核心的store
    
    // 引入Vue
    import Vue from 'vue'
    // 应用Vuex插件
    import Vuex from 'vuex'
    
    // 使用Vuex插件
    Vue.use(Vuex)
    
    // 准备actions——用于响应组件中的动作
    const actions = {
        // 由于没有进行多余操作,外界可以直接调用commit函数,使用mutations进行处理
        // jia(context, value){
        //     console.log('actions中的jia被调用了')
        //     context.commit('JIA', value)
        // },
        // jian(context, value){
        //     console.log('actions中的jian被调用了')
        //     context.commit('JIAN', value)
        // },
        jiaOdd(context, value){
            console.log('actions中的jiaOdd被调用了')
            if (context.state.sum % 2) {
                context.commit('JIA', value)
            }
        },
        jiaWait(context, value){
            console.log('actions中的jiaWait被调用了')
            setTimeout(()=>{
                context.commit('JIA', value)
            }, 1000)
        },
    }
    
    // 准备mutations——用于操作数据(state)
    const mutations = {
        JIA(state, value){
            console.log('mutations中的JIA被调用了')
            state.sum += value
        },
        JIAN(state, value){
            console.log('mutations中的JIAN被调用了')
            state.sum -= value
        },
    }
    
    // 准备state——用于存储数据
    const state = {
        // 当前的和
        sum:0,
        school:'尚硅谷',
        subject:'前端'
    }
    
    // 准备getters——用于将state中的数据进行加工
    const getters = {
        bigSum(state){
            return state.sum * 10
        }
    }
    
    // 创建并暴露store
    export default new Vuex.Store({
        actions,
        mutations,
        state,
        getters,
    })
    
  • src\components\Count.vue

    <
    
    
    
    
    

27. 求和案例_mapMutations与mapActions

  • src\components\Count.vue

    <
    
    
    
    
    

28. 求和案例_多组件共享数据

  • src\store\index.js

    // 该文件用于创建Vuex中最为核心的store
    
    // 引入Vue
    import Vue from 'vue'
    // 应用Vuex插件
    import Vuex from 'vuex'
    
    // 使用Vuex插件
    Vue.use(Vuex)
    
    // 准备actions——用于响应组件中的动作
    const actions = {
        // 由于没有进行多余操作,外界可以直接调用commit函数,使用mutations进行处理
        // jia(context, value){
        //     console.log('actions中的jia被调用了')
        //     context.commit('JIA', value)
        // },
        // jian(context, value){
        //     console.log('actions中的jian被调用了')
        //     context.commit('JIAN', value)
        // },
        jiaOdd(context, value){
            console.log('actions中的jiaOdd被调用了')
            if (context.state.sum % 2) {
                context.commit('JIA', value)
            }
        },
        jiaWait(context, value){
            console.log('actions中的jiaWait被调用了')
            setTimeout(()=>{
                context.commit('JIA', value)
            }, 1000)
        },
    }
    
    // 准备mutations——用于操作数据(state)
    const mutations = {
        JIA(state, value){
            console.log('mutations中的JIA被调用了')
            state.sum += value
        },
        JIAN(state, value){
            console.log('mutations中的JIAN被调用了')
            state.sum -= value
        },
    
        ADD_PERSON(state, value){
            console.log('mutations中的ADD_PERSON被调用了')
            state.personList.unshift(value)
        }
    }
    
    // 准备state——用于存储数据
    const state = {
        // 当前的和
        sum:0,
        school:'尚硅谷',
        subject:'前端',
        personList:[
            {id:'001', name:'张三'}
        ]
    }
    
    // 准备getters——用于将state中的数据进行加工
    const getters = {
        bigSum(state){
            return state.sum * 10
        }
    }
    
    // 创建并暴露store
    export default new Vuex.Store({
        actions,
        mutations,
        state,
        getters,
    })
    
  • src\App.vue

    
    
    
    
    
    
  • src\components\Count.vue

    <
    
    
    
    
    
  • src\components\Person.vue

    <
    
    
    
    
    

7.模块化+命名空间

  1. 目的:让代码更好维护,让多种数据分类更加明确。

  2. 修改store.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. 开启命名空间后,组件中读取state数据:

    //方式一:自己直接读取
    this.$store.state.personAbout.list
    //方式二:借助mapState读取:
    ...mapState('countAbout',['sum','school','subject']),
    
  4. 开启命名空间后,组件中读取getters数据:

    //方式一:自己直接读取
    this.$store.getters['personAbout/firstPersonName']
    //方式二:借助mapGetters读取:
    ...mapGetters('countAbout',['bigSum'])
    
  5. 开启命名空间后,组件中调用dispatch

    //方式一:自己直接dispatch
    this.$store.dispatch('personAbout/addPersonWang',person)
    //方式二:借助mapActions:
    ...mapActions('countAbout',{incrementOdd:'jiaOdd',incrementWait:'jiaWait'})
    
  6. 开启命名空间后,组件中调用commit

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

29. 求和案例_vuex模板化编码

  • src\store\count.js

    // 求和相关配置
    export default {
        namespaced: true,
        actions: {
            jiaOdd(context, value){
                console.log('actions中的jiaOdd被调用了')
                if (context.state.sum % 2) {
                    context.commit('JIA', value)
                }
            },
            jiaWait(context, value){
                console.log('actions中的jiaWait被调用了')
                setTimeout(()=>{
                    context.commit('JIA', value)
                }, 1000)
            },
        },
        mutations: {
            JIA(state, value){
                console.log('mutations中的JIA被调用了')
                state.sum += value
            },
            JIAN(state, value){
                console.log('mutations中的JIAN被调用了')
                state.sum -= value
            },
        
            ADD_PERSON(state, value){
                console.log('mutations中的ADD_PERSON被调用了')
                state.personList.unshift(value)
            }
        },
        state: {
            // 当前的和
            sum:0,
            school:'尚硅谷',
            subject:'前端',
        },
        getters: {
            bigSum(state){
                return state.sum * 10
            }
        }
    }
    
  • src\store\person.js

    // 人员管理相关配置
    import axios from 'axios'
    import { nanoid } from "nanoid";
    export default {
        namespaced: true,
        actions: {
            addPersonWang(context, value){
                if (value.name.indexOf('王') === 0) {
                    context.commit('ADD_PERSON', value)
                }else {
                    alert('添加的人必须姓王!')
                }
            },
            addPersonServer(context){
                axios.get('https://api.uixsj.cn/hitokoto/get?type=social').then(
                    response => {
                        context.commit('ADD_PERSON', {id:nanoid(), name:response.data})
                    },
                    error => {
                        alert(error.message)
                    }
                )
            }
        },
        mutations: {
            ADD_PERSON(state, value){
                console.log('mutations中的ADD_PERSON被调用了')
                state.personList.unshift(value)
            }
        },
        state: {
            personList:[
                {id:'001', name:'张三'}
            ]
        },
        getters:{
            firstPersonName(state){
                return state.personList[0].name
            }
        }
    }
    
  • src\store\index.js

    // 该文件用于创建Vuex中最为核心的store
    
    // 引入Vue
    import Vue from 'vue'
    // 应用Vuex插件
    import Vuex from 'vuex'
    // 导入模块化配置
    import countOptions from './count'
    import personOptions from './person'
    
    // 使用Vuex插件
    Vue.use(Vuex)
    
    // 创建并暴露store
    export default new Vuex.Store({
        modules:{
            countAbout: countOptions,
            personAbout: personOptions,
        }
    })
    
  • src\components\Count.vue

    <
    
    
    
    
    
  • src\components\Person.vue

    <
    
    
    
    
    

路由

1.基本使用

  1. 安装vue-router,vue2的版本只能和vue-router 3.x使用,vue-router 4.x和vue3使用,如果安装vue-router不标注版本的话,会默认安装vue-router 4.x的版本。命令:npm i vue-router@3

  2. 应用插件:Vue.use(VueRouter)

  3. 编写router配置项:

    //引入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. 实现切换(active-class可配置高亮样式)

    About
    
  5. 指定展示位置

    
    

30. 路由的基本使用

  • public\index.html(bootstrap.css样式就是在这里添加)

    DOCTYPE html>
    <html lang="">
      <head>
        <meta charset="utf-8">
    		
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
    		
        <meta name="viewport" content="width=device-width,initial-scale=1.0">
    		
        <link rel="icon" href="<%= BASE_URL %>favicon.ico">
    		
    		<link rel="stylesheet" href="<%= BASE_URL %>css/bootstrap.css">
    		
        <title>硅谷系统title>
      head>
      <body>
    		
        <noscript>
          <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.strong>
        noscript>
    		
        <div id="app">div>
        
      body>
    html>
    
  • src\router\index.js

    // 该文件专门用于创建整个应用的路由器
    import VueRouter from 'vue-router'
    //引入组件
    import About from '../components/About'
    import Home from '../components/Home'
    
    //创建并暴露一个路由器
    export default new VueRouter({
    	routes:[
    		{
    			path:'/about',
    			component:About
    		},
    		{
    			path:'/home',
    			component:Home
    		}
    	]
    })
    
  • src\main.js

    /*
      该文件是整个项目的入口文件
    */
    // 引入Vue
    import Vue from 'vue'
    // 引入App组件,它是所有组件的父组件
    import App from './App.vue'
    // 引入VueRouter
    import VueRouter from 'vue-router'
    // 引入路由器
    import router from './router'
    // 关闭Vue的生产提示
    Vue.config.productionTip = false
    
    Vue.use(VueRouter)
    
    // 创建Vue实例对象——vm
    new Vue({
        el:'#app',
        render: h => h(App),
        router:router
    })
    
  • src\components\About.vue

    
    
    
    
    
    
  • src\components\Home.vue

    
    
    
    
    
    
  • src\App.vue

    
    
    
    
    
    

2.几个注意点

  1. 路由组件通常存放在pages文件夹,一般组件通常存放在components文件夹。
  2. 通过切换,“隐藏”了的路由组件,默认是被销毁掉的,需要的时候再去挂载。
  3. 每个组件都有自己的$route属性,里面存储着自己的路由信息。
  4. 整个应用只有一个router,可以通过组件的$router属性获取到。

3.多级路由(多级路由)

  1. 配置路由规则,使用children配置项:

    routes:[
    	{
    		path:'/about',
    		component:About,
    	},
    	{
    		path:'/home',
    		component:Home,
    		children:[ //通过children配置子级路由
    			{
    				path:'news', //此处一定不要写:/news
    				component:News
    			},
    			{
    				path:'message',//此处一定不要写:/message
    				component:Message
    			}
    		]
    	}
    ]
    
  2. 跳转(要写完整路径):

    News
    

31. 多级路由

  • src\components\Banner.vue(将标题部分拆分到Banner.vue中)

    
    
    
    
    
    
  • src\pages\News.vue

    
    
    
    
    
    
  • src\pages\Message.vue

    
    
    
    
    
    
  • src\pages\Home.vue

    
    
    
    
    
    
  • src\router\index.js

    // 该文件专门用于创建整个应用的路由器
    import VueRouter from 'vue-router'
    //引入组件
    import About from '../pages/About'
    import Home from '../pages/Home'
    import News from '../pages/News'
    import Message from '../pages/Message'
    
    //创建并暴露一个路由器
    export default new VueRouter({
    	routes:[
    		{
    			path:'/about',
    			component:About
    		},
    		{
    			path:'/home',
    			component:Home,
                //通过children配置子级路由
                children:[
                    {
                        //此处一定不要写:/news
                        path:'news',
                        component:News
                    },
                    {
                        //此处一定不要写:/message
                        path:'message',
                        component:Message
                    },
                ]
    		}
    	]
    })
    

4.路由的query参数

  1. 传递参数

    
    跳转
    
    
    跳转
    
  2. 接收参数:

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

32. 路由的query参数

  • src\pages\Detail.vue

    
    
    
    
    
    
  • src\pages\Message.vue

    
    
    
    
    
    
  • src\router\index.js

    // 该文件专门用于创建整个应用的路由器
    import VueRouter from 'vue-router'
    //引入组件
    import About from '../pages/About'
    import Home from '../pages/Home'
    import News from '../pages/News'
    import Message from '../pages/Message'
    import Detail from '../pages/Detail'
    
    //创建并暴露一个路由器
    export default new VueRouter({
    	routes:[
    		{
    			path:'/about',
    			component:About
    		},
    		{
    			path:'/home',
    			component:Home,
                //通过children配置子级路由
                children:[
                    {
                        //此处一定不要写:/news
                        path:'news',
                        component:News
                    },
                    {
                        //此处一定不要写:/message
                        path:'message',
                        component:Message,
                        children:[
                            {
                                path:'detail',
                                component:Detail
                            },
                        ]
                    },
                ]
    		}
    	]
    })
    

5.命名路由

  1. 作用:可以简化路由的跳转。

  2. 如何使用

    1. 给路由命名:

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

      
      跳转
      
      
      跳转
      
      
      跳转
      

33. 命名路由

  • src\pages\Message.vue

    
    
    
    
    
    
  • src\router\index.js

    // 该文件专门用于创建整个应用的路由器
    import VueRouter from 'vue-router'
    //引入组件
    import About from '../pages/About'
    import Home from '../pages/Home'
    import News from '../pages/News'
    import Message from '../pages/Message'
    import Detail from '../pages/Detail'
    
    //创建并暴露一个路由器
    export default new VueRouter({
    	routes:[
    		{
                name:'guanyu',
    			path:'/about',
    			component:About
    		},
    		{
    			path:'/home',
    			component:Home,
                //通过children配置子级路由
                children:[
                    {
                        //此处一定不要写:/news
                        path:'news',
                        component:News
                    },
                    {
                        //此处一定不要写:/message
                        path:'message',
                        component:Message,
                        children:[
                            {
                                // 命名路由
                                name:'xiangqing',
                                path:'detail',
                                component:Detail
                            },
                        ]
                    },
                ]
    		}
    	]
    })
    

6.路由的params参数

  1. 配置路由,声明接收params参数

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

    
    跳转
    
    
    跳转
    

    特别注意:路由携带params参数时,若使用to的对象写法,则不能使用path配置项,必须使用name配置!

  3. 接收参数:

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

34. 路由的params参数

  • src\router\index.js

    // 该文件专门用于创建整个应用的路由器
    import VueRouter from 'vue-router'
    //引入组件
    import About from '../pages/About'
    import Home from '../pages/Home'
    import News from '../pages/News'
    import Message from '../pages/Message'
    import Detail from '../pages/Detail'
    
    //创建并暴露一个路由器
    export default new VueRouter({
    	routes:[
    		{
                name:'guanyu',
    			path:'/about',
    			component:About
    		},
    		{
    			path:'/home',
    			component:Home,
                //通过children配置子级路由
                children:[
                    {
                        //此处一定不要写:/news
                        path:'news',
                        component:News
                    },
                    {
                        //此处一定不要写:/message
                        path:'message',
                        component:Message,
                        children:[
                            {
                                // 命名路由
                                name:'xiangqing',
                                // 使用占位符声明接收params参数
                                path:'detail/:id/:title',
                                component:Detail
                            },
                        ]
                    },
                ]
    		}
    	]
    })
    
  • src\pages\Message.vue

    
    
    
    
    
    
  • src\pages\Detail.vue

    
    
    
    
    
    

7.路由的props配置

作用:让路由组件更方便的收到参数

{
	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
		}
	}
}

35. 路由的props配置

  • src\router\index.js

    // 该文件专门用于创建整个应用的路由器
    import VueRouter from 'vue-router'
    //引入组件
    import About from '../pages/About'
    import Home from '../pages/Home'
    import News from '../pages/News'
    import Message from '../pages/Message'
    import Detail from '../pages/Detail'
    
    //创建并暴露一个路由器
    export default new VueRouter({
    	routes:[
    		{
                name:'guanyu',
    			path:'/about',
    			component:About
    		},
    		{
    			path:'/home',
    			component:Home,
                //通过children配置子级路由
                children:[
                    {
                        //此处一定不要写:/news
                        path:'news',
                        component:News
                    },
                    {
                        //此处一定不要写:/message
                        path:'message',
                        component:Message,
                        children:[
                            {
                                // 命名路由
                                name:'xiangqing',
                                path:'detail',
                                // 使用占位符声明接收params参数
                                // path:'detail/:id/:title',
                                component:Detail,
    
                                // props的第一种写法,值为对象,该对象中的所有key-value都会以props的形式传给Detail组件
                                // props:{a:1, b:'hello'}
                                
                                // props的第二种写法,值为布尔值,若布尔值为真,就会把该路由组件收到的所有params参数(path记得使用占位符声明接收params参数),以props的形式传给Detail组件
                                // props:true
    
                                // props的第三种写法,值为函数
                                props($route){
                                    return {
                                        id:$route.query.id,
                                        title:$route.query.title,
                                        a:1,
                                        b:'hello'
                                    }
                                }
    
                            },
                        ]
                    },
                ]
    		}
    	]
    })
    
  • src\pages\Message.vue

    
    
    
    
    
    
  • src\pages\Detail.vue

    
    
    
    
    
    

8.的replace属性

  1. 作用:控制路由跳转时操作浏览器历史记录的模式
  2. 浏览器的历史记录有两种写入方式:分别为pushreplacepush是追加历史记录,replace是替换当前记录。路由跳转时候默认为push
  3. 如何开启replace模式:News

36. 的replace属性

  • src\pages\Home.vue

    
    
    
    
    
    

9.编程式路由导航

  1. 作用:不借助 实现路由跳转,让路由跳转更加灵活

  2. 具体编码:

    //$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() //可前进也可后退
    

37. 编程式路由导航

  • src\components\Banner.vue

    
    
    
    
    
    
  • src\pages\Message.vue

    
    
    
    
    
    

10.缓存路由组件

  1. 作用:让不展示的路由组件保持挂载,不被销毁。

  2. 具体编码:

     
        
    
    

38. 缓存路由组件

  • src\pages\News.vue

    
    
    
    
    
    
  • src\pages\Message.vue

    
    
    
    
    
    
  • src\pages\Home.vue

    
    
    
    
    
    

11.两个新的生命周期钩子

  1. 作用:路由组件所独有的两个钩子,用于捕获路由组件的激活状态。
  2. 具体名字:
    1. activated路由组件被激活时触发。
    2. deactivated路由组件失活时触发。

39. 两个新的生命周期钩子

  • src\pages\News.vue

    
    
    
    
    
    

12.路由守卫

  1. 作用:对路由进行权限控制

  2. 分类:全局守卫、独享守卫、组件内守卫

  3. 全局守卫:

    //全局前置守卫:初始化时执行、每次路由切换前执行
    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. 独享守卫:(在一个路由内部单独写一个守卫)

    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. 组件内守卫:

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

40. 全局路由守卫

  • src\router\index.js

    // 该文件专门用于创建整个应用的路由器
    import VueRouter from 'vue-router'
    //引入组件
    import About from '../pages/About'
    import Home from '../pages/Home'
    import News from '../pages/News'
    import Message from '../pages/Message'
    import Detail from '../pages/Detail'
    
    //创建并暴露一个路由器
    const router =  new VueRouter({
    	routes:[
    		{
                name:'guanyu',
    			path:'/about',
    			component:About,
                meta:{title:'关于'}
    		},
    		{
                name:'zhuye',
    			path:'/home',
    			component:Home,
                meta:{title:'主页'},
                //通过children配置子级路由
                children:[
                    {
                        //此处一定不要写:/news
                        name:'xinwen',
                        path:'news',
                        component:News,
                        meta:{isAuth:true, title:'新闻'}
                    },
                    {
                        //此处一定不要写:/message
                        path:'message',
                        component:Message,
                        meta:{isAuth:true, title:'消息'},
                        children:[
                            {
                                // 命名路由
                                name:'xiangqing',
                                path:'detail',
                                // 使用占位符声明接收params参数
                                // path:'detail/:id/:title',
                                component:Detail,
                                meta:{isAuth:true, title:'详情'},
    
                                // props的第一种写法,值为对象,该对象中的所有key-value都会以props的形式传给Detail组件
                                // props:{a:1, b:'hello'}
                                
                                // props的第二种写法,值为布尔值,若布尔值为真,就会把该路由组件收到的所有params参数(path记得使用占位符声明接收params参数),以props的形式传给Detail组件
                                // props:true
    
                                // props的第三种写法,值为函数
                                props($route){
                                    return {
                                        id:$route.query.id,
                                        title:$route.query.title,
                                        a:1,
                                        b:'hello'
                                    }
                                }
    
                            },
                        ]
                    },
                ]
    		}
    	]
    })
    
    // 全局前置路由守卫————初始化的时候被调用,每次路由切换之前被调用
    router.beforeEach((to, from, next)=>{
        console.log('前置路由守卫',to,from)
        // 判断是否需要鉴权
        if (to.meta.isAuth) {
            if (localStorage.getItem('school') === 'atguigu') {
                next()
            }else {
                alert('学校名不对,无权限查看!')
            }
        }else {
            next()
        }
    })
    
    // 全局后置路由守卫————初始化的时候被调用,每次切换路由后被调用
    router.afterEach((to, from)=>{
        console.log('后置路由守卫',to,from)
        document.title = to.meta.title || '硅谷系统'
    })
    
    export default router
    

41. 独享路由守卫

  • src\router\index.js

    // 该文件专门用于创建整个应用的路由器
    import VueRouter from 'vue-router'
    //引入组件
    import About from '../pages/About'
    import Home from '../pages/Home'
    import News from '../pages/News'
    import Message from '../pages/Message'
    import Detail from '../pages/Detail'
    
    //创建并暴露一个路由器
    const router =  new VueRouter({
    	routes:[
    		{
    			name:'guanyu',
    			path:'/about',
    			component:About,
    			meta:{title:'关于'}
    		},
    		{
    			name:'zhuye',
    			path:'/home',
    			component:Home,
    			meta:{title:'主页'},
    			children:[
    				{
    					name:'xinwen',
    					path:'news',
    					component:News,
    					meta:{isAuth:true,title:'新闻'},
    					beforeEnter: (to, from, next) => {
    						console.log('独享路由守卫',to,from)
    						if(to.meta.isAuth){ //判断是否需要鉴权
    							if(localStorage.getItem('school')==='atguigu'){
    								next()
    							}else{
    								alert('学校名不对,无权限查看!')
    							}
    						}else{
    							next()
    						}
    					}
    				},
    				{
    					name:'xiaoxi',
    					path:'message',
    					component:Message,
    					meta:{isAuth:true,title:'消息'},
    					children:[
    						{
    							name:'xiangqing',
    							path:'detail',
    							component:Detail,
    							meta:{isAuth:true,title:'详情'},
    
    							//props的第一种写法,值为对象,该对象中的所有key-value都会以props的形式传给Detail组件。
    							// props:{a:1,b:'hello'}
    
    							//props的第二种写法,值为布尔值,若布尔值为真,就会把该路由组件收到的所有params参数,以props的形式传给Detail组件。
    							// props:true
    
    							//props的第三种写法,值为函数
    							props($route){
    								return {
    									id:$route.query.id,
    									title:$route.query.title,
    									a:1,
    									b:'hello'
    								}
    							}
    
    						}
    					]
    				}
    			]
    		}
    	]
    })
    
    //全局前置路由守卫————初始化的时候被调用、每次路由切换之前被调用
    /* router.beforeEach((to,from,next)=>{
    	console.log('前置路由守卫',to,from)
    	if(to.meta.isAuth){ //判断是否需要鉴权
    		if(localStorage.getItem('school')==='atguigu'){
    			next()
    		}else{
    			alert('学校名不对,无权限查看!')
    		}
    	}else{
    		next()
    	}
    }) */
    
    //全局后置路由守卫————初始化的时候被调用、每次路由切换之后被调用
    router.afterEach((to,from)=>{
    	console.log('后置路由守卫',to,from)
    	document.title = to.meta.title || '硅谷系统'
    })
    
    export default router
    

42. 组件内路由守卫

  • src\router\index.js

    // 该文件专门用于创建整个应用的路由器
    import VueRouter from 'vue-router'
    //引入组件
    import About from '../pages/About'
    import Home from '../pages/Home'
    import News from '../pages/News'
    import Message from '../pages/Message'
    import Detail from '../pages/Detail'
    
    //创建并暴露一个路由器
    const router =  new VueRouter({
    	routes:[
    		{
                name:'guanyu',
    			path:'/about',
    			component:About,
                meta:{isAuth:true, title:'关于'}
    		},
    		{
                name:'zhuye',
    			path:'/home',
    			component:Home,
                meta:{title:'主页'},
                //通过children配置子级路由
                children:[
                    {
                        //此处一定不要写:/news
                        name:'xinwen',
                        path:'news',
                        component:News,
                        meta:{isAuth:true, title:'新闻'},
                        // 独享路由守卫
                        beforeEnter:(to, from, next)=>{
                            console.log('独享路由守卫',to,from)
                            // 判断是否需要鉴权
                            if (to.meta.isAuth) {
                                if (localStorage.getItem('school') === 'atguigu') {
                                    next()
                                }else {
                                    alert('学校名不对,无权限查看!')
                                }
                            }else {
                                next()
                            }
                        }
                    },
                    {
                        //此处一定不要写:/message
                        path:'message',
                        component:Message,
                        meta:{isAuth:true, title:'消息'},
                        children:[
                            {
                                // 命名路由
                                name:'xiangqing',
                                path:'detail',
                                // 使用占位符声明接收params参数
                                // path:'detail/:id/:title',
                                component:Detail,
                                meta:{isAuth:true, title:'详情'},
    
                                // props的第一种写法,值为对象,该对象中的所有key-value都会以props的形式传给Detail组件
                                // props:{a:1, b:'hello'}
                                
                                // props的第二种写法,值为布尔值,若布尔值为真,就会把该路由组件收到的所有params参数(path记得使用占位符声明接收params参数),以props的形式传给Detail组件
                                // props:true
    
                                // props的第三种写法,值为函数
                                props($route){
                                    return {
                                        id:$route.query.id,
                                        title:$route.query.title,
                                        a:1,
                                        b:'hello'
                                    }
                                }
    
                            },
                        ]
                    },
                ]
    		}
    	]
    })
    
    // 全局前置路由守卫————初始化的时候被调用,每次路由切换之前被调用
    // router.beforeEach((to, from, next)=>{
    //     console.log('前置路由守卫',to,from)
    //     // 判断是否需要鉴权
    //     if (to.meta.isAuth) {
    //         if (localStorage.getItem('school') === 'atguigu') {
    //             next()
    //         }else {
    //             alert('学校名不对,无权限查看!')
    //         }
    //     }else {
    //         next()
    //     }
    // })
    
    // 全局后置路由守卫————初始化的时候被调用,每次切换路由后被调用
    router.afterEach((to, from)=>{
        console.log('后置路由守卫',to,from)
        document.title = to.meta.title || '硅谷系统'
    })
    
    export default router
    
  • src\pages\About.vue

    
    
    
    
    
    

13.路由器的两种工作模式

  1. 对于一个url来说,什么是hash值?—— #及其后面的内容就是hash值。
  2. hash值不会包含在 HTTP 请求中,即:hash值不会带给服务器。
  3. hash模式:
    1. 地址中永远带着#号,不美观 。
    2. 若以后将地址通过第三方手机app分享,若app校验严格,则地址会被标记为不合法。
    3. 兼容性较好。
  4. history模式:
    1. 地址干净,美观 。
    2. 兼容性和hash模式相比略差。
    3. 应用部署上线时需要后端人员支持,解决刷新页面服务端404的问题。

43. history模式与hash模式

  • src\router\index.js

    // 该文件专门用于创建整个应用的路由器
    import VueRouter from 'vue-router'
    //引入组件
    import About from '../pages/About'
    import Home from '../pages/Home'
    import News from '../pages/News'
    import Message from '../pages/Message'
    import Detail from '../pages/Detail'
    
    //创建并暴露一个路由器
    const router =  new VueRouter({
        // 默认为hash模式,修改为history模式
        mode:'history',
    	routes:[
    		{
                name:'guanyu',
    			path:'/about',
    			component:About,
                meta:{isAuth:true, title:'关于'}
    		},
    		{
                name:'zhuye',
    			path:'/home',
    			component:Home,
                meta:{title:'主页'},
                //通过children配置子级路由
                children:[
                    {
                        //此处一定不要写:/news
                        name:'xinwen',
                        path:'news',
                        component:News,
                        meta:{isAuth:true, title:'新闻'},
                        // 独享路由守卫
                        beforeEnter:(to, from, next)=>{
                            console.log('独享路由守卫',to,from)
                            // 判断是否需要鉴权
                            if (to.meta.isAuth) {
                                if (localStorage.getItem('school') === 'atguigu') {
                                    next()
                                }else {
                                    alert('学校名不对,无权限查看!')
                                }
                            }else {
                                next()
                            }
                        }
                    },
                    {
                        //此处一定不要写:/message
                        path:'message',
                        component:Message,
                        meta:{isAuth:true, title:'消息'},
                        children:[
                            {
                                // 命名路由
                                name:'xiangqing',
                                path:'detail',
                                // 使用占位符声明接收params参数
                                // path:'detail/:id/:title',
                                component:Detail,
                                meta:{isAuth:true, title:'详情'},
    
                                // props的第一种写法,值为对象,该对象中的所有key-value都会以props的形式传给Detail组件
                                // props:{a:1, b:'hello'}
                                
                                // props的第二种写法,值为布尔值,若布尔值为真,就会把该路由组件收到的所有params参数(path记得使用占位符声明接收params参数),以props的形式传给Detail组件
                                // props:true
    
                                // props的第三种写法,值为函数
                                props($route){
                                    return {
                                        id:$route.query.id,
                                        title:$route.query.title,
                                        a:1,
                                        b:'hello'
                                    }
                                }
    
                            },
                        ]
                    },
                ]
    		}
    	]
    })
    
    // 全局前置路由守卫————初始化的时候被调用,每次路由切换之前被调用
    // router.beforeEach((to, from, next)=>{
    //     console.log('前置路由守卫',to,from)
    //     // 判断是否需要鉴权
    //     if (to.meta.isAuth) {
    //         if (localStorage.getItem('school') === 'atguigu') {
    //             next()
    //         }else {
    //             alert('学校名不对,无权限查看!')
    //         }
    //     }else {
    //         next()
    //     }
    // })
    
    // 全局后置路由守卫————初始化的时候被调用,每次切换路由后被调用
    router.afterEach((to, from)=>{
        console.log('后置路由守卫',to,from)
        document.title = to.meta.title || '硅谷系统'
    })
    
    export default router
    

44. element-ui组件库

完整引入

  • 安装组件

    npm i element-ui -S

  • src\main.js

    /*
      该文件是整个项目的入口文件
    */
    // 引入Vue
    import Vue from 'vue'
    // 引入App组件,它是所有组件的父组件
    import App from './App.vue'
    
    // 完整引入
    // 引入ElementUI组件库
    import ElementUI from 'element-ui'
    // 引入ElementUI全部样式
    import 'element-ui/lib/theme-chalk/index.css'
    
    // 关闭Vue的生产提示
    Vue.config.productionTip = false
    
    // 应用ElementUI
    Vue.use(ElementUI)
    
    // 创建Vue实例对象——vm
    new Vue({
        el:'#app',
        render: h => h(App),
    })
    
  • src\App.vue

    
    
    
    
    
    

按需引入

  • 安装组件

    npm install babel-plugin-component -D

  • 修改文件babel.config.js为

    module.exports = {
      presets: [
        '@vue/cli-plugin-babel/preset',
        ["@babel/preset-env", { "modules": false }]
      ],
      "plugins": [
        [
          "component",
          {
            "libraryName": "element-ui",
            "styleLibraryName": "theme-chalk"
          }
        ]
      ]
    }
    
  • src\main.js

    /*
      该文件是整个项目的入口文件
    */
    // 引入Vue
    import Vue from 'vue'
    // 引入App组件,它是所有组件的父组件
    import App from './App.vue'
    
    // 完整引入
    // 引入ElementUI组件库
    // import ElementUI from 'element-ui'
    // 引入ElementUI全部样式
    // import 'element-ui/lib/theme-chalk/index.css'
    
    // 按需引入
    import { Button, Row, DatePicker } from 'element-ui';
    
    // 关闭Vue的生产提示
    Vue.config.productionTip = false
    
    // 应用ElementUI
    // Vue.use(ElementUI)
    Vue.component('atguigu-button', Button)
    Vue.component('atguigu-row', Row)
    Vue.component('atguigu-date-picker', DatePicker)
    
    // 创建Vue实例对象——vm
    new Vue({
        el:'#app',
        render: h => h(App),
    })
    
  • src\App.vue

    
    
    
    
    
    

你可能感兴趣的:(vue.js,学习,前端框架)