Vue基础语法

Vue基础

Vue介绍

渐进式JavaScript框架,一套拥有自己规则的语法

官网地址: https://cn.vuejs.org/ (作者:尤雨溪)

Vue从基础开始,会循序渐进向前学习

声明式渲染
组件系统
客户端路由
大规模状态管理
构建工具
库和框架

库:封装的属性或方法(例jQuery)

框架:拥有自己的规则和元素,比库强大的多(例Vue)

Vue学习方式
  • 传统开发模式:基于HTML文件开发Vue
  • 工程化开发方式:在webpack环境中开发Vue,这是最推荐,企业常用的方式
@vue/cli和脚手架介绍

@vue/cli是Vue官方提供的一个全局模块包(得到vue命令),此包用于创建脚手架项目

脚手架好处

  • 开箱即用
  • 0配置webpack

@vue/cli安装

  • 全局安装@vue/cli模块包
yarn global add @vue/cli
  • 查看是否成功
vue -V
@vue/cli 4.5. 12
创建脚手架项目
  1. 创建项目 (项目名不能有大写字母,中文和特殊符号)
vue create vuecli-demo
  1. 选择模板和包管理器,等待脚手架项目创建完毕
Default([Vue 2] babel, eslint)
Default(Vue 3 Preview)([Vue 3] babel, eslint)
Mannually select features
  1. 初始化设置
  2. 切换到项目文件夹下
cd vuecli-demo
  1. 启动vue项目
yarn serve || npm run serve
@vue/cli目录和代码分析

在这里插入图片描述

项目机构了解

在这里插入图片描述

import Vue from 'vue'    // 引入vue对象,类似于<script src="vue.js"></script>
import App from './App.vue'   // App.vue文件里对象引入过来(vue项目页面入口)

new Vue({
    render: h => h(App),  // 准备渲染App页面
}).$mount('#app')  // 渲染到index.html 文件里id叫app的标签上
修改服务器端口号

Vue脚手架项目用配置文件名字是vue.config.js

src并列处新建vue.config.js, 填入配置,重启webpack开发服务器

module.exports = {
    devServer: {    // 自定义服务器配置
        port: 3000,
        open: true
    }
}
暂时关闭eslint设置

eslint是一种代码检查的工具,如果写代码违反了eslint的规则-报错

解决方式:

  • 手动解决掉错误,在以后的项目中会讲到
  • 暂时关闭eslint检查,在vue.config.js中配置后重启服务
module.exports = {
    // ...其他配置
    lintOnSave: false  // 关闭eslint检查
}
单vue文件讲解
  • Vue推荐采用.vue文件来开发项目
  • template里只能有一个根标签
  • js独立作用域互不影响
  • style配合scoped属性,保证样式只针对当前template内标签生效
清理欢迎页面
  • assets和components文件夹下的一切都删除掉(不要默认的欢迎页面)
  • src/App.vue默认有很多内容,可以全部删除留下template,script和style
Vue语法
插值表达式

又叫:声明式渲染/文本插值

语法:{{ 表达式 }}

<template>
  <div>
     <h1>{{msg}}</h1>
     <h2>{{obj.name}}</h2>
     <h3>{{obj.age}}</h3>
     <h4>{{obj.team}}</h4>
     <h5>{{obj.age > 18? "去网吧":"伊藤美诚你妈叫你回家吃饭"}}</h5>
  </div>
</template>

<script>
export default {
   data(){
     return {
        msg:"Hello,Vue!",
        obj:{
           name:"沈梦瑶",
           age: 23,
           team:"HII"
        }
     }
   }
}
</script>
MVVM设计模式

用数据驱动视图改变,操作dom的事,vue源码已经处理了

  • 设计模式:是一套被反复使用的、多数人知晓的,经过分类编目的、代码设计经验的总结

  • MVVM(模型,视图,视图模型双向关联的一种设计模式)

  • 好处:减少DOM操作,提高开发效率

v-bind

给标签属性设置Vue变量的值

<template>
  <div>
    <a :href="url">跳转去百度</a>
  </div>
</template>

<script>
export default {
  data () {
    return {
      url:"https://www.baidu.com"
    }
}
}
</script>
v-on绑定事件

v-on: 可以简写成@

<template>
  <div>
    <p>你要购买商品的数量{{count}}</p>
    <button @click="addOne">+1</button><br>
    <button @click="abstractOne">-1</button><br>
    <button @click="addFive">+5</button><br>
  </div>
</template>

