Vue的一些笔记

目录

数据代理

事件处理

Vue的methods

表单绑定(获取数据)

表单修饰符

过滤器filters

计算属性

监视属性

绑定class样式

axios

Vue-cli创建页面

Vue组件的引入

全局组件的注册

组件style标签

ref属性

组件之间的传值

父传子(props)

子传父

兄弟组件的传值

组件的生命周期

$nextTick()

动态组件

组件的name选项

插槽

私有自定义指令

全局自定义指令

全局导入axios

路由

路由高亮显示

路由的重定向

嵌套路由

编程式路由

动态路由

命名路由

路由模式

全局路由设置

局部路由设置

路由懒加载

mixin混入

vue中的插件

Vue动画

使用transition标签

配置代理(一)

解决跨域问题

配置代理(二)

完整的配置代理

插槽

在组件标签里面写内容

betterScroll

vant组件库

Vuex


数据代理

vue中的数据代理:通过一个对象去对另一个对象属进行操作。

实现原理是通过es6中的Object对象的defineProperties方法实现的。

Object.defineProperty(obj, prop, desc)
  • obj 需要定义属性的当前对象

  • prop 当前需要定义的属性名

  • desc 属性描述符

在defineProperties中其中desc是一个对象;里面有很多的配置项

  1. value:设置属性的值

  2. enumerable:控制属性是否可以枚举;默认是false

  3. writeable:控制属性可以是否被修改;默认是false

  4. configurable:控制属性是否可以被删除;默认是false

  5. get()函数:当有人读取对象是时,get函数就会被调用

  6. set()函数:当有人修改对象时,set函数就会被调用

所以说vue中使存在数据代理的,如果没存在的话,data中的数据修改之后,页面不会进行响应式的改变的。这就是vue里面数据代理的好处。

事件处理

事件、修饰符、键盘事件

  1. 点击事件:v-on:click="" -----> 可以简写为: @click=""

  2. 修饰符:(可以连着写)

    1. .prevent: 阻止默认行为(常用)

    2. .stop:阻止事件冒泡(常用)

    3. .once:事件只触发一次(常用)

    4. .capture:事件的捕获模式

    5. .self:只有event.target是当前操作的元素是才触发事件

    6. passive: 事件的默认行为立即执行,无需等待事件回调执行完毕

     <h1 @click="say2">
        <span @click.stop="say1">aaa</span>
    </h1>

  3. 滚动事件:

    1. @scroll 是元素滚动就会触发事件

    2. @wheel是鼠标滚动就会触发事件

  4. 键盘事件:

    1. @keydown.enter:表示当按下键盘enter键的时候触发事件

    2. @keyup

    3. 获取键盘的编码,e.keyCode

    4. 获取键盘的名字:e.key

    5. 按键别名:

      1. 回车---enter

      2. 删除---delete

      3. 退出---esc

      4. 空格---space

      5. 换行---tab

      6. 上-----up

      7. 下----down

      8. 左----left

      9. 右----right

      <input type="text" @keydown.enter="getMsg" v-model="msg">

    6. 系统修饰键用法特殊:ctrl、alt、shift、win

      1. 配合keyup使用:按下修饰键的同时,再按下其他键,随后释放其他键,事件才被触发。

      2. 配合keydown使用:正常触发事件。

Vue的methods

在vue中方法可以拿到event对象,也就是点击的事件;

event.target:获取点击的对象。

注意:如果你需要传递自己的参数,并且需要使用事件对象,那么必须在函数那些个占位符$event

<button @click="fn1"> 点击 </button>
<button @click="fn2(666,$event)"> 点击 </button>
<script>
    const vm = new Vue({
        el: '#app',
        methods: {
            fn1(event){
                console(event.target.innerHTML)
            },
            fn2(a, event){
                console(a,event)
            }
        }
    })
</script>

表单绑定(获取数据)

获取表单输入的值

 <div id="app">
        <input type="text" v-model="msg">
        <br><br>
        {{msg}}
        <hr>
        <input type="checkbox" v-model="check"> 记住用户名
        <br><br>
        {{check}}
        <hr>
        <h2>您的兴趣爱好</h2>
        <input type="checkbox" v-model="Arrbox" value="vue">vue
        <input type="checkbox" v-model="Arrbox" value="react">react
        <input type="checkbox" v-model="Arrbox" value="小程序">小程序
        <br><br>
        {{Arrbox}}
        <hr>
        <h2>单选按钮</h2>
        <input type="radio" value="男" name="sex" v-model="sex"> 男
        <input type="radio" value="女" name="sex" v-model="sex"> 女
        <br><br>
        {{sex}}
        <hr>
        <select name="" id="" v-model="option">
            <option value="岳麓区">岳麓区</option>
            <option value="天心区">天心区</option>
            <option value="芙蓉区">芙蓉区</option>
        </select>
        {{option}}
    </div>
    <script>
        var vm = new Vue({
            el:"#app",
            data:{
                msg:"",
                check:true,
                //多选绑定数组
                Arrbox:[],
                sex:'',
                option:'岳麓区'
            }
        })
    </script>

