09_Vue2

1.初始容器

容器和组件是一对一的

<div id="root">
    <h1>姓名:{{name}}</h1>
    <h1>年龄:{{age}}</h1>
</div>
<script>
    //阻止生产提示
    Vue.config.productionTip = false;
    const x = new Vue({
        el: "#root",
        data: {
            name: "rokned",
            age: 18,
        },
    });
</script>

2.模板语法

在这里插入图片描述

<div id="root">
    <!-- 插值语法 -->
    <h1>姓名:{{name}}</h1>
    <h1>年龄:{{age}}</h1>
    <!-- 指令语法,可以简写成: -->
    <a v-bind:href="url">跳转b站</a>
    <a :href="url">跳转b站</a>
</div>
<script>
    Vue.config.productionTip = false;
    const x = new Vue({
        el: "#root",
        data: {
            name: "rokned",
            age: 18,
            url: "https://www.bilibili.com/",
        },
    });
</script>

3.数据绑定

v-model只支持表单类元素

<div id="root">
    <!-- 单向数据绑定 -->
    单向<input type="text" :value="name" />
    <hr />
    <!-- 双向数据绑定 可以简写成v-model=-->
    <!-- 双向<input type="text" v-model:value="name" /> -->
    双向<input type="text" v-model="name" />

</div>
<script>
    Vue.config.productionTip = false;
    const x = new Vue({
        el: "#root",
        data: {
            name: "数据绑定",
        },
    });
</script>

4.事件处理

在这里插入图片描述

事件修饰符写在事件后,例:@click.stop=“xxx”

<div id="root">
    <!-- 使用v-onxxx: ,缩写@xxx-->
    <!-- <button v-on:click="showinfo">点击提示信息</button> -->
    <button @click="showinfo">点击提示信息</button>
    <button @click="showinfo2(1)">点击提示信息</button>
</div>
<script>
    const vm = new Vue({
        el: "#root",
        methods: {
            showinfo(e) {
                console.log(e.target);
            },
            showinfo2(value) {
                console.log(value);
            },
        },
    });
</script>

5.键盘事件

在这里插入图片描述

在这里插入图片描述

6.计算属性

<div id="root">
    姓:<input type="text" v-model="fn" /><br />
    名:<input type="text" v-model="ln" /> <br />
    姓名:<span>{{fullname}}</span>
</div>
<script>
    const vm = new Vue({
        el: "#root",
        data() {
            return {
                fn: "rok",
                ln: "ned",
            };
        },
        computed: {
            // 完整写法
            // fullname: {
            //   get() {
            //     return this.fn + this.ln;
            //   },
            //   set(v) {
            //     console.log(v);
            //   },
            // },

            //简写,只有getter
            fullname(){ 
                return this.fn + this.ln;
            }
        },
    });
</script>

7.监视属性

watch可以开启异步任务,而computed不行

注:定时器要写成箭头函数,如果写成普通函数,this会指向window,因为箭头函数的this作用域在当前函数之下

**所以非Vue管理的函数最好写成箭头函数 **

<div id="root">
    姓:<input type="text" v-model="fn" /><br />
    名:<input type="text" v-model="ln" /> <br />
    姓名:<span>{{fullname}}</span>
    <hr />
    <span>{{number.a}}</span>
    <button @click="number.a++">a+1</button>
</div>
<script>
    const vm = new Vue({
        el: "#root",
        data() {
            return {
                fn: "rok",
                ln: "ned",
                number: {
                    a: 1,
                },
            };
        },
        computed: {
            fullname() {
                return this.fn + this.ln;
            },
        },
        watch: {
            //注:当只有handler函数时,可以简写
            fn(newValue, oldValue) {
                //一定要写成箭头函数,不然指向window
                setTimeout(() => {
                    console.log("改变了", newValue, oldValue);
                }, 1000);
            },

            //正常写法
            // fn: {
            //   immediate: true, //初始化调用一下handler
            //   handler(newValue, oldValue) {
            //     console.log("改变了", newValue, oldValue);
            //   },
            // },
            //深度监视,使多层次数据可以被发现
            number: {
                deep: true,
                handler() {
                    console.log("number改变了");
                },
            },
        },
    });