<script>
export default {
   data () {
     return {
       count:0
     }
   },
   // 定义函数
  //  this指向export default的{}
  // data函数会把对象挂到当前组件对象上
   methods: {
     addOne(){
       this.count++;
     },
     abstractOne(){
       this.count--;
     },
     addFive(){
       this.count +=5
     }
   }
}
</script>
v-on事件对象

Vue事件处理函数中,拿到事件对象

  • 无传参,通过形参直接接收
  • 传参,通过$event指代事件对象传给事件处理函数
<template>
  <div>
    <a @click="one" href="https://www.baidu.com">Baidu</a><br>
    <a @click="two(5,$event)" href="https://www.taobao.com">Taobao X {{count}}</a>
  </div>
</template>

<script>
export default {
  data () {
    return {
      count:0
    }
  },
   methods: {
     one(e){
       e.preventDefault()
     },
     two(num,e){
       e.preventDefault()
        this.count += num
     }
   }
}
</script>
v-on事件修饰符

在事件后面.修饰符名-给事件带来更强大的功能

修饰符:

  • .stop -阻止事件冒泡
  • .prevent -阻止默认行为
  • .once -程序运行期间,只触发一次事件处理函数
<template>
  <div>
    <div @click="fatherFn">点击父盒子
        <p @click.stop="sonFn">点击子盒子</p>
        <a @click.prevent="preventFn" href="https://www.baidu.com">Baidu</a>
    </div>
  </div>
</template>

<script>
export default {
   methods: {
     fatherFn(){
       console.log('你点击了父盒子')
     },
     sonFn(){
       console.log("你点击了子盒子")
     },
     preventFn(){
       console.log("阻止了页面跳转")
     }
   }
}
</script>
v-on按键修饰符
  • @keydown.enter - 监测回车按键
  • @keydown.esc - 监测返回按键
<template>
  <div>
    <input type="text" @keydown="enterFn">我是回车键
    <input type="text" @keydown="escFn">我是退出键
  </div>
</template>

<script>
export default {
   methods: {
     enterFn(){
       console.log("用户按下了回车键")
     },
     escFn(){
       console.log("用户按下了退出键")
     }
   }
}
</script>
Vue指令:v-model

双向数据绑定

  • 变量变化 -> 视图自动同步
  • 视图变化 -> 变量自动同步

下拉菜单

<template>
  <div>
    <!-- 下拉表单 -->
    <select v-model="from">
      <option value="bj">北京</option>
      <option value="sh">上海</option>
      <option value="hz">杭州</option>
    </select>
  </div>
</template>

<script>
export default {
  data () {
    return {
      from:''
    }
  }
}
</script>

复选框

非数组 -关联的是复选框的checked属性

数组 -关联的是复选框的value属性

<template>
  <div>
    <!-- 复选框 -->
    <div>我的爱好:</div>
    <input type="checkbox" value="b站" v-model="hobby">b站
    <input type="checkbox" value="追星" v-model="hobby">追星
    <input type="checkbox" value="写代码" v-model="hobby">写代码
  </div>
</template>

<script>
export default {
  data () {
    return {
      hobby:[]  // 数组
    }
  }
}
</script>

单选框

<template>
  <div>
    <!-- 单选框 -->
    <span>性别:</span>
    <input type="radio" value="male" name="sex" v-model="gender"><input type="radio" value="female" name="sex" v-model="gender"></div>
</template>

<script>
export default {
  data () {
    return {
      gender:''
    }
  }
}
</script>

文本域

<template>
  <div>
    <!-- 文本域 -->
    <span>自我介绍</span>
    <textarea name="" cols="30" rows="10" v-model="intro">
    </textarea>
  </div>
</template>

<script>
export default {
  data () {
    return {
      intro:''
    }
  }
}
</script>
v-model修饰符

语法:v-model.修饰符 = “Vue数据变量”

  • .number 以parseFloat转成数字类型
  • .trim 去除首尾空白字符
  • .lazy 利用onChange事件,只有失去焦点时才同步

只有当失去焦点时,才会将数据同步到v-model

<template>
  <div>
    <span>自我介绍</span>
    <textarea v-model.lazy="intro" cols="30" rows="10"></textarea>
  </div>
</template>

<script>
export default {
  data () {
    return {
      intro:''
    }
  }
}
</script>
Vue指令 v-text/v-html

更新DOM对象的innerText/innerHTML

  • v-text = ‘Vue数据变量’
  • v-html = ‘Vue数据变量’

注意:会覆盖默认值