表单修饰符

  1. lazy:修饰符,懒惰的

  2. number:显示输入的东西为数字类型的

  3. trim:去除首位空格

<input type="text" v-model.lazy="uname">  //反应更慢一点
<input type="number" v-model.number="uage"> //限制输入的类型为数字型的
<input type="text" v-model.trim="num"> //去除首位空格

过滤器filters

相当于对数据进行格式化处理的。(在vue3中已经被废除)

<p>
{{uname | capitalize}}
 // uname:是data中的数据
 // capitalize:是处理uname数据的函数
</p>

计算属性

就是使用computed配置项

我们在使用计算属性的配置对象的时候,如果是简单的获取数据只需要直接写方法就行,但是如果需要修改计算属性里面的方法时候,就需要get()和set()方法了。

监视属性

watch,监视属性的改变。

<script type="text/javascript">
            const vm = new Vue({
                el: '#app',
                data: {
                    weather: true
                },
                methods:{
                    change(){
                        this.weather = !this.weather
                    }
                },
                computed:{
                    ishot(){
                        return this.weather ? '凉爽':'炎热'
                    }
                },
                watch:{
                    weather:{
                        handler(newV,oldV){
                            if(newV == true){
                                console.log("之前的天气为炎热,现在的天气为凉爽");
                            }else{
                                console.log("之前的天气为凉爽,现在的天气为炎热");
                            }
                        }
                    }
                }
            })
        </script>

监视属性里面的配置项:

  • handler(){} 当检测的属性发生变化的时候,函数就会被调用

  • immediate: false 初始化的时候就执行handler一次。默认值为false

  • deep:false。默认为false开启深度检测 ,一般使用的是如果侦听的是一个对象里面属性的变化的话,这个时候就需要开启深度侦听了。

注意:如果是侦听一个对象的子属性的话,就需要包裹一层单引号

watch:{
	'ifo.uname'(newval){
		console.log(newval)
	}
}

绑定class样式

  1. 字符串形式, 直接在标签里面绑定样式:class

  2. 数组形式,通过把class类名放在数组里面,绑定这个数据 。:class="arrClass"

  3. 对象形式,通过对象绑定类名,对象里面的类名用true和false决定

axios

  1. axios.get()

  2. axios.post()

  3. axios.put()

  4. axios.delete()

axios是一个专注于网络请求的库。

axios的基本使用

axios({
 method:"",
	url:"",
 //url的查询参数
 params:{},
 //提交数据的时候给的参数
 data:{}
}).then(function(){
 
})

axios({
         method:"GET",
         params:{
             id:"001"
         },
         url:"http://localhost:3000/students"
     }).then(function(res){
         console.log(res.data);
     })

使用axios在返回数据回来的会给我们包裹一层壳

{
config:{},
data:{真实数据},
headers:{},
status:xxx,
statusText:''
}

axios的简单使用 axios.get() axios.post()

axios.get("url", {
 //get传递的数据
 params:{}
})
axios.post("url",{
 //post提交数据
 name:"张三",
 age:20
})

Vue-cli创建页面

vue-cli是Vue.js开发的标准工具。它简化了程序员基于webpack创建工程化的Vue项目的过程。

1| vue i @vue/cli -g
2| vue -V //检测vue-cli安装完成
3| vue create 项目名称
4| npm run serve

vue-cli项目的解析

1| assets文件夹:存放项目中用到的静态资源文件,例如: css样式表、图片资源
2| components文件夹: 程序员封装的、可复用的组件,都要放到components目录下
3| main.js是项目的入口文件。整个项目的运行,要先执行main.js
4| App.vue是项目的根组件。

Vue组件的引入

<div>
 <h1>App Vue 根组件</h1>
 <hr>
 <Left></Left>
 <Right></Right>
</div>
</template>

<script>
import Left from '@/components/Left.vue'
import Right from '@/components/Right.vue'
export default {
components:{
 Left,
 Right
}
};
</script>

四个步骤:

  1. 创建组件

  2. 在需要使用的组件中导入,import Left from '@/components/Left.vue'

  3. 注册组件通过js当中的component的部分

  4. 使用组件

全局组件的注册

私有组件的注册,只有是引用了该组件才可以使用。当没有引入该组件则不可以使用。但是当我们注册的组件是全局组件那么每个组件不管有没有引用注册该组件,都能使用该组件

