vue.js

二级路由

在这里插入图片描述
welcome子路由页面在home页面当中的写法:
在这里插入图片描述

过渡

在这里插入图片描述
第一步:
在这里插入图片描述
第二步:
在这里插入图片描述

动画

用法与过渡效果一样,可以自己写动画,也可以用第三方库animate.css
在这里插入图片描述
在这里插入图片描述
注:animate.css网站在国内看不了,需要去swiper网站
https://swiper.com.cn/usage/animate/index.html
在这里插入图片描述

ref

vue中ref的使用大全

  • 基本用法,本页面获取dom元素
<template>
  <div id="app">
    <div ref="testDom">11111</div>
    <button @click="getTest">获取test节点</button>
  </div>
</template>

<script>
export default {
  methods: {
    getTest() {
      console.log(this.$refs.testDom)
    }
  }
};
</script>

在这里插入图片描述

获取子组件中的data

子组件

<template>
  <div>
      {{ msg }}
  </div>
</template>

<script>
export default {
  data() {
    return {
      msg: "hello world"
    }
  }
}
</script>

父组件

<template>
  <div id="app">
    <HelloWorld ref="hello"/>
    <button @click="getHello">获取helloworld组件中的值</button>
  </div>
</template>

<script>
import HelloWorld from "./components/HelloWorld.vue";

export default {
  components: {
    HelloWorld
  },
  data() {
    return {}
  },
  methods: {
    getHello() {
      console.log(this.$refs.hello.msg)
    }
  }
};
</script>

子组件调用父组件方法

子组件

<template>
  <div>
</div>
</template>

<script>
export default {
  methods: {
    open() {
      console.log("调用了");
      //  调用父组件方法
      this.$emit("refreshData",111111);
    }
  }
}
</script>

父组件

<template>
  <div id="app">
    <HelloWorld ref="hello" @refreshData="getData"/>
    <button @click="getHello">获取helloworld组件中的值</button>
  </div>
</template>

<script>
import HelloWorld from "./components/HelloWorld.vue";

export default {
  components: {
    HelloWorld
  },
  data() {
    return {}
  },
  methods: {
    getHello() {
      this.$refs.hello.open()
    },
    getData() {
      console.log('111111')
    }
  }
};
</script>

mixin

混入 (mixin) 提供了一种非常灵活的方式,来分发 Vue 组件中的可复用功能。一个混入对象可以包含任意组件选项。当组件使用混入对象时,所有混入对象的选项将被“混合”进入该组件本身的选项。

// 定义一个混入对象
var myMixin = {
  created: function () {
    this.hello()
  },
  methods: {
    hello: function () {
      console.log('hello from mixin!')
    }
  }
}

// 定义一个使用混入对象的组件
var Component = Vue.extend({
  mixins: [myMixin]
})

var component = new Component() // => "hello from mixin!"

vuex

Vuex 允许我们在 store 中定义“getter”(可以认为是 store 的计算属性)。就像计算属性一样,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算vuex|Getter

const store = new Vuex.Store({
  state: {
    todos: [
      { id: 1, text: '...', done: true },
      { id: 2, text: '...', done: false }
    ]
  },
  getters: {
    doneTodos: state => {
      return state.todos.filter(todo => todo.done)
    }
  }
})

Module

const moduleA = {
  state: { ... },
  mutations: { ... },
  actions: { ... },
  getters: { ... }
}

const moduleB = {
  state: { ... },
  mutations: { ... },
  actions: { ... }
}

const store = new Vuex.Store({
  modules: {
    a: moduleA,
    b: moduleB
  }
})

store.state.a // -> moduleA 的状态
store.state.b // -> moduleB 的状态

命名空间

namespaced:ture

  • 默认情况下,模块内部的 action、mutation 和 getter 是注册在全局命名空间的——这样使得多个模块能够对同一 mutation 或 action 作出响应。
  • 如果希望你的模块具有更高的封装度和复用性,你可以通过添加 namespaced: true 的方式使其成为带命名空间的模块。当模块被注册后,它的所有 getter、action 及 mutation 都会自动根据模块注册的路径调整命名。
