侧边栏壁纸
博主头像
一朵云的博客博主等级

拥抱生活,向阳而生。

  • 累计撰写 67 篇文章
  • 累计创建 25 个标签
  • 累计收到 7 条评论

目 录CONTENT

文章目录

Vue 笔记(2) -- 语法基础

一朵云
2022-08-07 / 0 评论 / 1 点赞 / 7426 阅读 / 16193 字

一、模板语法

文本

数据绑定最常见的形式就是使用“Mustache”(双大括号)语法的文本插值

<span>Message:{{ msg }}</span>

一般配合js 中的 data() 设置数据

export default {
  name: "HelloWorld",
  data(){
    return{
      msg: "消息提示"
    }
  }
}

原始 HTML

双大括号会将数据解释为普通文本,而非HTML代码。为了输出真正的 HTML ,需要使用 v-html 指令

<p>Using mustaches:{{ rawHtml }}</p>
<p>Using v-html directive:<span v-html="rawHtml"></span></p>
data(){
  return{
    rawHtml: "<a href="https://www.baidu.com">百度</a>"
  }
}

属性 Attribute

Mustache 语法不能在 HTML 属性中使用,然而,可以使用 v-bind 指令。

<div v-bind:id="dynamicId"></div>
data(){
  return{
    dynamicId: 1001
  }
}

提示:

v-bind 指令可以进行简写,如 v-bind:id=“dynamicId” 可以简写成 :id=“dynamicId”。

JavaScript 表达式

刚才的模板中,我们一直都只绑定简单的 property 键值,实际 Vue.js 提供了完全的 JavaScript 表达式支持

{{ number + 1 }}

{{ ok ? 'YES' : 'NO' }}

{{ message.split('').reverse().join('') }}

每个绑定都只能包含单个表达式,举例一些不会生效的例子(错误示范):

<!-- 这是语句,不是表达式 -->
{{ var a = 1 }}

<!-- 流程控制也不会生效,请使用三元表达式 -->
{{ if (ok) { return message } }}

二、条件渲染

v-if

v-if 指令用于条件性地渲染一块内容,这块内容只会在指令的表达式返回 true 值的时候被渲染。

<p v-if="flag">我是孙猴子</p>
data(){
  return {
    flag: true
  }
}

v-else

可以使用 v-else 指令来表示 v-if 的“else 块”

<p v-if=“flag”>我是孙猴子</p>
<p v-else>你是傻猴子</p>
data(){
  return {
    flag: false
  }
}

v-show

另一个用于条件性展示元素的选项是 v-show 指令

<h1 v-show="ok">Hello!</h1>

v-if 和 v-show 的区别:

  v-if 是“真正”的条件渲染,应为它会确保在切换过程中,条件块内的事件监听器和子组件适当地被销毁和重建。

  v-if 是惰性的;如果在初始渲染时条件为假,则什么也不做,知道条件第一次变为真时,他才会开始渲染条件块。

  相比之下,v-show 就简单多,不管初始条件是否成立,元素都会被渲染,并且只是简单地基于CSS进行切换。

  一般来说,v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。说人话就是,如果模块需要频繁地切换,推荐用 v-show;如果运行时条件很少改变,则使用 v-if 较好。

三、列表渲染

用 v-for 把一个数组映射为一组元素

我们可以用 v-for 指令基于一个数组来渲染一个列表。v-for 指令需要使用 item in items 形式的特殊语法,其中 items 是源数据数组,而 item 则是被迭代的数组元素的别名

<ul>
  <li v-for="item in items">{{ item.message }}</li>
</ul>
data(){
  return {
    items: [{ message: 'Foo' },{ message: 'Bar' }]
  }
}

维护状态

  当 Vue 正在更新使用 v-for 渲染元素列表时,它默认使用“就地更新”的策略。如果数据项的顺序被改变了,Vue 将不会移动 DOM 元素来匹配数据项的顺序,而是就地更新每个元素,并且确保他们在每个索引位置正确渲染。

  为了给Vue 一个提示,以便它跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一的 key attrubute:

<div v-for="(item,index) in items" :key="item.id">
  <!-- 内容 -->
</div>

或者

<div v-for="(item,index) in items" :key="index">
  <!-- 内容 -->