</script>

8.绑定class样式

在这里插入图片描述

在这里插入图片描述

<div id="root">
    <div :class="color"></div>
    <button @click="change" :style="StyObj">改变颜色</button>
</div>
<script>
    const vm = new Vue({
        el: "#root",
        data() {
            return {
                color: "T1",
                StyObj: {
                    fontSize: 50 + "px",
                    color: "orange",
                },
            };
        },
        methods: {
            change() {
                this.color == "T2" ? (this.color = "T1") : (this.color = "T2");
            },
        },
    });
</script>

9.V-指令

v-show,v-if

注:template只能和v-if使用,不能和v-show

<!-- v-show调整display,里面可以是一个表达式 -->
<h1 v-show="false">v-show</h1>
<!-- v-if调整结构,里面可以是一个表达式,v-else,v-else-if也可以使用 -->
<h1 v-if="false">v-if</h1>

v-for

<ul>
    <li v-for="p in persons" :key="p.id">{{p.name}}</li>
</ul>
<br>
<ul>
    <li v-for="(p,index) in persons" :key="index">{{index}}</li>
</ul>
data() {
    return {
        persons: [
            { id: "1", name: "张三" },
            { id: "2", name: "李四" },
            { id: "3", name: "王五" },
        ],
    };
},

key的作用(虚拟dom的对比)

在这里插入图片描述

在这里插入图片描述

Vue.set()

后期添加属性,第一个参数表示添加的对象,第二三个参数表示键值对

注:添加的对象不能是vm或根对象

在这里插入图片描述

在这里插入图片描述

v-text

作用与插值语法类似,无法解析标签

v-html

作用与v-text类似,不过可以解析标签

v-clock

在这里插入图片描述

在页面渲染完成时删除,配合css

在这里插入图片描述

v-once

在这里插入图片描述

在初次渲染后就称为静态

v-pre

跳过有v-pre的节点不进行解析

自定义指令

只要指令所在的模板重新解析时,就会调用

<div id="root">
    <h2>当前n</h2>
    <h2>放大十倍: <span v-big="n"></span></h2>
    <button @click="n++">点击n+1</button>
</div>
<script>
    const vm = new Vue({
        el: "#root",
        data() {
            return {
                n: 1,
            };
        },
        directives: {
            //   big(element, binding) {
            //     console.log(element, binding);
            //     element.innerText = binding.value * 10;
            //   },
            big: {
                bind(e, b) {
                    console.log("bind");
                },
                inserted(e, b) {
                    console.log("inserted");
                    e.innerText = b.value * 10;
                },
                update(e, b) {
                    console.log("update");
                    e.innerText = b.value * 10;
                },
            },
        },
        methods: {},
    });
</script>

10.过滤器

只能使用在插值语法和v-bind

在这里插入图片描述

将管道符前面作为参数传递给管道符后面,管道符后面的函数也可以带参数,但第一个参数是管道符前面那个,第二个参数才是括号内传递的

在这里插入图片描述

11.生命周期

在这里插入图片描述

在这里插入图片描述

12.组件

基本使用

注册全局组件:Vue.component(‘xxx’,xxx)

<div id="root">
    <!-- 编写组件标签 -->
    <school></school>
    <hr />
    <student></student>
</div>
<script>
    //创建组件
    const school = Vue.extend({
        template: `
<div>
<h2>学校名称{{Scname}}</h2>
<h2>学校地址{{Scadd}}</h2>
    </div>
`,
        data() {
            return {
                Scname: "nju",
                Scadd: "nj",
            };
        },
    });
    const student = Vue.extend({
        template: `
<div>
<h2>学生名称{{Sname}}</h2>
<h2>学生年龄{{Sage}}</h2>
    </div>
`,
        data() {
            return {
                Sname: "rokned",
                Sage: 18,
            };
        },
    });

    new Vue({
        el: "#root",
        //注册组件,局部注册
        components: {
            //左边是最终变量,右边只是一个中转变量
            school: school,
            student: student,
        },
    });
</script>