注册全局组件步骤:(注意组件自己不要使用自己)

  1. 创建组件。

  2. 在main.js入口文件中,导入被创建好的全局组件。

  3. 通过Vue.conponent('为组件起的名字', 组件名字)方法,可以注册全局组件。

  4. 在需要使用的组件中,直接写全局组件的名称。

  5. // 全局组件的引入
    import All from '@/components/All.vue'
    Vue.component("MyAll", All)

组件style标签

每个组件都有自己的script标签和style标签。当我们在给组件设置样式的时候,其他组件也有相同的标签的时候,样式会影响其他组件的样式,所以我们一般会给当前组件style标签加上scoped

<style lang="less" scoped>
h1 {
 margin: 0;
 font-size: 15px;
 color: #fff;
}
</style>

但是如果我们设置一个组件中的引入组件,引入组件需要个别设置样式那就需要增加 /deep/

<style lang="less" scoped>
div {
flex-grow: 1;
background-color: pink;
padding: 20px;
}
/deep/ button {
background-color: orange;
}
</style>

ref属性

ref获取DOM元素

在每个vue实例中都有$refs对象,里面存储着对应的DOM元素或组件的应用.默认情况下,组件的$refs指向一个空的对象

<template>
<div id="app">
<h1 ref="title">我是一个标题</h1>
<button @click="showTitle">点击我获取标题</button>
</div>
</template>

<script>

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

注意:当ref在标签里面有相同的属性值的情况,会以最后一个为主。

使用方式:

  • 打标识:<h1 ref="xxx">我是一个标题</h1>或者 <School ref="xxx"></School>

  • 获取:this.$refs.xxx

ref不仅仅可以获取DOM元素还可以获取组件实例.

组件之间的传值

父传子(props)

父传子:采用的是props

//父组件-组件的使用者
<template>
<div>
 <h1>left</h1>
 <hr>
 <MyAll :init="18"></MyAll>
</div>
</template>


//子组件-组件的封装者
<template>
<div>
 {{init || 0}}
</div>
</template>
<script>
export default {
 props: ['init'],
}
</script>

props的使用注意点:props只读,不建议修改。如果需要使用props的值,我们可以把这个props的值赋给其他的值。

<template>
<div>
 <h1>All组件</h1>
 <br>
 count的值为: {{count}}
 <br><br>
 <button @click="count++">+1</button> 
</div>
</template>

<script>
export default {
 props: ['init'],
 data() {
     return {
         count: this.init || 0,
     };
 },
}

props的几种使用方式

  1. props的数组方式:直接用数组。

    • props: ['name', 'age', 'sex']
  2. props的对象写法:限制接受过来数据的类型,如果传过来的数据不是对应的数据,就会报错。

    • props: {
              name: String,
              age: Number,
              sex: String
          }
  3. props对象的详细写法:针对每个属性都有自己的配置项。

    • props: {
              name:{
                  type: String,
                  required: true
              },
              age: {
                  type: Number,
                  default: 40
              },
              sex: {
                  type:String,
                  require: true
              }
          }
    • type:表示传入数据的类型

    • required:表示该传入的数据是必须要传的值

    • default:表示不传入值,有默认的值。

    • 一般required和default不会同时出现

注意:父传子通过props传入过来的值,最好是不要直接修改props的值,如果需要修改,应当利用一个变量接收props,再去修改那个变量。

子传父

子组件向父组件传递数据要通过自定义事件。

  1. 子组件通过$emit this.$emit("sendMsg", this.msg)

  2.  

兄弟组件的传值

通过事件车去实现兄弟组件之间的传值

main.js

import Vue from 'vue'
import App from './App.vue'

Vue.config.productionTip = false

new Vue({
render: h => h(App ),
beforeCreate() {
 Vue.prototype.$bus = this
}, 
}).$mount('#app')

哥哥组件

<template>
<div>
   <div class="contain">
       <h1>自己的姓名:{{sonName}}</h1>
       <h3>我的父亲是:{{fname}} </h3>
       <h4>弟弟的名字:{{litterBrather}} </h4>
       <button @click="send">点击告诉父亲我的姓名</button>
   </div>
</div>
</template>

<script>
export default {
 props:['fname', 'getSon'],
 data() {
     return {
         sonName: '唐三',
         litterBrather:''
     }
 },
 methods: {
     send(){
         this.getSon(this.sonName)
     },
     
 },
 mounted(){
     // 绑定事件
     this.$bus.$on('getBratherName',(name)=>{
         // console.log('我是哥哥,收到了弟弟的名字', name);
         this.litterBrather = name
     })
 }
}
</script>

<style scoped>
* {
    box-sizing: border-box;
}
    .contain {
        width: 400px;
        background-color: pink;
        border-radius: 20px;
        overflow: hidden;
        padding: 20px;
    }
    button {
        padding: 10px;
        border: 5px solid skyblue;
        border-radius: 20px;
        background-color: #fff;
    }
</style>

弟弟组件

