当前位置: 首页 > news >正文

配置 vue 环境

配置 vue 环境

一、安装 vue 的环境

  1. 安装:
    yarn add vue -D

  2. 在 index.html 中添加挂载点 dom(#app)

<div id="app"></div>
  1. 在 main.js 中引入 vue
import Vue from 'vue'
var app = new Vue({
  el: "#app",
  data: {
    message: 'hello webpack!!'
  }
})

启动 server,会出现
[Vue warn]: You are using the runtime-only build of Vue where the template compiler is not available. Either pre-compile the templates into render functions, or use the compiler-included build.

原因

vue 默认使用的是 vue.runtime.esm.js,
vue 有两种形式的代码 compiler(模板编译)模式和 runtime(运行时)模式,vue 模块的 package.json 的 main 字段默认为 runtime 模式, 指向了"dist/vue.runtime.esm.js"位置

1.1 对不同构建版本的解释

在 NPM 包的 dist/ 目录你将会找到很多不同的 Vue.js 构建版本。这里列出了它们之间的差别:

  • UMDCommonJSES Module (基于构建工具使用)ES Module (直接用于浏览器)
    完整版vue.jsvue.common.jsvue.esm.js
    只包含运行时版vue.runtime.jsvue.runtime.common.jsvue.runtime.esm.js
    完整版 (生产环境)vue.min.js--
    只包含运行时版 (生产环境)vue.runtime.min.js-

1.2 术语

完整版:同时包含编译器和运行时的版本。

编译器:用来将模板字符串编译成为 JavaScript 渲染函数的代码。

运行时:用来创建 Vue 实例、渲染并处理虚拟 DOM 等的代码。基本上就是除去编译器的其它一切。

UMD:UMD 版本可以通过 <script> 标签直接用在浏览器中。jsDelivr CDN 的 https://cdn.jsdelivr.net/npm/vue 默认文件就是运行时 + 编译器的 UMD 版本 (vue.js)。

CommonJS:CommonJS 版本用来配合老的打包工具比如 Browserify 或 webpack 1。这些打包工具的默认文件 (pkg.main) 是只包含运行时的 CommonJS 版本 (vue.runtime.common.js)。

ES Module:从 2.6 开始 Vue 会提供两个 ES Modules (ESM) 构建文件:

为打包工具提供的 ESM:为诸如 webpack 2 或 Rollup 提供的现代打包工具。ESM 格式被设计为可以被静态分析,所以打包工具可以利用这一点来进行“tree-shaking”并将用不到的代码排除出最终的包。为这些打包工具提供的默认文件 (pkg.module) 是只有运行时的 ES Module 构建 (vue.runtime.esm.js)。

为浏览器提供的 ESM (2.6+):用于在现代浏览器中通过 <script type="module"> 直接导入。

1.3 运行时 + 编译器 vs. 只包含运行时

如果你需要在客户端编译模板 (比如传入一个字符串给 template 选项,或挂载到一个元素上并以其 DOM 内部的 HTML 作为模板),就将需要加上编译器,即完整版:

// 需要编译器
new Vue({
    template: "<div>{{ hi }}</div>",
})

// 不需要编译器
new Vue({
    render(h) {
        return h("div", this.hi)
    },
})

当使用 vue-loader 或 vueify 的时候,*.vue 文件内部的模板会在构建时预编译成 JavaScript。你在最终打好的包里实际上是不需要编译器的,所以只用运行时版本即可。

因为运行时版本相比完整版体积要小大约 30%,所以应该尽可能使用这个版本。如果你仍然希望使用完整版,则需要在打包工具里配置一个别名:

1.4 解决方案

而我的 main.js 文件中,初始化 vue 却是这么写的,这种形式为 compiler 模式的,所以就会出现上面的错误信息

//compiler
var app = new Vue({
  el: "#app",
  data: {
    message: 'hello webpack!!'
  }
})

方案一、使用 render 函数渲染

在 src 目标新建一个根组件 App.vue,同时也需要安装 vue-loader 来解析
将 main.js 中的代码修改如下,同时也需要安装 vue-loader 来解析

import App from "src/App.vue"
//runtime
new Vue({
    //el: "#app",
    render: (h) => h(App),
}).$mount("#app")

方案二、webpack 配置文件里有个别名配置

因为之前我们的 webpack 配置文件里有个别名配置,具体如下

resolve: {
alias: {
‘vue$’: ‘vue/dist/vue.esm.js’ //内部为正则表达式 vue 结尾的
}
}
也就是说,import Vue from ‘vue’ 这行代码被解析为 import Vue from ‘vue/dist/vue.esm.js’,直接指定了文件的位置,没有使用 main 字段默认的文件位置

方案三、直接引入 vue/dist/vue.esm.js

既然到了这里我想很多人也会想到第三中解决方法,那就是在引用 vue 时,直接写成如下即可

把
import Vue from 'vue';
改成
import Vue from 'vue/dist/vue.esm.js'

二、使用 Vue 单文件组件

2.1 安装 vue-loader 及依赖

yarn add vue vue-loader vue-template-compiler -D

vue template compiler 模版解析器
简单来说就是使用这个插件就会将 template 语法转为 render 函数,那么常见的操作就是这样的情况:

import Vue from 'vue'
import App from './app.vue';
new Vue({
    el:'#root',
    render:h=>h(App)
})

2.2 配置 webpack.common.js

首先,在 Webpack 4.x 中我们必须显性的引入 vue-loader 插件

const VueLoaderPlugin = require("vue-loader/lib/plugin")
module.exports = {
    module: {
        rules: [
            // ... 其它规则
            {
                test: /\.vue$/,
                loader: "vue-loader",
            },
        ],
    },
    plugins: [
        // 请确保引入这个插件!
        new VueLoaderPlugin(),
    ],
}

2.3 模板预编译 vue-template-compiler

当使用 DOM 内模板 template 或 JavaScript 内的字符串模板时,模板会在运行时被编译为渲染函数。通常情况下这个过程已经足够快了,但对性能敏感的应用还是最好避免这种用法。

如果你需要在客户端编译模板 (比如传入一个字符串给  template  选项,或挂载到一个元素上并以其 DOM 内部的 HTML 作为模板),就将需要加上编译器,即完整版:

vue 的 template 是在运行时转换为 render 函数的

单文件模板中的 template 会在打包运行时 ,即编译阶段编译成 render 函数.

推荐的就是直接使用 render 函数:

预编译模板最简单的方式就是使用单文件组件,相关的构建设置会自动把预编译处理好,所以构建好的代码已经包含了编译出来的渲染函数而不是原始的模板字符串。

如果你使用 webpack,并且喜欢分离 JavaScript 和模板文件,你可以使用  vue-template-loader,它也可以在构建过程中把模板文件转换成为 JavaScript 渲染函数。

// 需要编译器
new Vue({
    template: "<div>{{ hi }}</div>",
})

// 不需要编译器
new Vue({
    render(h) {
        return h("div", this.hi)
    },
})

2.4 Vue2.0 render:h => h(App)的理解

render: h => h(App)  是下面内容的缩写:

render: function (createElement) {
    return createElement(App);
}

进一步缩写为(ES6 语法):

render (createElement) {
    return createElement(App);
}

再进一步缩写为:

render (h){
    return h(App);
}

按照 ES6 箭头函数的写法,就得到了:

render: h => h(App);
new Vue({
  router,
  store,
  render: h => h(App)    vue2.0的写法
}).$mount('#app')

render 函数是渲染一个视图,然后提供给 el 挂载,如果没有 render 那页面什么都不会出来
vue.2.0 的渲染过程:

1.首先需要了解这是 es 6 的语法,表示 Vue 实例选项对象的 render 方法作为一个函数,接受传入的参数 h 函数,返回 h(App) 的函数调用结果。 2.其次,Vue 在创建 Vue 实例时,通过调用 render 方法来渲染实例的 DOM 树。 3.最后,Vue 在调用 render 方法时,会传入一个 createElement 函数作为参数,也就是这里的 h 的实参是 createElement 函数,然后 createElement 会以 APP 为参数进行调用

// ES5
(function (h) {
  return h(App);
});
// ES6
h => h(App);
//官方
render: function (createElement) {
     return createElement(
       'h' + this.level,   // tag name 标签名称
       this.$slots.default // 子组件中的阵列
     )
   }

三、组件的分类

全局组件:可以在所有的 vue 实例中使用
局部组件:只能在当前 vue 实例中使用

四、定义组件的方式

4.1 定义全局组件:

方式 1:先创建组件构造器,然后由组件构造器创建组件

// 1. Vue.extend创建组件构造器
var mycom = Vue.extend({
    template: "<h2>今天天气不错</h2>",
})
// 2. Vue.component(组件名,组件构造器)
Vue.component("hello", mycom)

方式 2:直接创建组件

全局组件 可以在所有的 vue 实例中使用

Vue.component("my-world", {
    template: "<h2>世界, 你好</h2>",
})
Vue.component("my-hello", {
    template: "<h2>我是全局组件</h2>",
    data() {
        //在组件中存储数据时,必须以函数形式,函数返回一个对象
        return {
            name: "laney",
        }
    },
})

4.2 定义局部组件:

var vm = new Vue({
    //这里的vm也是一个组件,称为根组件Root
    el: "#itapp",
    data: {
        msg: "软谋",
    },
    components: {
        "my-world": {
            template: "<h2>世界, 你好 {{age}}</h2>",
            data() {
                return {
                    age: "20",
                }
            },
        },
    },
})

4.3 引用模板

将组件内容放到模板<template>中并引用

在模板文件 main.ejs 添加:

<template id="wbs">
    <div>
        <h3>{{msg}}</h3>
        <ul>
            <li v-for="(item,index) in arr" :key="index">{{item}}</li>
        </ul>
    </div>
</template>
var vm = new Vue({
  el: "#app",
  data: {
    message: 'hello webpack!!',
    username:'my name is Laney',
    flag:true
  },
  components:{
    'my-world':{
      // template:'<h2>我是局部组件:世界, 你好 {{age}}</h2>',
      template:'#wbs',   //直接使用#id名应用模板
      data(){
          return {
              age:'20',

              msg:'我是局部组件my-world',
              arr:['tom','jack','laney']
          }
      }
  }
}

4.4 动态组件

<component :is=""></component>
多个组件使用同一个挂载点,然后动态的在它们之间切换

```<keep-alive>```默认每次都会销毁非活动组件并重新创建
     keep-alive 缓存,避免重新渲染

在模板文件 添加

<button @click="flag='my-hello'">显示hello组件</button>
<button @click="flag='my-world'">显示world组件</button>

<!-- 默认每次都会销毁非活动组件并重新创建
         缓存,避免重新渲染, -->
<keep-alive>
    <component :is="flag"></component>
</keep-alive>
<!-- <my-world></my-world> -->

然后再实例化 vue 的时候添加 flag:true 就可以 动态显示组件了

4.5 通过模板创建子组件

components/footer.vue
components/hello.vue

4.6 组件间数据传递

1. 父子组件

在一个组件内部定义另一个组件,称为父子组件
子组件只能在父组件内部使用
默认情况下,子组件无法访问父组件中的数据,每个组件实例的作用域是独立的

2. 组件间数据传递 (通信)

2.1 子组件访问父组件的数据 props

a)在调用子组件时,绑定想要获取的父组件中的数据
b)在子组件内部,使用props选项声明获取的数据,即接收来自父组件的数据
总结:父组件通过props向下传递数据给子组件
注:组件中的数据共有三种形式:data、props、computed

可以通过这个方式在子组件获取整个父组件, 包括方法,data 数据 等等

2.2 父组件访问子组件的数据 $emit

a)在子组件中使用vm.$emit(事件名,数据)触发一个自定义事件,事件名自定义
b)父组件在使用子组件的地方监听子组件触发的事件,并在父组件中定义方法,用来获取数据
总结:子组件通过events给父组件发送消息,实际上就是子组件把自己的数据发送到父组件