在这里插入图片描述

组件嵌套

<div id="root">
    <hr />
</div>
<script>
    //创建组件
    const student = Vue.extend({
        template: `
<div>
<h2>学生名称{{Sname}}</h2>
<h2>学生年龄{{Sage}}</h2>
    </div>
`,
        data() {
            return {
                Sname: "rokned",
                Sage: 18,
            };
        },
    });

    const school = Vue.extend({
        template: `
<div>
<h2>学校名称{{Scname}}</h2>
<h2>学校地址{{Scadd}}</h2>
<student></student>
    </div>
`,
        data() {
            return {
                Scname: "nju",
                Scadd: "nj",
            };
        },
        components: {
            student: student,
        },
    });
    const app = Vue.extend({
        template: `
<school></school>
`,
        components: {
            school,
        },
    });
    new Vue({
        el: "#root",
        template: ` <app></app>`,
        components: {
            app,
        },
    });
</script>

单文件组件

详细见代码

13.脚手架

脚手架代码笔记

将需要运行的代码笔记替换src文件夹

基本使用

new Vue({
    //将app组件放入容器
  render: h => h(App),
    //$mount('#app')等价于el:'#app'
}).$mount('#app')

在这里插入图片描述

ref属性

<template>
<div>
    <h1 v-text="msg" ref="title"></h1>
    <button @click="showDom">点击控制台输出</button>
    <demo ref="demo" id="demo"></demo>
    </div>
</template>
<script>
    methods: {
        showDom() {
            //非组件标签获得的是DOM
            console.log(this.$refs.title);
            //如果是组件标签则会获得vc组件
            console.log(this.$refs.demo);
            //如果使用原生获取则是DOM
            console.log(document.getElementById('demo'));
        },
    },
</script>

props配置

外部接收数据

外部传入优先级大于内部

如果外部传入数据之后还需要对其进行修改,需要在子模块data声明一个新的属性

子模块

<template>
<!-- 组件结构 -->
<div>
    <h1 class="demo">{{ NTest + 1 }}</h1>
    <button @click="change">点击修改</button>
    </div>
</template>
<script>
    export default {
        name: "demo", //一般和文件名相同
        // 简单接收
        props: ["Test"],

        //简单接收2
        // props: {
        //   //设置接收类型,如果数据类型不对会在控制台报错
        //   Test: Number,
        // },

        //完整接收
        // props: {
        //   Test: {
        //     type: Number,
        //     require: false,
        //     default: 99,
        //   },
        // },
        data() {
            return {
                NTest: this.Test,
            };
        },
        methods: {
            change() {
                //会进行报错警告
                // this.Test += 1;

                this.NTest += 1;
            },
        },
    };
</script>

app模块

<template>
<div>
    <h1 v-text="msg"></h1>
    <!-- 直接传递引号中字符串 -->
    <demo Test="18"></demo>
    <!-- 动态绑定相当于将引号中作为js执行 -->
    <demo :Test="18"></demo>
    <!-- 可以使用默认值进行配置 -->
    <!-- <demo></demo> -->
    </div>
</template>

mixin混入

组件共有配置可以写入混合,可以混合多个,使用分别暴露即可

混合优先级没有内部优先级高

main.js

//全局混合
import mixin from "./mixin";
Vue.mixin(mixin);

demo.vue

<script>
    //引入混合,局部引入
    // import mixin from "../mixin";

    export default {
        name: "demo", //一般和文件名相同
        data() {
            return {
                NTest: 100,
            };
        },
        // mixins: [mixin],
    };
</script>

demo2.vue

<script>
    //引入混合,局部引入
    // import mixin from "../mixin";
    export default {
        name: "demo2", //一般和文件名相同
        data() {
            return {
                NTest: 200,
            };
        },
        // mixins: [mixin],
    };
</script>

mixin.js(文件名随意)

export default {
    name: "mixin",
    methods: {
        change() {
            this.NTest += 1;
        },
    },
};

插件

//引入插件,可以带参数
import plguin from "./plugin";
Vue.use(plguin);

在这里插入图片描述

scoped

当组件样式冲突时,使用scoped,表示样式只负责此处的组件

