vue2学习笔记

脚手架

使用

安装

npm install -g @vue/cli

创建项目

  1. 文件根目录下的控制台 vue create 项目名,项目名不能有大写字母,中文和特殊字符
  2. 选择vue的版本
  3. npm run serve 运行项目

配置

官方文档

https://cli.vuejs.org/zh/config/#%E5%85%A8%E5%B1%80-cli-%E9%85%8D%E7%BD%AE

服务器

module.exports = defineConfig({
    transpileDependencies: true,
    devServer: {
        port: 3000,
        open: true
    }
})

关闭eslint代码检查

module.exports = defineConfig({
    lintOnSave: false
})

单vue文件讲解

  • template里只能有一个根标签
  • style配合scoped属性,保证样式只针对当前template生效
  • vue文件配合webpack,把他们打包起来插入到Index.html

vue项目文件结构

  • node_modules -----------存放第三方npm包
  • public/index.html ------------浏览运行的网页
  • src/main.js ----------------项目入口,打包入口
  • src/App.vue -------------页面根组件,页面入口
  • package.json -------------存放项目的npm依赖包

脚手架项目初始清理

  • assets和components文件下的一切都删除
  • App.vue全部删除留下template,script,style框

插值表达式

语法

标签内:{{ 表达式 }}

语法示例

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

<script>
export default {
  data() {
    return {
      msg: "今天吃西兰花了吗",
    };
  },
};
</script>

v-bind

作用

给标签属性动态赋值

代码示例

<template>
  <div>
    //v-bind简写:
    <a :href="aURL">百度</a>
  </div>
</template>

<script>
export default {
  data() {
    return {
      aURL: "https://www.baidu.com",
    };
  },
};
</script>

v-on

作用

给标签绑定事件

语法

  • v-on事件名 = “要执行的少量代码”
  • v-on事件名 = “函数名”
  • v-on事件名 = “函数名(参数)”

代码示例

<template>
  <div>
    <h1>计数:{{ count }}</h1>
     //v-on的简写@
    <p><button @click="count++">加一</button></p>
    <p>
      <button @click="addFive">加五</button>
    </p>
    <p>
      <button @click="addFn(15)">加15</button>
    </p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      count: 0,
    };
  },
  methods: {
    addFive() {
      this.count += 5;
    },
    addFn(num) {
      this.count += num;
    },
  },
};
</script>

Vue获取事件对象

语法

  • 如果无传参,通过形参直接接收
  • 如果有传参,通过$event指代事件对象传给事件处理函数

代码示例

<template>
  <div>
    <a href="http://www.baidu.com" @click="fn">百度</a>
    <a href="http://www.baidu.com" @click="fn2(2,$event)">百度2</a>
  </div>
</template>

<script>
export default {
  methods: {
    fn(e) {
      e.preventDefault();
    },
    fn2(num,e) {
      e.preventDefault();
    },
  },
};
</script>

v-on修饰符

语法

  • @事件名.修饰符 = “函数”

修饰符列表

  • .stop 阻止事件冒泡
  • .prevent 阻止默认行为
  • .once 程序运行期前,只触发一次事件处理函数

运行过程

先执行修饰符,然后执行绑定的函数

v-on按键修饰符

语法

  • @keydown.enter ------监测回车按键
  • @keyup.esc ------监测返回按键

v-model修饰符

语法

v-model.修饰符=‘数据变量’

修饰符列表

  • .number -------以parseFloat转成数字类型
  • .trim-----------去除首尾空白字符
  • .lazy----------在change时触发数据改变

v-for

作用

列表渲染,按照数据数量,循环生成

语法

数组的遍历

  • v-for=“值变量 in 目标数组”
  • v-for=“(值变量,索引变量) in 目标结构”

对象的遍历

  • v-for=“value in 目标对象”
  • v-for=“(value ,key) in 目标对象”

字符串的遍历

  • v-for=“值变量 in 目标字符串”
  • 单独遍历每一个字符

数字的遍历

  • v-for=“值变量 in 目标数字”
  • 从1开始到当前数字

目标结构

可以遍历数组/对象/数字/字符串(可遍历结构)