<template>
  <div>
      <div class="contain">
          <h1>自己的姓名:{{sonName}}</h1>
          <button @click="sendTwoName">把自己的名字给父亲</button>
          <button @click="unbind">解绑事件</button>
          <button @click="sendBratherName">把自己的名字告诉哥哥</button>
      </div>
  </div>
</template>

<script>
export default {
    data() {
        return {
            sonName: '小三'
        }
    },
    methods: {
        sendTwoName(){
            this.$emit('cha', this.sonName);
        },
        unbind(){
            // 解绑一个自定义事件
            this.$off('cha');
            // 解绑多个自定义事件
            // this.$off(['cha', 'demo']);
            // 所有的自定义事件全部解绑
            // this.$off();
        },
        sendBratherName(){
            this.$bus.$emit('getBratherName', this.sonName);
        }
    },
    mounted(){
        
    }
}
</script>

<style scoped>
* {
    box-sizing: border-box;
}
    .contain {
        width: 400px;
        background-color: salmon;
        border-radius: 20px;
        overflow: hidden;
        padding: 20px;
        margin: 20px 0;
    }
    button {
        padding: 10px;
        border: 5px solid skyblue;
        border-radius: 20px;
        background-color: #fff;
        display: block;
        margin: 20px 0  ;
    }
</style>

组件的生命周期

  1. beforeCreate:组件的props/data/methods尚未被创建,都处于不可用状态。(初始化事件)

  2. create d:组件的props/data/methods都已经创建好,都处于可用状态。但是组件的模板结构(DOM)尚未生成。(发送ajax请求拿数据)

  3. beforeMount:将要把内存中编译好的HTML结构渲染到浏览器中,此时浏览器中还没有当前组件的DOM结构。

  4. mounted:已经把内存中的HTML结构,成功渲染到浏览器之中了。此时浏览器中已然包含了当前组件的DOM结构。

  5. beforeUpdate:当数据发生改变的时候就会触发。数据是最新的但是拿到的DOM结构中的数据是旧的。

  6. updated: DOM结构和data的数据都已更新同步。(最新的DOM结构)。

  7. beforeDestroy:将要销毁,但是还没销毁。组件还处在工作状态。

  8. destroyed:组件已经被销毁,组件在浏览器中对应的DOM结构已经被完全移除。

$nextTick()

每个组件身上都有$nextTick()里面接收一个回调函数。

主要的作用就是延迟执行$nextTick中的代码,待页面的DOM元素渲染完成再去执行其中的代码。

简单来说:等组件的DOM更新完成之后,再执行回调函数,从而保证回调函数可以操作最新的DOM元素。

this,$nextTic(()=>{
this.$refs.iptRef.focus()
})

动态组件

动态组件:动态的切换组件的显示与隐藏

<components is="Left"></components> 
//标签是占位符的意思,is属性是将哪个组件渲染在此
//<components></components> 是 vue 的内置标签,作用:组件的占位符。

简单实现组件的动态切换

<template>
<div id="app">
 <h1>App</h1>
 <hr>
 <button @click="whichComponent = 'Left'">展示Left组件</button>
 <button @click="whichComponent = 'Right'">展示Right组件</button>
 <br><br>
 <div class="contain">
   <components :is="whichComponent"></components>
 </div>
</div>
</template>

<script>
import Left from '@/components/Left.vue'
import Right from '@/components/Right.vue';
export default {
components: {
 Left,
 Right
},
data() {
 return {
   whichComponent: 'Left',
 };
},
}
</script>

有些时候我们在切换组件的时候之前组件的数据依然能够保存,这个时候就是需要使用我们的keep-alive去保持组件的状态

<template>
<div id="app">
 <h1>App</h1>
 <hr>
 <button @click="whichComponent = 'Left'">展示Left组件</button>
 <button @click="whichComponent = 'Right'">展示Right组件</button>
 <br><br>
 <div class="contain">
   <keep-alive>
     <components :is="whichComponent"></components>
   </keep-alive>
 </div>
</div>
</template>

<keep-alive></keep-alive>原理:

使用keep-alive标签可以使组件在被切换的时候不被销毁而是被缓存,这样就不会销毁组件的数据了。

keep-alive对应的生命周期函数

  1. 当组件被缓存时,会自动触发组件的deactivated生命周期函数。

  2. 当组件被激活时,会自动触发组件的activated生命周期函数。

keep-alive标签的include属性

主要是设置哪些组件需要缓存的。include的属性值是包含哪些需要缓存的组件。

<keep-alive include="Left,Right">
        <components :is="whichComponent"></components>
</keep-alive>

keep-alive标签的exclude属性

排除哪些组件不需要缓存的。

注意!! include和exclude不能同时使用。

组件的name选项