在这里插入图片描述

自定义事件

父组件传递函数给子组件使用

三种方法,一种使用props一种使用v-on(自定义事件)还有一种使用ref

ref更加灵活

子组件

<template>
<div>
    <h1 class="demo">{{ NTest }}</h1>
    <button @click="sendname">发送名字</button>
    <br />
    <button @click="dotage">触发tage</button>
    </div>
</template>

<script>
    export default {
        name: "demo", //一般和文件名相同
        data() {
            return {
                NTest: 100,
                name: "rokned",
            };
        },
        methods: {
            sendname() {
                this.getname(this.name);
            },
            dotage() {
                //触发tage,可以传参
                this.$emit("tage");
            },
        },
        props: ["getname"],
    };
</script>

<style>
    .demo {
        color: aqua;
    }
</style>

父组件

<template>
<div>
    <h1 v-text="msg"></h1>
    <!-- 父组件传递函数给子组件,通过props实现 -->
    <demo :getname="getname"></demo>
    <!-- 绑定事件,在vc身上 -->
    <!-- <demo v-on:tage="tage"></demo> -->
    <!-- 通过ref标签 -->
    <demo ref="demo"></demo>
    </div>
</template>

<script>
    import demo from "./components/demo.vue";
    export default {
        name: "app",
        data() {
            return {
                msg: "this is a test",
            };
        },
        methods: {
            getname(name) {
                console.log(name);
            },
            tage() {//可以接收参数
                console.log("tage触发");
            },
        },
        components: {
            demo,
        },
        //从ref标签获取vc进行绑定
        mounted() {
            this.$refs.demo.$on("tage", this.tage);
        },
    };
</script>

<style></style>

解绑

解绑多个

在这里插入图片描述

全部解绑:this.$off()

unbind(){
    this.$off('tage')
}

解绑还可以直接进行销毁在这里插入图片描述

全局事件总线

收数据的组件绑定事件创建回调,发送数据的组件触发事件并将数据带入

在这里插入图片描述

demo.vue

<template>
<div>
    <h1 class="demo">{{ NTest }}</h1>
    </div>
</template>

<script>
    export default {
        name: "demo", //一般和文件名相同
        data() {
            return {
                NTest: 100,
                name: "rokned",
            };
        },
        mounted() {
            //挂载方法
            this.$bus.$on("hello", (data) => {
                console.log("demo1,参数:", data);
            });
        },
        // 销毁方法
        beforeDestroy() {
            this.$bus.$off("hello");
        },
    };
</script>

<style>
    .demo {
        color: aqua;
    }
</style>

demo2.vue

<template>
<div>
    <h1 class="demo">{{ NTest }}</h1>
    <button @click="sub">转交数据</button>
    </div>
</template>

<script>
    export default {
        name: "demo2", //一般和文件名相同
        data() {
            return {
                NTest: 200,
                name: "rokned",
            };
        },
        methods: {
            sub() {
                //调用方法
                this.$bus.$emit("hello",666);
            },
        },
    };
</script>

<style>
    .demo {
        color: aqua;
    }
</style>

main.js

import Vue from "vue";
import App from "./app.vue";
Vue.config.productionTip = false;

// //创建构造
// const demo = Vue.extend({});
// //生成一个傀儡vc
// const d = new demo();
// //挂载到原型上供所有其他vc访问
// Vue.prototype.x = d;

new Vue({
    render: (h) => h(App),
    beforeCreate() {
        //标准安装全局事件总线
        Vue.prototype.$bus = this;
    },
}).$mount("#app");

插槽

同一模块的复用中可以添加不同的属性

默认插槽
<template>
<div>
    <h1 class="demo">{{ NTest }}</h1>
    <slot>默认值	</slot>
    </div>
</template>


<template>
<div>
    <h1 v-text="msg"></h1>
    <demo>使用了插槽</demo>
    <hr />
    <demo>也使用了插槽</demo>
    <hr />
    <demo></demo>
    </div>