注意

  • v-for中,如果数组源发生了改变,会触发数据更新
  • array[index] = value的写法 不会触发v-for的更新,$set(数组,索引,值)才可以触发v-for的更新
  • v-model绑定单选框,某一个单选框被选中后,v-model绑定的变量的值等于该单选框的value.v-model的值等于某一个单选框的value,则该单选框默认被选中

v-text

作用

  • 把内容作为文本直接显示,不解析内容
  • 会覆盖掉插值表达式
  • 在标签内渲染文本值

语法

v-text = “数据变量”

v-html

作用

  • 设置标签内容为html
  • 在标签内渲染html

语法

v-html = “数据变量”

v-show

作用

  • 控制标签的显示与隐藏
  • 通过控制display:none属性来控制显示与隐藏

语法

v-show = “表达式”

v-if

作用

  • 通过控制是否插入标签来显示隐藏

语法

v-if = “表达式”

vue动态添加类

语法

  • :class=“{类名:布尔值}”
  • 布尔值为true,标签添加类名,为false标签删除类名
  • 可以控制多个类

代码示例

<template>
  <div>
    <button :class="{ on: isOn, off: !isOn }" @click="fun">开关</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      isOn: false,
    };
  },

  methods: {
    fun() {
      this.isOn = !this.isOn;
    },
  },
};
</script>

<style scoped>
.on {
  background-color: pink;
}
.off {
  background-color: gray;
}
</style>

vue动态设置style

语法

:style=“{css属性名:值}”

代码示例

<template>
  <div>
    <button :style="{ color: colorStr }" @click="fun">单机修改样式</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      colorStr: "",
    };
  },

  methods: {
    fun() {
      this.colorStr = "skyblue";
    },
  },
};
</script>

<style scoped>
.on {
  background-color: pink;
}
.off {
  background-color: gray;
}
</style>

过滤器

代码示例

  1. 局部使用

    <template>
      <div>
        商品价格:{{ price | priceFilter }}
        <!-- 过滤器能使用在插值表达式和v-bind属性里 -->
        <p :title="'hello vue' | toUpperCase">hello vue</p>
      </div>
    </template>
    
    <script>
    export default {
      data() {
        return {
          price: 9,
        };
      },
    
      filters: {
        //表达式的值就是过滤器的第一个参数
        priceFilter(num) {
          return `${num < 10 ? "0" + num : num}¥`;
        },
        toUpperCase(string) {
          return string.toUpperCase();
        },
      },
    };
    </script>
    
  2. 全局使用

    //过滤器第一个参数是传入的值,一般是表达式的值,我们传给过滤器的参数从第二个开始
    //在main.js编写
    Vue.filter("moneyFilter",function(value,unit,unit2){
      return `${value} ${unit}${unit2 || ''}`;
    })
    

注意

  • 数组过滤器的方法要这样写

    arrayFilter(array) {
        //必须生成一个新数组,返回对新数组的处理
        return array.slice(0).reverse();
    }
    

计算属性

作用

  • 根据一些数据计算出来一个属性
  • 当计算属性依赖的数据发生变化的时候,计算属性会重新运算
  • 计算属性是作为变量使用的,不要使用括号的语法
  • 计算属性不能和data里的变量重名

代码示例

<template>
  <div>
    <h1>{{ sum }} = {{ a }} + {{ b }}</h1>
    a: <input type="text" v-model.number="a" />
  </div>
</template>

<script>
export default {
  data() {
    return {
      a: 10,
      b: 20,
    };
  },
  computed: {
    sum() {
      return this.a + this.b;
    },
  },
};
</script>
<style lang="scss" scoped></style>

全选案列

<template>
  <div>
    <p>全选:<input type="checkbox" v-model="isAllCheck" /></p>
    <ul>
      <li v-for="item in list" :key="item.id">
        <input type="checkbox" v-model="item.checked" />{{ item.name }}
      </li>
    </ul>
  </div>
</template>