</div>

效果演示:

未加key的v-for,删除的元素时会出现一些问题。

没加key的v-for

上图中,仔细看,可以看出这是在第一个li上直接更新的,也就是复用了第一个li的DOM结构,也就是直接在第一个li上改成了第二个li(观察对应的class和li前面的数字)。

为解决这个问题,vue推荐我们使用索引,使用索引后的效果如下:

加了key的v-for

四、事件处理

监听事件

  我们可以使用 v-on 指令(通常缩写为 @ 符号)来监听 DOM 事件,并在触发事件时执行一些JavaScript。用法为:v-on:click=“methodName” 或使用快捷方式 @click=“methodName” 。

<button @click="counter += 1">
  Add 1
</button>
data(){
  return {
    counter: 0
  }
}

  通常情况下,我们是不推荐直接在事件绑定中直接写内容的,因为许多事件处理逻辑更为复杂,直接将 js 代码写在 v-on 指令中不可行。推荐使用 v-on 接收方法名的方式来完成该操作。

<button @click="greet">
  Greet
</button>
methods: {
  greet(event){
    // 'event'是原生的 DOM event
    if(event){
      alert(event.target.tagName)
    }
  }
}

示例:

image-1675824601653

方法事件中也可以进行参数传递,官方成为“内联处理器中的方法”。

<button @click="say('hi')">Say hi</button>
<button @click="say('what')">Say what</button>
methods: {
  say(message) {
    alert(message)
  }
}

五、表单输入绑定

  可以利用 v-model 指令在表单 <input><textarea><select> 元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素。尽管有些神奇,但 v-model 本质上不过是语法糖(更简单的写法)。它负责监听用户的输入事件来更新数据,并在某种极端场景下进行一些特殊处理。

<input v-model="message" placeholder="edit me">
<p>Message is:{{ message }}</p>
data() {
  return {
    message: ""
  }
}

修饰符

  • .lazy

  在默认情况下,v-model 在每次 input 事件触发后将输入框的值与数据进行同步。你可以添加 lazy 修饰符,从而转为在 change 事件之后进行同步。

<input v-model.lazy="message"/>
<p>Message is:{{ message }}</p>
data() {
  return {
    message: ""
  }
}
  • .trim

  如果要自动过滤用户输入的首尾空白字符,可以给 v-model 添加 trim 修饰符。

<input v-model.trim="message" />
data() {
  return {
    message: ""
  }
}

6、组件基础

单文件组件

Vue 单文件组件(又名为 *.vue 文件,缩写为 SFC)是一种特殊的文件格式,它允许将 Vue 组件的模板、逻辑 与 样式 封装在单个文件中。

<template>
  <h3>
    单文件组件
  </h3>
</template>

<script>
export default {
  name: "MyComponent"
}
</script>

<!-- scoped:如果在style中添加此属性,就代表着当前样式,只在当前组件中生效 -->
<style scoped>
h3{
    color: red;
  }
</style>

加载组件

  • 第一步:引入组件 import MyComponentVue from ‘./components/MyComponent.vue’
  • 第二步:挂载组件 components: {MyComponentVue}
  • 第三步:显示组件 <my-componentVue/>

每个.vue文件都是个组件,可以嵌入其他的.vue文件中,形成一个组件树。

image-1675828303844

7、props的组件交互

组件与组件之间是存在交互的,存在交互才有意义。
Prop 是你可以再组件上注册的一些自定义 attribute。

//a.vue

<my-componentVue title="标题"/>

//b.vue

<template>
  <h3>单文件组件</h3>
  <p>{{ title }}</p>
</template>

<sctipt>
export default {
  name: "MyComponent",
  props: {
    title:{
      type: String,
      default: ""
    }
  }
}
</sctipt>

Prop 类型

Prop传递参数没有限制,常见有的以下这些:

props: {
  title: String,
  likes: Number,
  isPublished: Boolean,
  commentIds: Array,
  author: Object,
  callback: Function
}

注意: 当数据类型为数组或者对象的时候,默认值是需要返回工厂模式(工厂模式可以理解为,将响应封装成函数进行返回)。

演示

结合第6点组件基础和第7点组件交互,做个实例演示。