</template>
具名插槽
<template>
<div>
    <h1 v-text="msg"></h1>
    <demo><span slot="s1">使用了插槽s1</span></demo>
    <hr />
    <demo><span slot="s2">使用了插槽s2</span></demo>
    <hr />
    <demo></demo>
    </div>
</template>

<template>
<div>
    <h1 class="demo">{{ NTest }}</h1>
    <slot name="s1">默认值s1</slot><br />
    <slot name="s2">默认值s2</slot>
    </div>
</template>

还可以使用v-slot配置

<demo>
    <template v-slot:s1>
<span>使用了v-slot</span>
    </template>
</demo>
作用域插槽

从子组件传递数据给父组件插槽,可以传入多个数据

子组件

<template>
<div>
    <h1 class="demo">{{ NTest }}</h1>
    <slot :names="names">默认值s1</slot><br />
    </div>
</template>

<script>
    export default {
        name: "demo", //一般和文件名相同
        data() {
            return {
                NTest: 100,
                names: ["rokned", "ywj", "wy"],
            };
        },
    };
</script>

<style>
    .demo {
        color: aqua;
    }
</style>

父组件

<template>
<div>
    <h1 v-text="msg"></h1>
    <demo>
        <!-- scope只能使用在template中 -->
        <template scope="names">
            <ul>
                <li v-for="(n, index) in names.names" :key="index">{{ n }}</li>
    </ul>
</template>
</demo>
<hr />
<demo>
    <template v-slot="names">
<ol>
    <li v-for="(n, index) in names.names" :key="index" style="">
        {{ n }}
        </li>
        </ol>
    </template>
</demo>
</div>
</template>

<script>
    import demo from "./components/demo.vue";
    export default {
        name: "app",
        data() {
            return {
                msg: "this is a test",
            };
        },

        components: {
            demo,
        },
    };
</script>

<style></style>

slot-scope

属于作用域插槽

<template lang="">
<div>
    <h3>这是父组件</h3>
    <son>
        <template slot="myslot" slot-scope="scope">
            <ul>
                <li v-for="item in scope.data">{{item}}</li>
    </ul>
</template>
</son>
</div> 
</template>
<template>
<div>
    <h4>这是子组件</h4>
    <input type="text" placeholder="请输入">
    <slot name="myslot" :data='list'></slot>
    </div>
</template>

<script>
    export default {
        name:'Son',
        data(){
            return{
                list:[
                    {name:"Tom",age:15},
                    {name:"Jim",age:25},
                    {name:"Tony",age:13}
                ]
            }
        }
    }
</script>

在这里插入图片描述

14.脚手架的配置文件

详情见官网配置参数https://cli.vuejs.org/zh/config/

//vue.config.js
// vue.config.js

/**
 * @type {import('@vue/cli-service').ProjectOptions}
 */
module.exports = {
    // 选项...
}

15.Vuex

与全局总线区别

在这里插入图片描述

在这里插入图片描述

工作原理

可以跳过actions直接进行commit,因为action实际上是与其他服务器进行请求数据的,就是dispatch时不发送具体数据,而让action与backend Api进行交互请求。

在这里插入图片描述

创建Store

//本文件用于创建store
import Vuex from "vuex";
import Vue from "vue";
Vue.use(Vuex);
const actions = {
    add(context, value) {
        context.commit("add", value);
    },
    sub(context, value) {
        context.commit("sub", value);
    },
}; 

const mutations = {
    add(state, value) {
        state.NTest += value;
    },
    sub(state, value) {
        state.NTest -= value;
    },
};

const state = {
    NTest: 0,
};

// 创建store
export default new Vuex.Store({
    actions,
    mutations,
    state,
});

demo.vue

<template>
<div>
    <h1 class="demo">当前和为:{{ $store.state.NTest }}</h1>
    <select v-model.number="n">
        <option value="1">1</option>
        <option value="2">2</option>
        <option value="3">3</option>
    </select>
    <button @click="add">+</button>
    <button @click="sub">-</button>
    <button @click="addOdd">奇加</button>
    </div>
</template>