const store = new Vuex.Store({
  modules: {
    account: {
      namespaced: true,
      
      // 模块内容(module assets)
      state: { ... }, // 模块内的状态已经是嵌套的了,使用 `namespaced` 属性不会对其产生影响
      getters: {
        isAdmin () { ... } // -> getters['account/isAdmin']
      },
      actions: {
        login () { ... } // -> dispatch('account/login')
      },
      mutations: {
        login () { ... } // -> commit('account/login')
      },

      // 嵌套模块
      modules: {
        // 继承父模块的命名空间
        myPage: {
          state: { ... },
          getters: {
            profile () { ... } // -> getters['account/profile']
          }
        },

        // 进一步嵌套命名空间
        posts: {
          namespaced: true,

          state: { ... },
          getters: {
            popular () { ... } // -> getters['account/posts/popular']
          }
        }
      }
    }
  }
})

启用了命名空间的 getter 和 action 会收到局部化的 getter,dispatch 和
 commit。换言之,你在使用模块内容(module assets)时不需要在同一模块
 内额外添加空间名前缀。更改 namespaced 属性后不需要修改模块内的代码。
  • vuex中的store分模块管理,需要在store的index.js中引入各个模块,为了解决不同模块命名冲突的问题,将不同模块的namespaced:true,之后在不同页面中引入getter、actions、mutations时,需要加上所属的模块名

vuex-persistedstate插件

Vuex持久化插件-解决刷新数据消失的问题
vuex可以进行全局的状态管理,但刷新后刷新后数据会消失,这是我们不愿意看到的。怎么解决呢,我们可以结合本地存储做到数据持久化,也可以通过插件-vuex-persistedstate。

  • 插件的原理其实也是结合了存储方式,只是统一的配置就不需要手动每次都写存储方法。
  • 默认存储到localStorage。

使用方法

  • 安装
npm install vuex-persistedstate  --save
  • 引入及配置
    在store下的index.js中
import createPersistedState from "vuex-persistedstate"
const store = new Vuex.Store({
  // ...
  plugins: [createPersistedState()]
})

想要存储到sessionStorage,配置如下

import createPersistedState from "vuex-persistedstate"
const store = new Vuex.Store({
  // ...
  plugins: [createPersistedState({
      storage: window.sessionStorage
  })]
})

想使用cookie同理 默认持久化所有state。