2.3 $refs

或者通过 ref 获取整个子组件

// 父组件
<home ref="home"/>

mounted(){
  console.log(this.$refs.home) //即可拿到子组件的实例,就可以直接操作 data 和 methods
}

2.4 parent 和 children

parent:父实例
children:子实例

//父组件
mounted(){
  console.log(this.$children)
  //可以拿到 一级子组件的属性和方法
  //所以就可以直接改变 data,或者调用 methods 方法
}

//子组件
mounted(){
  console.log(this.$parent) //可以拿到 parent 的属性和方法
}

children 和 parent 并不保证顺序,也不是响应式的 只能拿到一级父组件和子组件

2.5 provide,inject 组合传值

provide 和 inject 主要为高阶插件/组件库提供用例。 并且这对选项需要一起使用; 以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在起上下游关系成立的时间里始终生效。

父组件使用 provide,子组件和其孙子组件皆可用 inject 获取到父组件中 provide 定义的字段内容。

其中 provide 为对象形式,inject 为数组或者对象形式

父组件, provide 是一个对象,提供一个属性或方法

 provide(){
        return {
            fruit:'苹果',
            list:[
                {id:1, name:'香蕉'},
                {id:2, name:'菠萝'},
                {id:3, name:'哈密瓜'}
                ],
          fooMethod:()=>{
            console.log('父组件 fooMethod 被调用')
          }
        }
    },