<template>
  <div>
    <p v-text="str"></p>
    <p v-html="str"></p>
    <!-- 会覆盖前面的 -->
    <p v-html="str">{{msg}}</p>
  </div>
</template>

<script>
export default {
   data () {
     return {
       msg:"硬糖少女303",
       str:'<span>火箭少女101</span>'
     }
   }
}
</script>
Vue指令 v-if/v-show

控制标签的隐藏或出现

  • v-show = ‘Vue变量’
  • v-if = ‘Vue变量’

原理

  • v-show用的display:none 隐藏(频繁切换使用)
  • v-if 直接从DOM树上移除
<template>
  <div>
    <p v-if="isOk">披荆斩棘天使翼</p>
    <p v-show="isTrue">火箭少女101</p>
  </div>
</template>

<script>
export default {
  data () {
    return {
      isOk:true,
      isTrue:true
    }
  }
}
</script>
Vue指令 v-for循环渲染

列表渲染,所在标签结构,按照数据数量,循环生成

v-for = “(item , index) in 目标结构”

<template>
  <div id="app">
      <!-- 省略其他 -->
      <p>学生详细信息</p>
      <ul>
        <li v-for="obj in stuArr" :key="obj.id">
          <span>{{obj.name}}</span>
          <span>{{obj.sex}}</span>
          <span>{{obj.hobby}}</span>
        </li>
      </ul>
  </div>
</template>

<script>
export default {
  data() {
    return {
      stuArr: [
        {
          id: 1001,
          name: "孙悟空",
          sex: "男",
          hobby: "吃桃子",
        },
        {
          id: 1002,
          name: "猪八戒",
          sex: "男",
          hobby: "背媳妇",
        }
      ]
    }
  }
}
</script>
Vue指令 v-for的更新检测
  • 数组变更方法,才会导致v-for更新,页面更新
  • push() pop() shift() unshift() splice() sort() reverse()

this.$set() v-for可以更新检测

<template>
  <div>
    <ul>
      <li v-for="(item,index) in list" :key="index">{{item}}</li>
    </ul>
    <button @click="reBtn">翻转数组</button>
    <button @click="jBtn">截取前3个</button>
    <button @click="upBtn">点击改掉第一个元素的值</button>
  </div>
</template>

<script>
export default {
  data () {
    return {
      list:[5,3,6,7,2]
    }
  },
  methods: {
    reBtn(){
      this.list = this.list.reverse()
    },
    jBtn(){
      this.list = this.list.slice(0,3)
    },
    upBtn(){
      this.$set(this.list,0,1000)  // 只修改其中一个值
    }
  }
}
</script>

<style>

</style>
v-for就地更新

v-for更新时,是如何操作DOM的?

循环出新的虚拟DOM结构,和旧的虚拟DOM结构对比,尝试复用标签就地更新内容

真实DOM

在这里插入图片描述

虚拟DOM

存在于内存中的一个js对象,保存了DOM关键信息

<template>
   <div id="box">
         <p class="my_p">123</p>
    </div>
</template>
const dom = {
    type:'div',
    attributes:[ { id: 'box'}],
    children:{
        type:'p',
        attributes:[{ class:'my_p'}],
        text:'123'
    }
}

好处:

  • 提高DOM更新的性能,不频繁操作真实DOM,在内存中找到变化部分,再更新真实DOM(打补丁)
diff算法

同级比较-根元素变化-整个DOM树删除重建
在这里插入图片描述

同级比较-根元素不变-属性改变更新属性
在这里插入图片描述

diff算法如何比较新旧虚拟DOM

  • 同级比较
  • 根元素变化,删除重建整个DOM树
  • 根元素不变,属性改变,DOM复用,只更新属性
v-for中key的作用
  • 无key

最大限度尝试就地修改/复用相同类型元素

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cpjDRxDk-1638097686610)(C:/Users/Changnie/AppData/Roaming/Typora/typora-user-images/image-20211114165925155.png)]

  • 有key,值为索引

有key属性,基于key来比较新旧虚拟DOM,移除key不存在元素

在这里插入图片描述

  • 有key,值唯一不重复的字符串或数字

有key属性,基于key来比较新旧虚拟DOM,移除key不存在元素

在这里插入图片描述

动态class

:class=“{类名: 布尔值}”

<template>
  <div>
    <p :class = " {red : bool }">Vue基础</p>
  </div>
</template>

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

<style>
.red{
  color: red;
}
</style>
动态style

:style="{css属性: 值}"

<template>
  <div>
    <p :style="{color:str}">Vue基础</p>
  </div>
</template>