<script>
export default {
  data() {
    return {
      list: [
        {
          id: 1,
          name: "八戒",
          checked: false,
        },
        {
          id: 2,
          name: "孙悟空",
          checked: false,
        },
        {
          id: 3,
          name: "唐僧",
          checked: false,
        },
        {
          id: 4,
          name: "白龙马",
          checked: false,
        },
      ],
    };
  },

  computed: {
    //计算属性的全写形式
    isAllCheck: {
      get() {
        let flag = true;
        this.list.forEach((item) => {
          if (item.checked == false) {
            flag = false;
          }
        });
        return flag;
      },
      set(value) {
        this.list.forEach((item) => {
          item.checked = value;
        });
      },
    },
  },
};
</script>

侦听器watch

语法

  • “被监听的属性名”(newVal,oldVal) {}

    watch: {
        name(oldVal,newVal){}
    }
    

立即深度监听

<template>
  <div>
    <input type="text" v-model="obj.name" />
  </div>
</template>

<script>
export default {
  data() {
    return {
      obj: {
        name: "西兰花",
      },
    };
  },
  watch: {
    obj: {
      //可以监听到复杂数据内部的变化
      deep: true,
      //可以在页面进来时马上触发一次当前监听回调
      immediate: true,
      handler(newVal, oldVal) {
        console.log("监听到了数据变化");
      },
    },
  },
};
</script>
<style scoped></style>

组件

概念

  • 组件是可复用的Vue实例,封装标签,样式和JS代码
  • 一个vue文件就是一个组件

使用方式

  1. 创建组件

    <!-- 文件名ProItem.vue  -->
    <template>
      <div class="container" @click="fn">产品产品产品产品</div>
    </template>
    
    <script>
    export default {
      data() {
        return {};
      },
      methods: {
        fn() {
          console.log("触发组件事件");
        },
      },
    };
    </script>
    <style scoped>
    .container {
      border: 1px solid #ccc;
    }
    </style>
    
  2. 注册组件

    //全局注册 main.js
    import Vue from "vue";
    import App from "./App.vue";
    // @表示src目录
    import ProItem from '@/components/ProItem.vue'
    // 全局注册组件
    Vue.component('ProItem',ProItem);
    
    Vue.config.productionTip = false;
    
    new Vue({
      render: (h) => h(App),
    }).$mount("#app");
    
    
    <script>
    //局部注册
    import ProItem from "@/components/ProItem.vue";
    export default {
      components: {
        ProItem
      },
    };
    </script>
    
  3. 使用组件

    <template>
      <div>
        <ProItem></ProItem>
        <ProItem></ProItem>
        <ProItem></ProItem>
        <ProItem></ProItem>
        <ProItem></ProItem>
      </div>
    </template>
    
    <script>
    export default {};
    </script>
    <style scoped></style>
    
    

组件通信

父传子

  1. 父组件作为属性把数据交给子组件
  2. 子组件声明一个接收的配置 props,将父组件传来的属性写入其中
  3. 写入组内

代码示例:

<template>
  <div>
    <!-- 第一步 -->
    <ProItem
      v-for="(item, index) in list"
      :key="index"
      :itemName="item"
    ></ProItem>
  </div>
</template>

<script>
import ProItem from "@/components/ProItem.vue";
export default {
  components: {
    ProItem: ProItem,
  },
  data() {
    return {
      list: ["西兰花", "西红柿", "西柚"],
    };
  },
};
</script>
<style scoped></style>

<template>
  <!-- 第三步 -->
  <div class="container" @click="fn">{{ itemName }}</div>
</template>

<script>
export default {
  data() {
    return {};
  },
  //第二步
  props: ["itemName"],
  methods: {
    fn() {
      console.log("触发组件事件");
    },
  },
};
</script>
<style scoped>
.container {
  border: 1px solid #ccc;
}
</style>

子传父

  1. 子组件触发自定义事件,传递参数
  2. 父组件监听自定义事件,绑定监听处理函数
  3. 编写监听处理函数。

代码示例

<template>
  <div class="container">
    {{ itemName }}
    <button @click="subtract">+1</button>
  </div>
</template>

<script>
export default {
  data() {
    return {};
  },
  props: ["itemName", "index"],
  methods: {
    fn() {
      console.log("触发组件事件");
    },
    subtract() {
      // 第一步
      this.$emit("subtract", 1, this.index);
    },
  },
};
</script>
<style scoped>
.container {
  border: 1px solid #ccc;
}
</style>