<script>
    export default {
        name: "demo", //一般和文件名相同
        data() {
            return {
                n: 1,
            };
        },
        methods: {
            add() {
                this.$store.dispatch("add", this.n);
            },
            sub() {
                this.$store.dispatch("sub", this.n);
            },
            addOdd() {
                if (this.n % 2 != 0) {
                    this.$store.dispatch("add", this.n);
                }
            },
        },
    };
</script>

<style>
    .demo {
        color: aqua;
    }
    button {
        margin: 5px;
    }
</style>

main.js

import Vue from "vue";
import App from "./app.vue";
Vue.config.productionTip = false;

// 引入store
import store from "./store/index";

new Vue({
    render: (h) => h(App),
    store,

    beforeCreate() {},
}).$mount("#app");

getter

加工数据

const getters = {
    bigsum(state) {
        return state.NTest * 10;
    },
};
// 创建store
export default new Vuex.Store({
    actions,
    mutations,
    state,
    getters,
});

应用:

    <h1>放大十倍和:{{$store.getters.bigsum}}</h1>

mapState

帮助生成计算属性,映射state

在这里插入图片描述

当键值对相同时,可以使用数组写法

在这里插入图片描述

mapGetters

用法作用与mapstate相同,不过是映射getter

在这里插入图片描述

mapMutations

同上

注:需要传参

在这里插入图片描述

在这里插入图片描述

mapActions

同上,也需要传参

在这里插入图片描述

在这里插入图片描述

模块化配置

分两个配置模块

在这里插入图片描述

分别加载

在这里插入图片描述

分别使用

在这里插入图片描述

在这里插入图片描述

也可以这么写在这里插入图片描述

要开启namespace:true

在这里插入图片描述

16.Vue-router

基本使用

main.js

import Vue from 'vue'
import App from './App.vue'
import VueRouter from 'vue-router'	// 引入VueRouter
import router from './router'				// 引入路由器

Vue.config.productionTip = false

Vue.use(VueRouter)	// 应用插件

new Vue({
	el:'#app',
	render: h => h(App),
	router: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
        }
    ]
})

About.vue

<template>
<h2>我是About的内容</h2>
</template>

<script>
    export default {
        name:'About'
    }
</script>

Home.vue

<template>
<h2>我是Home的内容</h2>
</template>

<script>
    export default {
        name:'Home'
    }
</script>

App.vue

<template>
<div>
    <div class="row">
        <div class="col-xs-offset-2 col-xs-8">
            <div class="page-header"><h2>Vue Router Demo</h2></div>
    </div>
    </div>
    <div class="row">
        <div class="col-xs-2 col-xs-offset-2">
            <div class="list-group">
                <!-- 原始html中我们使用a标签实现页面的跳转 -->
                <!-- <a class="list-group-item active" href="./about.html">About</a> -->
                <!-- <a class="list-group-item" href="./home.html">Home</a> -->

                <!-- Vue中借助router-link标签实现路由的切换 -->
                <router-link class="list-group-item" 
                             active-class="active" to="/about">About</router-link>
                <router-link class="list-group-item" 
                             active-class="active" to="/home">Home</router-link>
    </div>
    </div>
        <div class="col-xs-6">
            <div class="panel">
                <div class="panel-body">
                    <!-- 指定组件的呈现位置 -->
                    <router-view></router-view>
    </div>
    </div>
    </div>
    </div>
    </div>
</template>

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

多级路由

//使用children配置
routes:[
    {
        path:'/about',
        component:About,
    },
    {
        path:'/home',
        component:Home,
        children:[ 					// 通过children配置子级路由
            {
                path:'news', 		// 此处一定不要带斜杠,写成 /news
                component:News
            },
            {
                path:'message',	// 此处一定不要写成 /message
                component:Message
            }
        ]
    }
]

路由query参数

传递参数

<!-- 跳转并携带query参数,to的字符串写法 -->
<router-link :to="`/home/message/detail?id=${m.id}&title=${m.title}`">跳转</router-link>
				
<!-- 跳转并携带query参数,to的对象写法(推荐) -->
<router-link 
	:to="{
		path:'/home/message/detail',
		query:{
		   id: m.id,
       title: m.title
		}
	}"
>跳转</router-link>

接收参数

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