<script>
export default {
  data () {
    return {
      str:'red'
    }
  }
}
</script>

<style>
</style>
过滤器

过滤器只能用在,插值表达式和v-bind动态属性里

  • 全局过滤器

Vue.filter(“过滤器名”,(val) => {return “返回处理后的值”})

在main.js文件中

// 过滤器要写在new Vue上面
Vue.filter('reverse',val => val.split("").reverse().join(""))
<template>
  <div>
    <p>原来的样子{{msg}}</p>
    <p>使用过滤器后的样子{{msg | reverse}}</p>
  </div>
</template>

<script>
export default {
  data () {
    return {
      msg:"Hello,Vue"
    }
  }
}
</script>

<style>
</style>
  • 局部过滤器

filters:{过滤器名字: (val) => {return “返回处理后的值”}}

<template>
  <div>
    <p>需要翻转的message{{msg}}</p>
    <p>使用过滤器后的样子{{msg | reverse}}</p>
    <p :title="msg | toUp">鼠标长停字母大写</p>
  </div>
</template>

<script>
export default {
  data () {
    return {
      msg:"Hello,Vue"
    }
  },
  filters: {
    toUp(val){
      return val.toUpperCase()
    }
  }
}
</script>

<style>
</style>
  • 过滤器传参

vue变量 | 过滤器名(val)

// main.js
Vue.filter('reverse',(val,s) => val.split("").reverse().join(s))
<template>
  <div>
    <p>需要翻转的message{{msg}}</p>
    <p>使用过滤器后的样子{{msg | reverse('|')}}</p>
    <p :title="msg | toUp">鼠标长停字母大写</p>
  </div>
</template>
  • 多个过滤器

vue变量 | 过滤器1 | 过滤器2

<template>
  <div>
    <p>需要翻转的message{{msg}}</p>
    <p>使用过滤器后的样子{{msg | reverse('|')}}</p>
    <p :title="msg | toUp | reverse('|')">鼠标长停字母大写</p>
  </div>
</template>
计算属性computed

一个变量的值,依赖另外一些数据计算而来的结果

计算属性也是vue数据变量,所以不要和data里重名,用法和data相同

<template>
  <div>
    <p>a的值为{{a}}</p>
    <p>b的值为{{b}}</p>
    <p>计算后的值为{{num}}</p>
  </div>
</template>

<script>
export default {
  data () {
    return {
      a:10,
      b:20
    }
  },
  computed: {
    num(){
      return this.a + this.b
    }
  }
}
</script>

<style>
</style>
  • 计算属性的特点

函数内使用的变量改变,重新计算结果返回

  • 计算属性的好处

带缓存,只要依赖项不变,都直接从缓存取

依赖项改变函数自动执行并重新缓存

计算属性的完整写法

计算属性的赋值和取值

<template>
  <div>
    <span>姓名:</span>
    <input type="text" v-model="full">
  </div>
</template>

<script>
export default {
  computed: {
    full:{
      // 赋值过程
      set(val){
         console.log(val)
      },
      // 取值过程
      get(){
        return '刘昊然'
      }
    }
  }
}
</script>

<style>
</style>
侦听器watch

可以侦听data/computed属性值的改变

  • 简单类型侦听器
<template>
  <div>
     <span>用户名</span>
     <input type="text" v-model="name">
  </div>
</template>

<script>
export default {
   data () {
     return {
       name:''
     }
   },
   watch: {
     name(newVal,oldVal){
       console.log(newVal,oldVal)
     }
   }
}
</script>

<style>
</style>
  • 引用类型侦听器
<template>
  <div>
     <span>用户名</span>
     <input type="text" v-model="user.name"><br>
     <span>密码</span>
     <input type="password" v-model="user.pwd">
  </div>
</template>

<script>
export default {
   data () {
     return {
       user:{
          name:'',
          pwd:0
       }
     }
   },
   watch: {
     user:{
       immediate:true, //立即开启侦听
       deep:true, //开启深度监听
       handler(newVal,oldVal){
         console.log(newVal,oldVal)
       }
     }
   }
}
</script>

<style>
</style>
Vue组件基础

组件概念

  • 组件是可复用的Vue实例,封装标签,样式和JS代码
  • 组件化:封住的思想,把页面上可重用的部分封装为组件,从而方便项目的开发和维护

(1)全局注册

import Vue from 'vue'
import 组件对象 from 'vue文件路径'

Vue.component('组件名', 组件对象)

(2)局部注册

import Pannel from "./components/Pannel.vue"