<template>
  <div>
    <!-- 第二步 -->
    <ProItem
      v-for="(item, index) in list"
      :key="index"
      :itemName="item"
      :index="index"
      @subtract="subtract"
    ></ProItem>
  </div>
</template>

<script>
import ProItem from "@/components/ProItem.vue";
export default {
  components: {
    ProItem: ProItem,
  },
  data() {
    return {
      list: [36, 38, 40],
    };
  },
  methods: {
    // 第三步
    subtract(num, index) {
      this.$set(this.list, index, (this.list[index] += num));
    },
  },
};
</script>
<style scoped></style>

props高级

  • props数组的写法可以换成对象

    props: {
        //设定bg的要求格式
        bg: String,
        //继续使用对象的形式,可以使用默认值
        color: {
            type: String,
            default: '#fff'
        },
        //设置必填项
        title: {
            type: String,
            required: true
        }
    }
    

组件通信–EventBus

作用

用于跨组件通信时使用,比如兄弟组件之间通信

语法

  1. src/EventBus/index.js ------ 创建空白Vue对象并导出

    import Vue from 'vue'
    export default new Vue()
    
  2. 在要传递值的组件(a.vue) ------- eventBus.$emit(‘事件名’,值)

  3. 在要接收值的组件(b.vue)-------created()中声明并监听— eventBus.$on(‘事件名’,函数体)

代码示例

A组件

<template>
  <div @click="putData">我是A组件</div>
</template>

<script>
import eventBus from "@/eventBus/index";
export default {
  data() {
    return {
      data: "A组件数据",
    };
  },

  methods: {
    putData() {
      eventBus.$emit("putData", this.data);
    },
  },
};
</script>
<style scoped></style>

B组件

<template>
  <div>我是B组件{{ dataB }}</div>
</template>

<script>
import eventBus from "@/eventBus/index";
export default {
  data() {
    return {
      dataB: "我有自己的数据",
    };
  },

  created() {
    eventBus.$on("putData", (value) => {
      this.dataB = value;
    });
  },
};
</script>
<style scoped></style>

axios的使用

原理

export default function (options) {
  return new Promise(resolve=>{
    const xhr = new XMLHttpRequest()
    xhr.open(options.method, options.url)
    xhr.send()
    xhr.onload = function() {
      // xhr.responseText 其实是获取到的结果
      resolve(JSON.parse(xhr.responseText))
    }
  })
}

// 只要返回一个Promise 对象, 里面的回调函数就会自动带上一个 resolve 放行方法
// 返回Promise就表示可以使用.then()

$refs

概念

作用与标签选择器一样

使用方式

  1. 在标签设置一个ref属性
  2. 使用this.$refs.名字可以获取该dom元素
  3. 获取组件时,可以获取组件的所有属性方法

代码

<template>
  <div>
    <MyBox ref="myBoxRef"></MyBox>
  </div>
</template>

<script>
import MyBox from "@/components/MyBox.vue";
export default {
  components: {
    MyBox,
  },
  mounted() {
      console.log(this.$refs.myBoxRef);
  }
};
</script>
<style lang="scss" scoped></style>

补充

  • 开发时不建议通过$refs来改变组件的值,父子组件通信依然是最优解

$nextTick

作用

等待页面更新(页面跟新是异步的)完毕执行回调函数

语法

this.$nextTick(回调函数)

vue组件进阶

动态组件

作用

  • 多个组件使用同一个挂载点,并动态切换

使用方式

  • 使用:is给组件绑定一个变量,变量值为要显示的组件名

代码示例

<template>
  <div>
    <component :is="comName"></component>
    <button @click="comName = 'MyComA'">显示A组件</button>
    <button @click="comName = 'MyComB'">显示B组件</button>
  </div>
</template>

<script>
import MyComA from "@/components/MyComA.vue";
import MyComB from "@/components/MyComB.vue";
export default {
  data() {
    return {
      comName: "MyComA",
    };
  },

  components: {
    MyComA,
    MyComB,
  },
};
</script>
<style lang="scss" scoped></style>

组件缓存—keep-alive