子孙组件:

inject:['fruit','list','fooMethod']  //数组或者对象,注入到子组件

mounted() {
  this.fooMethod()
  console.log(this.fruit)
}
//在父组件下面所有的子组件都可以利用inject

provide 和 inject 绑定并不是可响应的。这是官方刻意为之的。 然而,如果你传入了一个可监听的对象,那么其对象的属性还是可响应的,对象是因为是引用类型

所以 provide 返回一个对象或者函数是可以响应的, 因为对象和函数是引用类型, 实际上改变也不是 vue 做的,而是 JS 的引用类型特性

2.7 $root

// 父组件
mounted(){
  console.log(this.$root) //获取根实例,最后所有组件都是挂载到根实例上
  console.log(this.$root.$children[0]) //获取根实例的一级子组件
  console.log(this.$root.$children[0].$children[0]) //获取根实例的二级子组件
}

2.8 .sync

在 vue@1.x 的时候曾作为双向绑定功能存在,即子组件可以修改父组件中的值; 在 vue@2.0 的由于违背单项数据流的设计被干掉了; 在 vue@2.3.0+ 以上版本又重新引入了这个 .sync 修饰符;

// 父组件
<home :title.sync="title" />
//编译时会被扩展为
<home :title="title"  @update:title="val => title = val"/>