路由params参数

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

注意:路由携带params参数时,使用to对象写法时,不能使用path参数,只能使用name

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

接收参数

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

路由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
                }
            }
}

命名路由

配置路有名字,简化代码

{
    path:'/demo',
        component:Demo,
            children:[
                {
                    path:'test',
                    component:Test,
                    children:[
                        {
                            name:'hello' // 给路由命名
                            path:'welcome',
                            component:Hello,
                        }
                    ]
                }
            ]
}
<!--简化前,需要写完整的路径 -->
<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>

编程式路由导航

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

push,replace

this.$router. push({}) 内传的对象与 中的 to 相同

this.$router.push({
    name:'xiangqing',
    params:{
        id:xxx,
        title:xxx
    }
})

this.$router.replace({
    name:'xiangqing',
    params:{
        id:xxx,
        title:xxx
    }
})
forward,back, go

forward前进,back后退,go可前进也可后退,n为正数前进n,为负数后退

<template>
<div class="col-xs-offset-2 col-xs-8">
    <div class="page-header">
        <h2>Vue Router Demo</h2>
        <button @click="back">后退</button>
        <button @click="forward">前进</button>
        <button @click="test">测试一下go</button>
    </div>
    </div>
</template>

<script>
    export default {
        name:'Banner',
        methods:{
            back(){
                this.$router.back()
            },
            forward(){
                this.$router.forward()
            },
            test(){
                this.$router.go(3)
            }
        },
    }
</script>

路由缓存

因为切换路由组件,会导致之前的组件被销毁

// 缓存一个路由组件
<keep-alive include="News"> // include中写想要缓存的组件名,不写表示全部缓存
    <router-view></router-view>
</keep-alive>

// 缓存多个路由组件
<keep-alive :include="['News','Message']"> 
    <router-view></router-view>
</keep-alive>

activated,deactivated

两个路由生命周期

activated:路由组件被激活时触发

deactivated:路由组件失活时触发

路由守卫

全局守卫
// 全局前置守卫:初始化时、每次路由切换前执行
router.beforeEach((to,from,next) => {
    console.log('beforeEach',to,from)
    if(to.meta.isAuth){ // 判断当前路由是否需要进行权限控制,meta自己定义
        if(localStorage.getItem('school') === 'nju'){ // 权限控制的具体规则
            next()	// 放行
        }else{
            alert('暂无权限查看')
        }
    }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'
    }
})
独享守卫

没有后置守卫

{
    name:'zhuye',
        path:'/home',
            component:Home,
                meta:{title:'主页'},
                    children:[
                        {
                            name:'xinwen',
                            path:'news',
                            component:News,
                            meta:{title:'新闻'},
                            // 🔴独享守卫,特定路由切换之后被调用
                            beforeEnter(to,from,next){
                                console.log('独享路由守卫',to,from)
                                if(localStorage.getItem('school') === 'nju'){
                                    next()
                                }else{
                                    alert('暂无权限查看')
                                }
                            }
                        },

组件内守卫
<template>
<h2>我是About组件的内容</h2>
</template>

<script>
    export default {
        name:'About',
        // 通过路由规则,离开该组件时被调用
        beforeRouteEnter (to, from, next) {
            console.log('About--beforeRouteEnter',to,from)
            if(localStorage.getItem('school')==='nju'){
                next()
            }else{
                alert('学校名不对,无权限查看!')
            }
        },
        // 通过路由规则,离开该组件时被调用
        beforeRouteLeave (to, from, next) {
            console.log('About--beforeRouteLeave',to,from)
            next()
        }
    }
</script>

路由工作模式

在这里插入图片描述

const router =  new VueRouter({
    mode:'history',
    routes:[...]
            })

    export default router

Objcet.defineProperty

let number = 18;
let number2 = 100;
let person = {
    name: "rokned",
    //不使用getter
    age: number,
};
//使用getter
Object.defineProperty(person, "weight", {
    get() {
        console.log("联动修改");
        return number2;
    },
    set(value) {
        number2 = value;
    },
});

数组更新检测

在这里插入图片描述

VM和VC的重要关系

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值