当我们给组件一个name属性之后,组件在调试工具中显示的就是name的属性值。就相当于组件的名字就是name的属性值。

插槽

插槽(Slot) 是vue为组件的封装者提供的能力。允许开发者在封装组件时,把不确定的、希望由用户指定的部分定义为插槽。

 

v-slot简写形式--#

<template #p>
       <p>
         Lorem ipsum dolor sit amet consectetur adipisicing elit. Debitis,vel.
       </p>
</template>

slot标签的name默认值为default。

slot标签可以传递值(作用域插槽)

<slot name="p" msg="aaaa"></slot>


<Left>
     <template v-slot:p="obj">
       <p>
         Lorem ipsum dolor sit amet consectetur adipisicing elit. Debitis,
         vel.
         <span>{{obj.msg}}</span>
       </p>
     </template>
     <img slot="img" src="@/assets/logo.png" width="100" />
</Left>

私有自定义指令

自定义指令:

  1. 私有自定义指令

  2. 全局自定义指令

私有自定义指令使用方法:

  1. 在js中增加directives配置项.

  2. 给自定义指令取名字.

  3. 给标签使用自定义指令

  4. <template>
      <div id="right">
       	<h1>right---{{ reduce }}</h1>
        <p v-color="tetxColor">啊啊啊 {{reduce}} </p>
        <p v-color="c">啊啊啊 {{reduce}} </p>
         <button @click="c = 'skyblue'">改变颜色</button>
        <p v-color="blue">测试</p>
      </div>
    </template>
    
    <script>
    export default {
         data() {
        return {
          reduce: 100,
          tetxColor:'blue',
          c:'orange'
        };
      },
      // 私有自定义指令
      directives: {
        // 自定义指令的名字
        color:{
          	// 当使用到自定指令的时候,就会立即执行bind方法,其中接收一个参数为只用自定义组件的DOM结构
            // el为使用指令的DOM结构(形参随意就行)
            // 自定义指令可以传递参数,bind中第二个参数就是来接收参数的(对象)
          bind(el,binding){
            console.log(el);
             el.style.color = binding.value
          },
            update(el, binding) {
            el.style.color = binding.value;
          },
        }
      },
    };
    </script>

    bind()函数的缺点:当指令第一次被绑定到元素上的时候,会立即触发bind 函数.只能触发一次

    这个时候就可以就需要用到我们自定义指令中的update方法了

    自定义指令的简写

    <template>
      <div id="right">
        <h1>right---{{ reduce }}</h1>
        <p v-color="tetxColor">啊啊啊 {{ reduce }}</p>
        <p v-color="c">啊啊啊 {{ reduce }}</p>
        <button @click="c = 'skyblue'">改变颜色</button>
        <button @click="reduce--">-</button>
      </div>
    </template>
    <script>
    export default {
      data() {
        return {
          reduce: 100,
          tetxColor: "blue",
          c: "orange",
        };
      },
      // 私有自定义指令
      directives: {
        color(el,binding){
          el.style.color = binding.value;
        }
      },
    };
    </script

全局自定义指令

//直接在main.js中定义全局自定义指令
Vue.directive('backgroundColor', function(el,binding){
el.style.background = binding.value
})

自定义指令一般来说是全局的自定义指令

全局导入axios

直接在main.js中导入axios,把axios直接挂在在Vue的原型身上这样的话,全局都可以直接使用axios不需要再去导入了.

import Vue from 'vue'
import App from './App.vue'
import axios from 'axios'
Vue.config.productionTip = false
// 直接把axios挂载在原型身上,那么每个组件的实例对象都能访问到axios 
// 不过一般来说我们取名字的话都习惯性的取 $http 而不是axios
// Vue.prototype.axios = axios
Vue.prototype.$http = axios

new Vue({
render: h => h(App)
}).$mount('#app')

axios默认请求路径设置

在我们发起axios请求的时候,可能多个组件都需要使用发起请求,那么这个时候请求路径要写多次,万一还需要修改的话,就不利于后期维护,所以我们可以在发起axios请求的时候,设置axios的默认请求路径

 
 

但是我们把axios直接挂载在原型上有一个缺点:

不利于axios API的复用

路由

路由:对应关系的组件 类似于a链接。

  1. 用户点击了页面上的路由链接

  2. 导致了URL地址栏中的Hash值发生了变化

  3. 前端路由监听了到Hash地址的变化

  4. 前端路由把当前Hash地址对应的组件渲染都浏览器中

安装路由:

npm i vue-router@3.5.2 -S

安装配置完Vue之后,可以直接使用<router-view></router-view>,这个标签是用来占位路由的展示区域的

 <router-link to="/home">首页</router-link>
    <router-link to="/movie">电影</router-link>
    <router-link to="/about">关于</router-link>
    <hr>
 <router-view></router-view>

路由高亮显示