import createPersistedState from "vuex-persistedstate"
const store = new Vuex.Store({
  // ...
  plugins: [createPersistedState({
      storage: window.sessionStorage,
      reducer(val) {
      	return {
      	// 只储存state中的assessmentData
    	  assessmentData: val.assessmentData
    	}
	 }
  })]

vuex引用多个插件的写法

import createPersistedState from "vuex-persistedstate"
import createLogger from 'vuex/dist/logger'
// 判断环境 vuex提示生产环境中不使用
const debug = process.env.NODE_ENV !== 'production'
const createPersisted = createPersistedState({
  storage: window.sessionStorage
})
export default new Vuex.Store({
 // ...
  plugins: debug ? [createLogger(), createPersisted] : [createPersisted]
})

plugins要是一个一维数组不然会解析错误

父子组件之间的传值

父组件往子组件传值props
①定义父组件,父组件传递 number这个数值给子组件,如果传递的参数很多,推荐使用json数组{}的形式

**父组件相关代码**
<template>
   <div class='parent'>  //传递数字88给自组件
       <children number=88></children>
    </div>
    
</template>
<script>
     import Childern from './components/childern' //引入子组件
    export default{
        components:{
            Childern
        }
    }

</script>

 ②定义子组件,子组件通过 props方法获取父组件传递过来的值。props中可以定义能接收的数据类型,如果不符合会报错。

  **子组件相关代码**

  <template>
     <div class='children'>  
         {{number}}  //显示父组件传递过来的值 88
      </div>
  </template>

  <script>
      export default{
          props:[
              //限制父组件传递值的类型
              'number':[Number,String,Object]//可以传递多个值用逗号隔开
              'string':[String]
          ]
      }
      //当然也可以简单一点,如果不考虑数据类型,直接 props:["number","string"]就可以了,中括号包裹,多个值使用,分隔。

  </script>

 

 

③假如接收的参数 是动态的,比如 input输入的内容 v-model的形式

注意:传递的参数名称 支持驼峰命名,下图 描述不正确(1.0是不支持的)

 **父组件相关代码**

  <template>

     <div class='parent'> 
        <input type='text' v-model='inputText'>
         <!--注意动态绑定属性时不支持驼峰命名,用‘-’隔开-->
         <children :input-val='inputText'></children>
      </div>

  </template>

  <script>

      import Childern from './components/childern' //引入子组件
      export default{
          components:{
              Childern
          }
      }

  </script>

 **子组件相关代码**
<template>

   <div class='children'>  
      {{input-val}}
    </div>

</template>

<script>

    export default{
        props:[
           'input-val':[String]
        ]
    }

</script>
 ④父子组件传值,数据是异步请求,有可能数据渲染时报错

  原因:异步请求时,数据还没有获取到但是此时已经渲染节点了

  解决方案:可以在 父组件需要传递数据的节点加上  v-if = false,异步请求获取数据后,v-if = true

(2)子组件往父组件传值,通过emit事件

**子组件相关代码**
 <template>

     <div class='children'>  
         <!-- 子组件通过触发emit方法将值传递给父组件-->
        <button @click='emitToparent'>点击按钮把值传递给父组件</button>
      </div>

  </template>

  <script>

      export default{
          methods:{
              emitToparent(){//不支持驼峰
                  //child-event子组件中自定义方法
                  this.$emit('child-event','我是子组件传递给父组件的值')
              }
          }
      }

  </script>

**父组件相关代码**
<template>

      <div class='parent'> 
         <!-- 触发了父组件的parentEvent方法,然后执行相应的操作-->
         <children @child-event='parentEvent'></children>
      </div>

  </template>

  <script>

      import Childern from './components/childern' //引入子组件
      export default{
          components:{
              Childern             
          },
          methods:{
          parentEvent(data){//data是从子组件传递过来的值
             console.log(data)//打印内容是:我是子组件传递给父组件的值
           }
         }
      }

  </script>

(3)不同组件之间传值,通过eventBus(小项目少页面用eventBus,大项目多页面使用 vuex)

①定义一个新的vue实例专门用于传递数据,并导出
eventBus.js文件相关代码 
import Vue from 'vue'
exprots default new Vue()

②定义传递的方法名和传输内容,点击事件或钩子函数触发eventBus.emit事件

组件A相关代码
<template>

     <div class='componetsA'> 
        <button @click='emitToB'>点击按钮将数据传递给组件B</button>
      </div>
  </template>

  <script>

      import eventBus from './common/eventBus.js' //引入eventBus,实际是引入了另一个vue实例
      export default{
          methods:{
              emitToB(){
                  eventBus.$emit('eventFromA','我是A组件传递给B组件的值')
              }
          }
      }

  </script>

③接收传递过来的数据
注意:enentBus是一个另一个新的Vue实例,区分两个this所代表得vue实例

组件B相关代码
<template>
     <div class='componetsB'> 
       {{title}}//显示A组件传递过来的值
      </div>
  </template>

  <script>

      import eventBus from './common/eventBus.js' //引入eventBus,实际是引入了另一个vue实例
      export default{
          data:{
              return{
              title:''
           }
          },+
          mounted(){
             this.getEventData()//这个是在mounted钩子函数执行获取数据的方法
          }
          methods:{
              getEventData(){
                  const that = this //this是项目vue实例用that接受,与eventBus的vue实例区分
                  eventBus.$on('eventFromA',function(val){
                      that.title = val
                  })
              }
          }
      }

  </script>

六.Vue路由传参的几种方式

vue路由传参是指嵌套路由时父路由向子路由传递参数,否则操作无效。传参方式可以划分为params传参和query传参,params传参又可以分为url中显示参数和不显示参数两种方式。

1.push方法跳转

### 手写完整的path:

this.$router.push({path:`/user/${userId}`})

这样传递参数的话,配置路由的时候需要在path上加参数path:user/:userId。

这种接收参数的方式是this.$route.params.userId。

2.query方式传参和接收参数


传参: 
this.$router.push({
        path:'/xxx',
        query:{
          id:id
        }
      })
  
接收参数:
this.$route.query.id
注意:传参是this.$router,接收参数是this.$route,这里千万要看清了!!!

this. r o u t e r 和 t h i s . router 和this. routerthis.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等

params方式传参和接收参数

传参: 
this.$router.push({
        name:'xxx',
        params:{
          id:id
        }
      })
  
接收参数:
this.$route.params.id
注意:params传参,push里面只能是 name:'xxxx',不能是path:'/xxx',因为params只能用name来引入路由,如果这里写成了path,接收参数页面会是undefined!!!

注意:如果提供了path,params将会被忽略,但是query不属于这种情况。。。
如果使用完整路径和query传参,刷新页面时不会造成路由传参的参数丢失。
另外,二者还有点区别,直白的来说query相当于get请求,页面跳转的时候,可以在地址栏看到请求参数,而params相当于post请求,参数不会再地址栏中显示

router-link标签跳转

params传参(url中显示参数)
定义路由:在定义path路由路径时定义参数名和格式,如 path: "/one/login/:num"

//第一步:引用vue和vue-router ,Vue.use(VueRouter)
import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)
 
//第二步:引用定义好的路由组件
import ChildOne from '../components/childOne'
import ChildTwo from '../components/childTwo'
import Log from '../components/log.vue'
import Reg from '../components/reg.vue'
 
//第三步:定义路由(路由对象包含路由名、路径、组件、参数、子路由等),每一个路由映射到一个组件
//第四步:通过new Router来创建router实例
export default new Router({
  mode: 'history',
  routes: [
    {
      path: '/one',
      name: 'ChildOne',
      component: ChildOne,
      children:[
        {
          path:'/one/log/:num',
          component:Log,
        },
        {
          path:'/one/reg/:num',
          component:Reg,
        },
      ],
    },
    {
      path: '/two',
      name: 'ChildTwo',
      component: ChildTwo
    }
  ]
})


在父路由组件上使用router-link进行路由导航,传参用的形式向子路由组件传递参数。使用router-view进行子路由页面内容渲染,父路由组件childOne.vue 如下:

<template>
  <div style="border:1px solid red;color:red;">
    <p>这是父路由childOne对应的组件页面</p>
    <p>下面可以点击显示嵌套的子路由 </p>
    <router-link to="/one/log/123">显示登录页面</router-link>
    <router-link to="/one/reg/002">显示注册页面</router-link>
    <router-view></router-view>
  </div>
</template>

子路由通过 this.$route.params.num 的形式来获取父路由向子路由传递过来的参数,子路由组件login.vue如下

<template>
  <div style="border:1px solid orange;color:orange;">
    <p>登录界面:这是另一个嵌套路由的内容</p>
    <h3>{{this.$route.params.num}}</h3>
  </div>
</template>

params传参(url中不显示参数)

定义路由时添加name属性给映射的路径取一个别名,router>index.js文件修改router如下

export default new Router({
  mode: 'history',
  routes: [
    {
      path: '/one',
      name: 'ChildOne',
      component: ChildOne,
      children:[
        {
          path:'/one/log/',
          name:'Log',
          component:Log,
        },
        {
          path:'/one/reg/',
          name:'Reg',
          component:Reg,
        },
      ],
    },
    {
      path: '/two',
      name: 'ChildTwo',
      component: ChildTwo
    }
  ]
})

**在父路由组件上使用router-link进行路由导航,使用 <router-link :to="{name:‘home’,params:{id:001}}> 形式传递参数。**注意 ': to= ’ 前面的冒号,childOne.vue组件修改如下:

<template>
  <div style="border:1px solid red;color:red;">
    <p>这是父路由childOne对应的组件页面</p>
    <p>下面可以点击显示嵌套的子路由 </p>
    <router-link :to="{name:'Log',params:{num:666}}">显示登录页面</router-link>
    <router-link :to="{name:'Reg',params:{num:888}}">显示注册页面</router-link>
    <router-view></router-view>
  </div>
</template>

子路由组件页面获取父路由传参方式不变,reg.vue 文件如下

<template>
  <div style="border:1px solid orange;color:orange;">
    <p>登录界面:这是另一个嵌套路由的内容</p>
    <h3>子路由获取的参数:{{this.$route.params.num}}</h3>
  </div>
</template>

常用的mode模式有两种:

  • 默认为hash模式,最明显的标志是,URL上有#号 localhost:8080/#/,路由会监听#后面的信息变化进行路由匹配

  • 另一种为history模式,不会有#出现,很大程度上对URL进行了美化。需要注意history模式在打包后的路由跳转需要服务器配合

组件之间eventBus传递数据

//a组件给b组件传数据

**A组件**
<template>
  <div class='container'>my-coma---<button @click="fn">给B数据</button></div>
</template>

<script>
import eventBus from '@/eventBus'
export default {
  name: 'my-coma',
  data () {
    return {
      aData: 'A组件的数据'
    }
  },
  methods: {
    fn () {
      eventBus.$emit('fromA', this.aData)
    }
  }
}
</script>
**b组件**
<template>
  <div class='container'>my-comb---{{bData}}</div>
</template>

<script>
import eventBus from '@/eventBus'
export default {
  name: 'my-comb',
  data () {
    return {
      bData: ''
    }
  },
  created () {
    // 绑定事件 接受A的数据
    eventBus.$on('fromA', (data) => {
      this.bData = data
    })
  }
}
</script>

vue渲染组件的过程

Vue 推荐在绝大多数情况下使用 template 来创建你的 HTML。但是模板毕竟是模板,不是真实的dom节点。从模板到真实dom节点还需要经过一些步骤

1.把模板编译为render函数
2.实例进行挂载, 根据根节点render函数的调用,递归的生成虚拟dom
3.对比虚拟dom,渲染到真实dom
4.组件内部data发生变化,组件和子组件引用data作为props重新调用render函数,生成虚拟dom, 返回到步骤3

data变化——通过数据劫持Object.defineProperty(Vue3.0放弃了数据劫持,采用了Proxy观察者)——更新data——编译——更新虚拟DOM——重新渲染

报错

vue.runtime.esm.js?2b0e:619 [Vue warn]: Do not use built-in or reserved HTML elements as component id: table

  • 不能使用内置或者保留的HTML或者组件作为组件id

意思就是你使用的组件名的名称跟系统(vue)的内置属性名冲突了,所以创建失败,最好的方法就是换个名字。

Property or method “tableRowcellStyle” is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property.

  • 属性或方法“ tableRowcellStyle”未在实例上定义,但在渲染期间被引用。 通过初始化属性,确保该属性在data,props或methods选项中或对于基于类的组件都是反应性的

原因:在data中没有定义一个tableRowcellStyle, 致错

解决方法:在data中定义一个tableRowcellStyle=" "

undefined 表示未声明或已声明但未赋值的变量或不存在的对象,函数没有返回值时,默认返回 undefined,判断是不是 undefined 使用 typeof 函数,其返回的字符串包括如下:

“number”,“string”,“boolean”,“object”,“function”,“undefined”

Vue 不允许动态添加根级响应式属性,所以你必须在初始化实例前声明根级响应式属性,哪怕只是一个空值」,ok,到这里,问题就解决了,既然说了可以声明空值,那就声明一个空值!

解决:
data() {
	return{
        tableRowcellStyle: ''
	}
}
  • 无效的道具:道具“ cellStyle”的类型检查失败。 预期的对象,函数的字符串值为“”

Invalid prop: type check failed for prop “”. Expected Object, Function, got String with value “”.

解决:cellStyle值的类型错误;

  • Vue只允许模板里存在一个根节点。
    Vue Error: The template root requires exactly one element.
    报错内容
解决:
在 <template> 中添加一个 <div>标签,
之后所有的组件全部加在 <div>即可解决。
  • Failed to mount component: template or render function not defined.
    翻译:无法安装组件:模板或渲染功能未定义。

vue- Invalid component name: “[object HTMLDivElement]”. Component names should conform to valid custom element name in html5 specification.

翻译:vue-无效的组件名称:“ [object HTMLDivElement]”。 组件名称应符合html5规范中的有效自定义元素名称。

  • component is not defined
    问题原因:使用公共组件大写了
    解决:
<tkTabs/>
修改为
<tk-tabs>
  • Failed to mount component: template or render function not defined
    翻译:无法安装组件:模板或渲染功能未定义

  • 格式缩进

alt+shift+F

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值