// 子组件
// 所以子组件可以通过$emit 触发 update 方法改变
mounted(){
  this.$emit("update:title", '这是新的title')
}

2.6 eventBus 传值

非父子组件间的通信,可以通过一个空的 Vue 实例作为中央事件总线(事件中心),用它来触发事件和监听事件

var Event=new Vue();
Event.$emit(事件名,数据);
Event.$on(事件名,data => {});

通过 vue 的实例化对象 vm,具有$on订阅, $emit 发布的方法, 可以实现兄弟组件, 父子组件以及各种层级组件之间的通信

比如这里有 network.vue 组件, 他的 2 个儿子组件是 software.vue 和 hardware.vue , 他们之间需要相互通信, 这个时候我们就可以使用 eventBus 模式

// 将需要的全局变量挂在到window对象上,不适合服务端

window.vm = new Vue({
    el:'#app',
    data:{
        username:'ma name is laney',
        message:'hello webpack'
    },
    render:h=>h(App)
});

hardware.vue

setTimeout(()=>{
    vm.$on('data-from-software', function(data){
        console.log(data);
    })
    },1000)

software.vue

 <p>
    <button @click="sendDataToSoftware()">发送数据给硬件页面</button>
 </p>
methods:{
    sendDataToSoftware(){
        vm.$emit('data-from-software', {
            kind:'software'
        })
    }
}

五、slot 内容分发

插槽分类:
A.匿名插槽(也叫默认插槽): 没有命名,有且只有一个
B.具名插槽: 相对匿名插槽组件 slot 标签带 name 命名的;
C.作用域插槽: 子组件内数据可以被父页面拿到(解决了数据只能从父页面传递给子组件)

作用:用来获取组件中的原内容,以及修改替换原内容

slotcon.vue

<template>
    <!-- slot内容分发 -->
    <div>
        <slot name="s1">
            <p>如果没有内容,就显示 -上</p>
        </slot>
        <h3>welcome to beijing</h3>
        <slot>
            <p>如果没有内容,就显示 - 中</p>
        </slot>

        <slot name="s2">
            <p>如果没有内容,就显示 - 下</p>
        </slot>
    </div>
</template>
<script>
    export default {
        data() {
            return {}
        },
    }
</script>

在根组件 App.vue

import slotcon from 'src/components/slotcon.vue';
..........

components:{
        slotcon
}