问题: 定义两个组件,一个用于展示数据,一个用于获取数据,通过加载组件的方式关联起来。

思路: 编写两个vue文件,一个是People.vue,表示为人的模板;另一个是Introduce.vue,表示介绍信息,该文件能获取到人的描述信息。需要将People.vue 和 Introduce.vue 关联起来,最终在App.vue中引用。

People.vue

<template>
<div v-for="(item,index) in objectArray" :key="index">
    <p>姓名:{{ item.name }}  年龄:{{ item.age }}</p>
    <p>性格:
        <ul >
            <li v-for="(item1,index) in item.character" :key="index">{{ item1 }}、</li>
        </ul>
    </p>
</div>
<div>
    <p>姓名:{{ man.name }}  年龄:{{ man.age }}</p>
    <p>性格:
        <ul>
            <li v-for="item2 in man.character" :key="man.name">{{ item2 }}</li>
        </ul>
    </p>
</div>
<div>
    <p>姓名:{{ name }}  年龄:{{ age }}</p>
    <p>性格:
        <ul>
            <li v-for="item3 in character" :key="name">{{ item3 }}</li>
        </ul>
    </p>
</div>
</template>

<script>
export default{
    name: 'People',
    props:{
        //数组(数组里存放的是对象)
        objectArray:{
            type: Array,
            default: function(){
                return []
            }
        },
        //对象
        man:{
            type: Object,
            default: function(){
                return {}
            }
        },
        //字符串
        name:{
            type: String,
            required: true,
            default: ""
        },
        //数字
        age:{
            type: Number,
            default: 0
        },
        //数组
        character:{
            type: Array,
            default: function(){
                return [];
            }
        }
    }   
}
</script>

<style></style>

Introduce.vue

<template>
<p>this is Introduce.vue</p>
<People :objectArray="objectArray" :man="man" :name="name" :age="age" :character="character"/>
</template>

<script>

import People from './People.vue'

export default{
    name: 'Introduce',
    data(){
        return{
            objectArray: [
                {
                 name: "张三",
                 age: 18,
                 character: ["傲慢","易怒","猜疑"]
                 },
                {
                 name: "李四",
                 age: 23,
                 character: ["谦虚","和蔼","信任"]
                }
            ],
            man: {
                name: "王五",
                age: 26,
                character: ["佛系","随和","孤僻"]
            },
            name: "赵六",
            age: 30,
            character: ["狡诈","恶毒","圆滑"]
        }
    },
    components:{
        People
    }
}
</script>

<style></style>

App.vue

<template>
  <img alt="Vue logo" src="./assets/logo.png">
  <HelloWorld msg="Welcome to Your Vue.js App"/>
  <Introduce/>
</template>

<script>
import HelloWorld from './components/HelloWorld.vue'
import People from './components/People.vue'
import Introduce from './components/Introduce.vue'

export default {
  name: 'App',
  components: {
    HelloWorld,
    People,
    Introduce
  }
}
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 40px;
}
</style>

image-1675911862257

8、自定义事件组件交互

  自定义事件可以在组件中反向传递数据,prop 可以将数据从父组件传递到子组件,那么反向操作就可以利用自定义事件实现 Semit 。

MyComponent.vue

<template>
    <h3>单文件组件</h3>
    <button @click="sendHandle">发送数据</button>
</template>

<script>
export default{
    name: "MyComponent",
    methods:{
        sendHandle(){
            this.$emit("onCustom","你好呀!")
        }
    }
}
</script>

<style></style>

App.vue

<template>
<MyComponent @onCustom="getData"></MyComponent>
</template>

<script>
import MyComponent from './components/MyComponent.vue'

export default {
  name: 'App',
  components: {
    MyComponent
  },
  methods:{
    getData(data){
      console.log(data);
    }
  }
}
</script>

子组件向父组件发送数据,效果如下:

image-1675914252180

9、组件的生命周期

重点:需要理解透彻。

组件生命周期

为了方便记忆,我们可以将他们分类:

创建时:beforeCreate 、created

渲染时:beforeMount 、mounted

更新时:beforeUpdate 、update

卸载时:beforeUnmount 、unmount

使用场景举例:

接口请求时,放在生命周期mounted中。

image-1675914748737

1
vue

评论区