//使用router-link-active类名
//我们也可以自己自定义名字,就只需要给router-link标签增加一个active-class类名就成.

.router-link-active {
        color: pink;
   }
 <ul>
        <li><router-link active-class="cha" to="/films">电影</router-link></li>
        <li><router-link active-class="cha" to="/cinemas">影院</router-link></li>
        <li><router-link active-class="cha" to="/center">我的</router-link></li>
      </ul>

 <style>
    .cha {
        color: pink;
    }
</style>
	

// tag属性 将touter-link标签(a标签),设置为其他的你需要的标签
<router-link active-class="cha" tag="li" to="/films">电影</router-link>
表示a标签转成li标签(但是tag属性在vue4中会被移除,)

路由配置

import Vue from 'vue'
import VueRouter from 'vue-router'

// 导入需要展示的组件
import Home from '@/components/routers/HomeDemo.vue'
import Movie from '@/components/routers/MovieDemo.vue'
import About from '@/components/routers/AboutDemo.vue'
Vue.use(VueRouter)
const router = new VueRouter({
  // routes 是一个数组用来定义hash地址与组件的对应关系
  routes: [
    {
      path: '/',
      component: Home
    },
    {
      path: '/home',
      component: Home
    },
    {
      path: '/movie',
      component: Movie
    },
    {
      path: '/about',
      component: About
    }
  ]
})
export default router

路由的重定向

重新制定路由的跳转位置

 routes: [
    {
      path: '/',
      redirect: Home
    },
  ]

嵌套路由

 

import Vue from 'vue'
import VueRouter from 'vue-router'

// 导入需要展示的组件
import About from '@/components/routers/AboutDemo.vue'
// 子路由
import Tab1 from '@/components/routers/tabs/TabDemo1.vue'
import Tab2 from '@/components/routers/tabs/TabDemo2.vue'
Vue.use(VueRouter)
const router = new VueRouter({
  // routes 是一个数组用来定义hash地址与组件的对应关系
  routes: [
    {
      path: '/about',
      component: About,
      children: [
        {
          path: 'tab1',
          component: Tab1
        },
        {
          path: 'tab2',
          component: Tab2
        }
      ]
    }
  ]
})
export default router
<template>
  <div class="about">
    <h1>About</h1>
    <router-link to="/about/tab1">tab_1</router-link>
    <router-link to="/about/tab2">tab_2</router-link>
    <hr>
    <router-view></router-view>
  </div>
</template>

子路由的重定向

{
      path: '/about',
      component: About,
      redirect: '/about/tab1',
      children: [
        {
          path: 'tab1',
          component: Tab1
        },
        {
          path: 'tab2',
          component: Tab2
        }
      ]
    }

或者

{
      path: '/about',
      component: About,
      redirect: '/about/tab1',
      children: [
        {
          path: '',
          component: Tab1
        },
        {
          path: 'tab2',
          component: Tab2
        }
      ]
    }

//默认子路由:如果children 数组中,某个路由规则的path 值为空字符串,则这条路由规则,叫做“默认子路由”

用默认子路由的话,组件的路径就需要改正

<template>
  <div class="about">
    <h1>About</h1>
    <router-link to="/about">tab_1</router-link>
    <router-link to="/about/tab2">tab_2</router-link>
    <hr>
    <router-view></router-view>
  </div>
</template>

编程式路由

  1. $router.push('/films') 有历史记录

  2. $router.replace('/films') 没有历史记录

动态路由

动态路由指的是:把Hash地址中可变的部分定义为参数项,从而提高路由规则的复用性。 在vue-router中使用英文的冒号(:) 来定义路由的参数项。示例代码如下

{
   path: '/movie/:mid',
   component: Movie
 },

这样的传递参数组件可以通过$route去拿到这个参数

 

或者可以直接开启props传递参数

 

命名路由

在路由规则中,可以给路由增加name属性,表示路由具有名字.那么我们以后进行路由跳转的话,不仅可以使用path进行跳转name同样也是可以进行跳转的.

methods: {
  toDetail(id){
    // 通过路径跳转
    // this.$router.push(`/detail/${id}`)
    //通过name跳转
    this.$router.push({
      name: 'chaDetail',
      params: {
        id
      }
    })
  }
}

 {
    name: 'chaDetail', // 命名路由
    path: '/detail/:id',
    component: Detail
  },

路由模式