<slotcon>
    <ul slot="s2">
        <li>插槽s2的内容</li>
        <li>bbmm</li>
        <li>ccmm</li>
    </ul>
    <ul slot="s2">
        <li>插槽s2的内容</li>
        <li>bb</li>
        <li>cc</li>
    </ul>

    <ul slot="s1">
        <li>插槽s1的内容</li>
        <li>1222</li>
        <li>1222</li>
    </ul>

    <p slot>我是中间的默认无名插槽</p>

    这个是我自己的内容
</slotcon>

C.作用域插槽: 子组件内数据可以被父页面拿到(解决了数据只能从父页面传递给子组件)

// 父组件
<todo-list>
 <template v-slot:todo="slotProps" >
   {{slotProps.user.firstName}}
 </template>
</todo-list>
//slotProps 可以随意命名
//slotProps 接取的是子组件标签slot上属性数据的集合所有v-bind:user="user"

// 子组件
<slot name="todo" :user="user" :test="test">
    {{ user.lastName }}
 </slot>
data() {
    return {
      user:{
        lastName:"Zhang",
        firstName:"yue"
      },
      test:[1,2,3,4]
    }
  },
// {{ user.lastName }}是默认数据  v-slot:todo 当父页面没有(="slotProps")

五、vue-router 路由

5.1 简介

使用 Vue.js 开发 SPA(Single Page Application)单页面应用
根据不同 url 地址,显示不同的内容,但显示在同一个页面中,称为单页面应用
参考

5.2 安装 VueRouter

yarn add vue-router -D

5.3 基本用法

  1. 定义组件
  2. 配置路由,构建 router 组件
  3. 创建路由实例
  4. 将 router 挂载在 vue 实例上
  5. 在 app.vue 页面添加路由外联

5.3.1 定义组件

在 src 目录新建 mkdir views && cd views && touch page1.vue page2.vue page3.vue

并添加相关模板信息

5.3.2 配置路由,构建 router 组件

在 src 目录新建 mkdir router && cd router && touch router.js
按照路径创建 router 文件:src/router/router.js

router.js

import Vue from "vue"
import VueRouter from "vue-router"
import Page1 from "pages/page1"
import Page2 from "pages/page2"

Vue.use(VueRouter)
export default new VueRouter({
    mode: "history",
    base: process.env.BASE_URL,
    routes: [
        {
            path: "/page1",
            name: "page1",
            component: Page1,
            beforeEnter(from, to, next) {
                console.log(`beforeEnterhome from ${from} to ${to}`)
                setTimeout(() => {
                    next()
                }, 1000)
            },
        },
        {
            path: "/page2",
            name: "page2",
            component: Page2,
        },
    ],
})

Vue.use
用户执行 Vue.use 的时候,实际执行的是模块的 install 方法,会把 vue 的实例传递进去

5.3.3 在入口文件的 Vue 实例中注入 Router

import Vue from "vue"
import App from "./App" //引入router组件
import router from "./router/router.js"
new Vue({
    //注入router
    router,
    render: (h) => h(App),
}).$mount("#app")

5.3.4 使用 router

在 App.vue 中可以直接使用<router-view><router-link>标签

router-link

https://router.vuejs.org/zh/api/ , 在 header.vue 中添加

header.vue

<template>
    <div class="page-head">
        <h1>Hello App!</h1>
        <div class="top-menu">
            <!-- router-link 进行导航 -->
            <router-link to="/page1">页面一</router-link>
            <router-link to="/page2">页面二</router-link>
        </div>
    </div>
</template>

并调整相应的样式

这时路由已经可以正常工作了!

5.3.5 historyApiFallback

单页应用(SPA)一般只有一个 index.html, 导航的跳转都是基于 HTML5 History API,当用户在越过 index.html 页面直接访问这个地址或是通过浏览器的刷新按钮重新获取时,就会出现 404 问题;

比如 直接访问/login, /login/online,这时候越过了 index.html,去查找这个地址下的文件。由于这是个一个单页应用,最终结果肯定是查找失败,返回一个 404 错误。

historyApiFallback: true 对应的 nginx 配置

这个设置用于自动将 404 响应跳转到首页入口文件 index.html。

webpack 配置如下:

module.exports = {
    //...
    devServer: {
        historyApiFallback: true,
    },
}