作用

  • 给需要经常切换的组件添加,将组件缓存

使用方式

  • 动态组件镶嵌到即可

组件插槽

作用

使用slot标签,让组件内可以接收不同的标签结构显示

给组件插入什么标签,组件就显示什么标签

语法口诀

  1. 组件内使用占位
  2. 使用组件时 夹着的地方,传入标签替换slot

设置插槽默认显示

默认显示的内容

具名插槽

使用条件

一个组件内有2处以上需要外部传入标签的地方

语法

  1. slot使用name属性区分名字
  2. template配合v-slot:名字 来分发对应的标签
  3. v-slot: 简写: #

代码示例

<template>
  <div>
    <slot name="left"></slot>
    <slot name="right"></slot>
  </div>
</template>

<script>
export default {
};
</script>
<style scoped>
div {
  display: flex;
  justify-content: space-between;
}
</style>

<template>
  <div>
    <component :is="comName">
      <template #left>
        <button>左按钮</button>
      </template>
      <template #right>
        <button>右按钮</button>
      </template>
    </component>
  </div>
</template>

<script>
import MyComA from "@/components/MyComA.vue";
import MyComB from "@/components/MyComB.vue";
export default {
  data() {
    return {
      comName: "MyComA",
      left: "left",
      right: "right",
    };
  },

  components: {
    MyComA,
    MyComB,
  },
};
</script>
<style lang="scss" scoped></style>

作用域插槽

使用条件

使用插槽时,想使用子组件内的变量

口诀

  1. 子组件,在slot上绑定属性和子组件的值
  2. 使用组件,传入自定义标签,用template和v-slot=“自定义变量名”
  3. scope变量名自动绑定slot上所有属性和值

代码示例

<template>
  <div>
    <!-- 作用域插槽子组件部分,直接传属性 -->
    <slot name="left" :data="monthList">
      {{ monthList.first }}
    </slot>
    <slot name="right"></slot>
  </div>
</template>

<script>
export default {
  data() {
    return {
      monthList: {
        first: "一月",
        second: "二月",
      },
    };
  },
};
</script>
<style scoped>
div {
  display: flex;
  justify-content: space-between;
}
</style>

<template>
  <div>
    <MyComA>
      <template #left="scoped">
        {{ scoped.data.second }}
      </template>
      <template v-slot:right> </template>
    </MyComA>
  </div>
</template>

<script>
import MyComA from "@/components/MyComA.vue";
import MyComB from "@/components/MyComB.vue";
export default {
  data() {
    return {
      comName: "MyComA",
      left: "left",
      right: "right",
    };
  },

  components: {
    MyComA,
    MyComB,
  },
};
</script>
<style lang="scss" scoped></style>

自定义指令

使用条件

获取标签,扩展额外的功能

使用方式–全局注册

Vue.directive("showDom",{
    "inserted" (el) {
        //可以对el标签扩展额外功能
    }
})

使用方式–局部注册

directives: {
 'showDom': {
     //配置对象
     //可以指定使用这个指令的元素,在不同生命周期执行的函数
     //在这些钩子函数的形参中,默认第一个可以获取元素本身,第二个可以用来传参
     inserted(el,options) {
         console.log(el)
         //在元素被插入的时候执行
     },
     updated(el,options) {
         console.log(el)
         //在元素被更新的时候执行
     }
 }
}

使用方式–调用

<div v-showDom>
    hallo world
</div>

Vue-Router

为何使用

  1. 单页面应用:所有功能在一个Html页面上实现
  2. 前端路由作用:实现业务场景切换

优点

  • 整体不刷新页面
  • 数据传递容易

缺点

  • 首次加载比较慢

使用方式

  1. npm i vue-router@3 这个版本对应vue2
  2. main.js----- import Router from ‘vue-router’ 引入
  3. main.js---- Vue.use(Router) Vue安装这个库
  4. main.js----- const router = new Router 创建一个实例
  5. main.js----- new Vue({router}) 挂在到new Vue 上

配置路由

//main.js
//1.引入组件对象
import Find from '@/views/Find.vue'
const routes = [
    {
        path: '/find',
        component: Find
    }
]
const router = new VueRouter({
    //路由配置表
    routes
})