路由模式:

  1. hash模式(带#号)

  2. history模式(不带#号)

具体操作,只需要在路由匹配规则中设置

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

注意:history要想更完美,还需要后台配置支持。因为我们的应用是个单页客户端应用,如果后台没有正确的配置,当用户在浏览器直接访问

http://oursite.com/user/id就会返回404,这就不好看了。

#

全局路由设置

全局路由设置,只需要在路由配置中index.js中配置就没问题了。

router.beforeEach((to, from, next) => {
 if(to.meta.isJudge){
  console.log('请先登录');
 }else {
  next()
 }

})

局部路由设置

只需要在路由配置中,路由模块所需要的

路由懒加载

当我们写项目的时候路由组件太多,如果我们使用平常的直接在路由配置中导入组件,那么大量的路由组件在服务器一加载的时候就会被使用,这样用户在使用的时候就会出现页面卡顿的情况,这样的话用户体验感就是不太好,所以我们就需要使用路由的懒加载.

路由的懒加载跟我们平常导入路由组件不一样.

  {
    path: '/cinemas',
    component: ()=>import("@/views/Cinemas.vue")
  },

mixin混入

复用组件内容

当不同组件之间某些功能是一样的情况,这样的话,就可以把一样的内容(方法)单独拿出来,然后用混入的方法去使用,增加代码的复用性。

组件的局部混用

单独一个组件的混入

mixin.js

export const mixin = {
    methods:{
        getName(){
            console.log(this.name);
        }
    }
}

school.vue

<script>
import {mixin} from '../mixin'
export default {
    data() {
        return {
            msg: '学校信息',
            name: '长沙学院',
            address: '长沙',
        }
    },
    mixins: [mixin]
    
}
</script>

混合里面如果混入里面的数据和本身数据发生冲突的时候,以自己为主,但是生命钩子函数的时候就是两者都会使用到

组件的全局混入

每个组件的混入

如果需要写的混入代码每个组件都需要混入进去的话,那么直接在main.js中引入混入,那么全部的组件都会混入这些内容。

import Vue from 'vue'
import App from './App.vue'

// 混入
import {a} from './mixin'
Vue.mixin(a)

Vue.config.productionTip = false

new Vue({
  render: h => h(App),
}).$mount('#app')

vue中的插件

插件用来增强vue

插件的本质是一个对象,里面要包含着install方法,其中可以获取参数Vue。

Vue动画

使用transition标签

vue中的动画,是自己写好css的动画,然后通过vue中的 transition标签来控制。

通过css书写关键帧来实现。

<template>
  <div>
      <h1>动画</h1>
      <button @click="isShow = !isShow">显示/隐藏</button>
     <transition name="cha" appear>
      <h2 v-show="isShow">Fighting!!</h2>
     </transition>
  </div>
</template>

<script>
export default {
    data() {
        return {
            isShow: true
        }
    },
}
</script>

<style scoped>
    h2 {
        width: 400px;
        height: 50px;
        background-color: rgb(209, 117, 209);
        text-align: center;
        line-height: 50px;
    }

    /* 来的时候实现的动画 */
    .cha-enter-active {
        animation: move .5s linear;
    }

    /* 去的时候实现的动画 */
    .cha-leave-active {
        animation: move .5s linear reverse;
    }

    @keyframes move {
        from {
            transform: translateX(-100%);
        }
        to {
            transform: translateX(0);
        }
    }
</style>

transition里面的配置项:

  1. name:控制动画类名,默认是v-开头,如果你通过name设置了之后,那么就会以你设置的开头 cha-

  2. appear: 一运行就有动画的展示。默认是false

利用过渡实现动画

<template>
  <div>
    <h1>动画</h1>
    <button @click="isShow = !isShow">显示/隐藏</button>
    <transition name="cha" appear>
      <h2 v-show="isShow">Fighting!!</h2>
    </transition>
  </div>
</template>

<script>
export default {
  data() {
    return {
      isShow: true,
    };
  },
};
</script>

<style scoped>
h2 {
  width: 400px;
  height: 50px;
  background-color: rgb(209, 117, 209);
  text-align: center;
  line-height: 50px;
}

.cha-enter-active {
  transition: 1s;
}
.cha-leave-active {
  transition: 1s;
}
.cha-enter {
  transform: translateX(-100%);
}
.cha-enter-to {
  transform: translateX(0);
}

.cha-leave {
  transform: translateX(0);
}
.cha-leave-to {
  transform: translateX(-100%);
}
</style>

配置代理(一)

解决跨域问题

当vue里面去请求数据的时候,请求的数据的地址和本机地址不是一个地址,就会出现跨域,就获取不到数据。

在vue.config.js里面配置代理

vue.config.js

const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
  transpileDependencies: true,
  lintOnSave: false,
  devServer: {
    // 告诉代理服务器,待会把请求转发给谁
    proxy: 'http://localhost:5000'
  }
})

请求的vue

<template>
  <div>
      <h1>发送axios请求</h1>
      <button @click="getStudent">请求学生信息</button>
  </div>
</template>

<script>
import axios from 'axios'
export default {
    data() {
        return {
            
        }
    },
    methods: {
        getStudent(){
            axios.get('http://localhost:8080/user').then(
                res=>{
                    console.log('请求成功',res.data);
                },
                err=>{
                    console.log('sorry,请求失败',err.message);
                }
            )
        }
    }
}
</script>