部署到服务器上时 nginx 的配置如下:

server {
    listen  80;
    server_name  172.20.47.16;

    location / {
        root /usr/share/nginx/html/console;
        try_files $uri $uri/ /index.html;  # 加上这一行即可
    }

    access_log /var/log/nginx/console_access.log main;
    error_log /var/log/nginx/console_error.log;
}

5.3.6 对 class 进行配置

// router.js
export default () => {
  return new Router({
    routes,
    mode: 'history',
    base: '/base/',
    linkActiveClass: 'active-link',
    linkExactActiveClass: 'exact-active-link'
  })}

vue-router 认为只有路由真正匹配时,才会加上 exact-active-link 这个 class,如果只有一部分重合,就会加上 active-link。

5.3.7 scrollBehavior

页面跳转后,页面是否滚动。
// router.js

export default () => {
  return new Router({
    scrollBehavior (to, from, savedPostion) {
      if (savedPostion) {
        return savedPostion
      } else {
        return { x: 0, y: 0 }
      }
    }
  })}

六、路由嵌套和参数传递

传参的两种形式:
a.查询字符串:login?name=tom&pwd=123
{{KaTeX parse error: Expected 'EOF', got '}' at position 12: route.query}̲} b.rest 风格 url…route.params}}

router.push() 添加路由,功能上与<route-link>相同
router.replace() 替换路由,不产生历史记录

scrollBehavior
beforeEnter 路由独享的守卫
linkActiveClass 更新活动链接的 class 类名
linkExactActiveClass 精确激活的 class

tag: 有时候想要 <router-link> 渲染成某种标签,例如 <li>。 于是我们使用 tag prop 类指定何种标签,同样它还是会监听点击,触发导航。

    <router-link to="/foo" tag="li">foo</router-link>
    <!-- 渲染结果 -->
    <li>foo</li>
 routes: 类型: Array {
            path:路由,
            component:组件
            children:嵌套路由
            beforeEnter: (from: Route, to: Route, next: Function) => void, 路由跳转前
            meta: ,
        }
  mode : 可选值: "hash" | "history" | "abstract"
    base: 默认值: "/" ,
        应用的基路径。例如,如果整个单页应用服务在 /app/ 下,然后 base 就应该设为 "/app/"。
    linkActiveClass :
        默认值: "router-link-active"  , 全局配置 <router-link> 默认的激活的 class。
    linkExactActiveClass:
        默认值: "router-link-exact-active"
        全局配置 <router-link> 默认的精确激活的 class

注入的属性
通过在 Vue 根实例的 router 配置传入 router 实例,下面这些属性成员会被注入到每个子组件。

6.1 query 方式传参和接收参数

传参:
this.$router.push({
        path:'/xxx',
        query:{
          id:id
        }
      })

接收参数:
this.$route.query.id

1.字符串形式

this.$router.push('/home')

2. 对象

 this.$router.push({
     path:'/home'
 })

3. 对象,带查询参数

this.$router.push({
      path:'/home',
      query:{
          plan:'private'
      }
 })

获取参数$route.query, 相当于 get

注意:传参是 this. r o u t e r , 接 收 参 数 是 t h i s . router,接收参数是this. router,this.route,这里千万要看清了!!!

1. r o u t e r 为 V u e R o u t e r 实 例 , 想 要 导 航 到 不 同 U R L , 则 使 用 router为VueRouter实例,想要导航到不同URL,则使用 routerVueRouterURL使router.push 方法
2.$route 为当前 router 跳转对象,里面可以获取 name、path、query、params 等

6.2 params 方式传参和接收参数

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

接收参数:
this.$route.params.id

注意:params 传参,push 里面只能是 name:‘xxxx’,不能是 path:’/xxx’,因为 params 只能用 name 来引入路由,如果这里写成了 path,接收参数页面会是 undefined!!!

另外,二者还有点区别,直白的来说 query 相当于 get 请求,页面跳转的时候,可以在地址栏看到请求参数,而 params 相当于 post 请求,参数不会再地址栏中显示

七、子路由 children,路由的嵌套

使用 children 属性实现路由嵌套,子路由 path 前不要加/,否则永远以根路径开始请求

— 在 users 页面添加子路由,