export default {
  components: {
    Pannel:Pannel
  }
}
组件内的scoped是如何工作的

scoped保证所添加样式只针对当前文件有效

  • 准备:当前组件内标签都被添加data-v-hash值的属性
  • 获取:css选择器都被添加data-v-hash值的属性选择器
Vue组件通信
  • 父 -> 子 通过props来传递
  • 步骤:

​ 子组件 - props - 变量(准备接收)

​ 父组件 - 传值进去

组件循环
<template>
  <div>
    <my-product
    v-for="obj in list" :key="obj.id"
    :title="obj.proname"
    :price="obj.proprice"
    :intro="obj.info"
    ></my-product>
  </div>
</template>

<script>
import MyProduct from "./components/MyProduct.vue"
export default {
  data () {
    return {
      list: [
    { id: 1, proname: "超级好吃的棒棒糖", proprice: 18.8, info: '开业大酬宾, 全场8折' },
    { id: 2, proname: "超级好吃的大鸡腿", proprice: 34.2, info: '好吃不腻, 快来买啊' },
    { id: 3, proname: "超级无敌的冰激凌", proprice: 14.2, info: '炎热的夏天, 来个冰激凌了' },
  ],
    }
  },
  components: {
    MyProduct
  }
}
</script>

<style>
</style>
组件通信-单向数据流

从父到子的数据流向,叫单向数据流

Vue规定props里的变量,本身是只读的

错误:

  • 子组件改父传入的数据不通知父组件,数据的不一致性
  • vue规定props本身只读的,不允许重新赋值
子向父-自定义事件

子组件内,恰当的时机,触发父给我绑定的自定义事件,导致父methods里事件处理函数执行

  • 父组件
<template>
  <div>
    <my-product
    v-for="(obj,index) in list" :key="obj.id"
    :title="obj.proname"
    :price="obj.proprice"
    :intro="obj.info"
    :index="index"
    @subPrice="fn"
    ></my-product>
  </div>
</template>

<script>
import MyProduct from "./components/MyProduct.vue"
export default {
  data () {
    return {
      list: [
    { id: 1, proname: "超级好吃的棒棒糖", proprice: 18.8, info: '开业大酬宾, 全场8折' },
    { id: 2, proname: "超级好吃的大鸡腿", proprice: 34.2, info: '好吃不腻, 快来买啊' },
    { id: 3, proname: "超级无敌的冰激凌", proprice: 14.2, info: '炎热的夏天, 来个冰激凌了' },
  ],
    }
  },
  components: {
    MyProduct
  },
  methods: {
    fn(index,price){
      this.list[index].proprice -= price
    }
  }
}
</script>

<style>
</style>
  • 子组件
<template>
  <div class="my-product">
    <h3>标题: {{title}}</h3>
    <p>价格: {{price}}元</p>
    <p>{{intro}}</p>
    <button @click="kan">砍价1元</button>
  </div>
</template>

<script>
export default {
  props:['index','title','price','intro'],
  methods: {
    kan(){
      this.$emit("subPrice",this.index,1)
      console.log(this.index)
    }
  }
}
</script>

<style>
.my-product {
  width: 400px;
  padding: 20px;
  border: 2px solid #000;
  border-radius: 5px;
  margin: 10px;
}
</style>

注意:

  • 为了区分砍价的组件,在props中传入index
  • 子组件传入this.index 给父组件用来区分到底是给哪个对象砍价
组件传值总结

组件是什么?

是一个vue实例,封装标签,样式和js代码

组件好处?

便于复用,易于扩展

组件通信有哪几种?

父 -> 子

子 -> 父

兄弟间的组件传值

跨组件传值-EventBus

常用于跨组件通信时使用

在这里插入图片描述

语法:

  • src/EventBus/index.js 创建空白Vue对象并导出
import Vue from 'vue'
// 导出空白vue对象
export default new Vue()
  • 在要接收值的组件(List.vue) eventBus.$on(‘事件名’,函数体)
import EventBus from '../EventBus'
export default {
  props:['arr'],
  created () {
    // 数据的接收方
    EventBus.$on("subPrice",(index,price)=>{
      this.arr[index].proprice > 1 && (this.arr[index].proprice = this.arr[index].proprice - price)
    })
  }
}
  • 在要传递值的组件 eventBus.$emit(‘事件名’,值)
// 引入空白vue实例
import EventBus from "../EventBus"
export default {
  props:['index','title','price','intro'],
  methods: {
    kan(){
      // 数据传递方
      EventBus.$emit("subPrice",this.index,1)
    }
  }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值