配置代理(二)

  1. 代理一的缺点(•́へ•́╬)

  2. 只适合配置一个代理,当有多个服务器需要请求的话,代理一就没有办法实现了。

  3. 不能控制请求的地址是否走代理。当本地资源有这个文件的名字时,就会优先请求本地的资源

完整的配置代理

vue.config.js

const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
  transpileDependencies: true,
  lintOnSave: false,
  devServer: {
    proxy: {
      '/api': {
          //转发给接口
        target: 'http://localhost:5000',
        pathRewrite:{'^/api': ''}
      }
    }
  }
})

请求的vue

<template>
  <div>
      <h1>发送axios请求</h1>
      <button @click="getStudent">请求学生信息</button>
  </div>
</template>

<script>
import axios from 'axios'
export default {
    data() {
        return {
            
        }
    },
    methods: {
        getStudent(){
            //朝自己发请求
            axios.get('http://localhost:8080/api/user').then(
                res=>{
                    console.log('请求成功',res.data);
                },
                err=>{
                    console.log('sorry,请求失败',err.message);
                }
            )
        }
    }
}
</script>

为了解决请求的地址是否走代理,就是在配置代理的时候设置前缀,但是有了前缀,我们请求的地址就会不一样。

这个时候我们就需要在配置代理中设置 pathRewrite这个配置项。重写路径。


插槽

在组件标签里面写内容

插槽的使用:通过slot标签的使用来设置插槽。

默认插槽

app.vue

<template>
    <h1>vue中的插槽</h1>
    <div class="main">
      <Slot title="美食" :list="foods">
        <img src="https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/b8259e8fb355acf168c66f75d375c6af.jpg?thumb=1&w=250&h=250&f=webp&q=90" alt="">
      </Slot>
      <Slot title="游戏" :list="games"></Slot>
      <Slot title="电影" :list="films"></Slot>
    </div>
</template>

slot.vue

<template>
  <div>
    <div class="box1">
      <h2>{{ title }}分类</h2>
      <slot>
        <ul>
          <li v-for="(item, index) in list" :key="index">{{ item }}</li>
        </ul>
      </slot>
    </div>
  </div>
</template>

使用插槽slot标签,讲所需要插槽的代码写在组件标签中,然后在所需要的结构中通过slot标签来挖坑放代码。如果不写slot标签的话,那么在组件标签里面写的代码是显示不出的。

slot标签里面还可以写内容,当组件标签没有写结构内容的时候,就会显示slot标签里面的内容;反之传了内容就会显示传入的结构。

具名插槽

具有名字的插槽

当要去使用多个插槽的时候那么就需要给插槽命名;通过slot标签中的name属性给插槽命名。

app.vue

<template>
  <div class="all">
    <h1>vue中的插槽</h1>
    <div class="main">
      <Slot title="美食" :list="foods">
        <img slot="top" src="https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/b8259e8fb355acf168c66f75d375c6af.jpg?thumb=1&w=250&h=250&f=webp&q=90" alt="">
        <a href="" slot="botton">底部</a>
      </Slot>
      <Slot title="游戏">
        <ul slot="top">
          <li v-for="(g, index) in games" :key="index">{{ g }}</li>
        </ul>
      </Slot>
      <Slot title="电影">
       <template v-slot:top>
            <ul>
          		<li v-for="(f, index) in films" :key="index">{{ f }}</li>
        	</ul>
		</template>
      </Slot>
    </div>
  </div>
</template>

slot.vue

  <template>
    <div>
      <div class="box1">
        <h2>{{ title }}分类</h2>
        <slot name="top"></slot>
        <slot name="bottom"></slot>
      </div>
    </div>
  </template>

当使用template标签的时候可以把slot="top"换成v-slot:top这个是template标签的特别的使用。

作用域插槽

.....

betterScroll

主要完成的功能需要包含Better-Scroll实现页面中拖动滚动、拉动属性等功能

new BetterScroll('.box', {
          // 加上滚动条
          scrollbar: {
            fade: true
          }
        })

vant组件库

Vant 2 - Mobile UI Components built on Vue

常用于移动化开发。

Vuex

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

数据的集中式管理.

 

<script>
import {mapState} from 'vuex'
export default {
data() {
 return {
   n: 1,
 };
},
computed: {
 /* ...mapState({
   he: 'sum',
   age: 'age',
   gender:'gender'
 }) */
 ...mapState(['sum','age','gender'])
},
methods: {
 add() {
   this.$store.commit('Add', this.n)
 },
 reduce() {
   this.$store.commit('Reduce', this.n)
 }
},
mounted() {
 var a = mapState(['he','age'])
 console.log(a);
}
}
</script>

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值