{
        path: '/users',
        name: 'users',
        component: () => import("pages/users.vue"),   //ES6的按需加载

         //子路由使用: 需要在上一级 (User)路由页面加上router-view
        // 使用children属性实现路由嵌套,子路由path前不要加/,否则永远以根路径开始请求
        children:[
            {
                path:'login',
                name:'login',
                // component:login
                // component: () => import("pages/login.vue")
            },{
                path:'regist/:username/:password',
                name:'regist',
                // component:register
                // component: () => import("pages/register.vue")
            }
        ]

    }

----在子路由的上一级添加 router-view

<router-view></router-view>

给 router-view 加 transition

给所有路由切换加个过渡效果。

<template>
    <div id="app">
        <transition name="fade">
            {" "}
            // 使用 name
            <router-view />
        </transition>
    </div>
</template>

八、命名视图

一个路由同时可以匹配多个组件

命名视图在 components(这时会多个 s)后加属性再在使用<router-view></router-view>的时候用 name 引入,可以使一个页面中存在多个路由

    <router-view></router-view>
    <router-view name="left"></router-view>
    <router-view name="main"></router-view>
var router = new VueRouter({
    routes: [
        {
            path: "/",
            components: {
                default: header,
                left: leftBox,
                main: mainBox,
            },
        },
    ],
})

相关文章:

  • 介绍J2ME的几个重要概念
  • 谷歌浏览器插件
  • 基于MIDP实现ResourceBundle类
  • Node.js 基础-01
  • vscode保存代码,自动按照eslint规范格式化代码设置(vscode最新版配置)
  • 关注J2ME WTK2.2新特性
  • 高级前端面试题
  • 介绍MIDP的属性问题
  • 破解 vue3.x 新特性
  • UniJa2.1声音播放问题(MIDI格式)
  • 在MIDP2.0中调用平台服务
  • 前端模块化
  • 搭建OTA下载服务器
  • Promise的理解
  • 介绍J2ME的安全结构
  • CSS 专业技巧
  • Gradle 5.0 正式版发布
  • JavaScript设计模式系列一:工厂模式
  • Js基础知识(一) - 变量
  • JS数组方法汇总
  • leetcode46 Permutation 排列组合
  • node学习系列之简单文件上传
  • SpriteKit 技巧之添加背景图片
  • Wamp集成环境 添加PHP的新版本
  • 程序员该如何有效的找工作?
  • 初识 beanstalkd
  • 分布式熔断降级平台aegis
  • 服务器之间,相同帐号,实现免密钥登录
  • 解决iview多表头动态更改列元素发生的错误
  • 小程序测试方案初探
  • 优秀架构师必须掌握的架构思维
  • ​VRRP 虚拟路由冗余协议(华为)
  • $$$$GB2312-80区位编码表$$$$
  • (C语言)strcpy与strcpy详解,与模拟实现
  • (c语言版)滑动窗口 给定一个字符串,只包含字母和数字,按要求找出字符串中的最长(连续)子串的长度
  • (NSDate) 时间 (time )比较
  • (SpringBoot)第二章:Spring创建和使用
  • (附源码)计算机毕业设计SSM基于java的云顶博客系统
  • (三) diretfbrc详解
  • (实战)静默dbca安装创建数据库 --参数说明+举例
  • (转)c++ std::pair 与 std::make
  • (转)自己动手搭建Nginx+memcache+xdebug+php运行环境绿色版 For windows版
  • .class文件转换.java_从一个class文件深入理解Java字节码结构
  • .net core 微服务_.NET Core 3.0中用 Code-First 方式创建 gRPC 服务与客户端
  • .net redis定时_一场由fork引发的超时,让我们重新探讨了Redis的抖动问题
  • .NET 的程序集加载上下文
  • .NET/C# 在代码中测量代码执行耗时的建议(比较系统性能计数器和系统时间)
  • .net开发时的诡异问题,button的onclick事件无效
  • [ vulhub漏洞复现篇 ] Apache Flink目录遍历(CVE-2020-17519)
  • [ 蓝桥杯Web真题 ]-布局切换
  • [AIGC] Kong:一个强大的 API 网关和服务平台
  • [BUUCTF NewStarCTF 2023 公开赛道] week3 crypto/pwn
  • [FT]chatglm2微调
  • [HeadFrist-HTMLCSS学习笔记][第一章Web语言:开始了解HTML]
  • [hihocoder1395] 最大权闭合子图