使用路由

<template>
	<div>
        <!-- 跳转链接,控制router-view的显示 -->
    	<router-link to="/myview1">跳转到组件1</router-link>
    	<router-link to="/myview2">跳转到组件2</router-link>
        <!-- 路由的挂载点,指定需要显示路由组件的地方 -->
        <router-view></router-view>
    </div>
</template>

router-link

概念

  1. vue-router提供了一个全局组件 router-link
  2. router-link实质上最终会渲染成a链接,to属性等价于href属性,to无需#
  3. router-link提供了声明式导航高亮的功能,点击自动生成类名router-link-active

声明式导航跳转传参

第一种方式
<!-- /path?参数名=值 -->
<router-link to="/myview1?name=xiancheng666">跳转到组件1</router-link>

对应页面组件接收传递过来的值

<template>
  <div>
      组件1
      <br>
      获取参数:{{$route.query}}
      <!-- 返回{ "name": "xiancheng666" } -->
  </div>
</template>
第二种方式
<!-- /path/值 -->
<router-link to="/myview2/6666666">跳转到组件2</router-link>

对应页面组件接收传递过来的值

//main.js
const routes = [
  {
    path: "/myview2/:id",
    component: MyView2,
  },
];
<template>
  <div>
    组件2
    <br />
    {{ $route.params.id }}
    <!-- 返回6666666 -->
  </div>
</template>

重定向和模式

概念

  1. 重定向:根据用户输入的url重新定向新的url
  2. 模式:url在地址栏显示的样子

重定向的实现

const routes = [
    {
        path: "/",
        redirect: "/find"
    }
]

访问的路由路径不存在处理方法

const routes = [
    {
        path: "*",
        component: NotFound
    }
]

切换路由模式

  • hash路由:http:localhost:8080/#/home
  • history路由:http:localhost:8080/home (以后需要服务器端支持,否者找的是文件夹)
const router = new VueRouter({
    mode: "history"
})

编程式导航跳转与传参

使用JS进行跳转

//传入一个对象,其中带有name属性,需要在路由中预先配置
//方式1
handleClick() {
    this.$router.push({
        name: 'MyPage'
    })
}
//在这里配置
const route = [
    {
        path:'/my',
        component: MyPage,
        name: 'MyPage'
    }
]
//传入一个对象,其中带有path属性
//方式2
handleClick() {
    this.$router.push({
        path: '/my'
    })
}
//直接path作为字符串传入
//方式3
handleClick() {
    this.$router.push('/my')
}

使用JS进行传参

//通过path传入
handleClick() {
    this.$router.push({
        path: '路由路径',
        query: {
            '参数名':'值'
        }
    })
}
//通过params传入
handleClick() {
    this.$router.push({
        name: '路由名',
        params: {
            '参数名':'值'
        }
    })
}

对应组件接收传参

<template>
  <div>
      组件1
      <br>
      <!-- 如果对方使用query传参 -->
      获取参数:{{$route.query.参数名}}
      <br>
      <!-- 如果对方使用params传参 -->
      获取参数:{{$route.params.参数名}}
  </div>
</template>

前进后退

this.$router.back()//后退
this.$router.go()//前进

路由嵌套

第一步配置路由表

const routes = [
    //一级路由
    {
        path: '/find',
        component: Find,
        children:[
            //二级路由
            {
                path: 'ranking',
                component: Ranking
            }
        ]
    }
]

第二步调用

<!-- Find.vue -->
<template>
  <div>
    <router-link to="/find/ranking">排行榜</router-link>
    <!-- 显示二级路由需要一个挂载点 -->
    <router-view></router-view>
  </div>
</template>

全局前置守卫

概念

路由跳转之前,会触发一个函数

语法

router.beforeEach((to,from,next)=>{})

代码示例

//main.js
const router = new VueRouter()
router.beforeEach((to,from,next)=>{
    //to 目的地,from来源,next 放行回调函数
    //如果你来到了我的音乐,但是没有token就要跳转到登录页
    if (to.path === '/my' && !localStorage.getItem('token')) {
        next('/login')
    }
    else {
        next()
    }
})
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值