发布于 2026-01-06 5 阅读
0

Vue.js 入门实战(第五部分)组件基础(第二级)——更实用的内容:组件属性、组件数据与属性

Vue.js 入门实战(第五部分)

组件基础知识

第二级——一些更有用的东西

组件属性

组件数据与属性

这次我们终于要开始学习组件了!所以,泡杯咖啡☕️,让我们开始吧。

今天的文章可以从零开始啦😁

<html>

<head>
  <title>Vue 101</title>
</head>

<body>
  <div id="app">

  </div>

  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

  <script>
    const app = new Vue({
      el: '#app',
      data: {

      }
    });
  </script>
</body>

</html>
Enter fullscreen mode Exit fullscreen mode

组件基础知识

我们将直接进入组件创建环节,因为真正有趣的部分就从这里开始。但请放心,这只是组件强大功能的冰山一角。此外,我们还需要学习computed属性和watchers类,它们也将对我们大有帮助。不过,我们会在下次学习时,结合今天的内容来讲解这些。

组件是Vue.js框架的核心部分,它们就像乐高积木一样,可以用来构建响应式、功能丰富的应用程序——幸运的是,它们学习和使用起来都非常简单!

你可以把组件想象成网页/应用程序中任何你想使用一次或多次的元素。它可以到按钮或输入框,也可以大到整个菜单栏,甚至是整个页面视图。

创建组件的优势在于,你只需编写一次组件的显示逻辑(HTML/CSS)以及与用户交互的逻辑(JS),然后就可以在整个应用程序中使用它。

和往常一样,我们将从最简单的例子——按钮——开始。
首先,让我们定义这个组件的蓝图模板awesome-button,我们暂且称之为“按钮”!

我们来定义一个新的awesome-button组件。将这段代码复制到你的new Vue声明上方。

Vue.component('awesome-button', {
  template: `<button @click="clickHandler">Click me for some awesomeness</button>`,
  methods: {
    clickHandler() {
      alert('YAAAS 😎');
    }
  }
});
Enter fullscreen mode Exit fullscreen mode

我们在第一天添加的脚本标签Vue中获取的对象包含我们在这里调用的方法。正如预期的那样,它允许我们创建一个新组件。我们设置的第一个参数是一个字符串,它将作为我们组件的名称。Vue.jscomponent

第二个参数是一个 JavaScript 对象object,令人惊讶的是,它实际上与我们之前用于主组件的配置对象类型相同Vue instance!这对你意味着什么?这意味着你已经知道如何为这个新组件分配属性和方法。

在上面的例子中,你会注意到一个区别——template属性。这里我们声明了一个字符串(注意,我们还使用了引号将其括起来,这样以后如果需要声明多行,就无需连接多个字符串),这个字符串将包含this 组件的实际 HTML 代码。在这个例子中,一个简单的<button>标签就足够了。

如果你现在刷新页面,什么都不会发生。还记得我之前说过这只是个蓝图/模板吗?现在是时候把它实际渲染到页面上了。

前往<div id="app">我们放置所有标记的位置,并创建一个新<awesome-button>元素。

你的HTML代码现在应该看起来像这样:

<div id="app">
  <awesome-button></awesome-button>
</div>
Enter fullscreen mode Exit fullscreen mode

加载页面后,您现在应该可以看到按钮已经渲染到页面上了。awesome-button在页面上放置几个,或者十个(读者自行决定)标签。现在您应该开始感受到组件的强大之处了,不过我觉得我们还可以再深入探讨一下。

额外提示:如果您好奇心强,不妨查看一下您的代码page source,并使用浏览器的开发者工具将其与该inspect功能进行比较。页面加载时,Vue.js会使用该<awesome-button>标签作为占位符,指示它应该将解析后的模板内容放置在哪里。

第二级——一些更有用的东西

让我们回顾一下上周的例子,并继续处理我们的games数据。

首先,让我们将这个游戏数组重新添加到data()Vue实例中。

const app = new Vue({
  el: '#app',
  data: {
    games: [
      { name: 'Super Mario 64', console: 'Nintendo 64', rating: 4 },
      { name: 'The Legend of Zelda Ocarina of Time', console: 'Nintendo 64', rating: 5 },
      { name: 'Secret of Mana', console: 'Super Nintendo', rating: 4 },
      { name: 'Fallout 76', console: 'Multiple', rating: 1 },
      { name: 'Super Metroid', console: 'Super Nintendo', rating: 6 }
    ]
  }
});
Enter fullscreen mode Exit fullscreen mode

和以前一样,欢迎您随时更新您喜欢的标题。

不过这一次,我们将创建一个game-card组件,用它来显示我们的数据会更有意义。

准备好了吗?

Vue.component('game-card', {
  props: ['gameData'],
  template: `
    <div style="border-radius: .25rem; border: 1px solid #ECECEC; width: 400px; margin: 1rem; padding: 1rem;">
      <h2>{{ gameData.name }} - <small>{{ gameData.console }}</small></h2>

      <span v-for="heart in gameData.rating">❤️</span>

      <button @click="increaseRating">Increase Rating</button>
    </div>
  `,
  methods: {
    increaseRating() {
      // this.game.rating++ ?
    }
  }
});
Enter fullscreen mode Exit fullscreen mode

别慌,你已经知道这些/大部分内容了😃!

我们正在创建一个新的对象Vue.component并为其命名game-card。让我们先跳过props这一步,看看这个对象template

这里没有什么新内容,只是你可能已经注意到,我们正在访问一个属性的属性,gameData该属性没有在内部定义data,而是在props属性内部定义。

接下来,我们声明methods对象,并increaseRating在其中定义方法。我特意注释掉了this.game.rating++你可能想要调用这个特定函数的部分,但它不起作用!现在是时候讨论props……

组件属性

自定义组件的一个保留属性是 `variables` props。最简单的形式是,它接受一个字符串数组定义变量。在之前的示例中,我们告诉组件蓝图/模板,我们希望它能够识别一个名为 `variables` 的属性game

Props这将使我们能够从外部向组件传递信息!让我们来看一个实际的例子,这样更容易理解。

首先,让我们向应用程序中添加一些<game-card>项目。我们将像之前一样使用v-for循环,但这次我们将在自定义组件之上进行循环!

<div id="app">
  <awesome-button></awesome-button>
  <hr>
  <game-card v-for="game in games" :game-data="game" :key="game.name"></game-card>
</div>
Enter fullscreen mode Exit fullscreen mode

目前有很多game说法被提及,所以我们来详细分析一下。

第一步,我们要创建<game-card>组件,就像我们之前讨论的那样。

v-for="game in games"接下来,我们像上周那样添加循环。这将创建一个game变量来保存循环中的当前游戏,我们可以立即使用它!

最后,我们给模板的prop赋值,gameData这里赋的就是game循环中得到的变量。注意,这里我们用连字符代替了驼峰命名法,game-data因为 HTML 不区分大小写。如果你觉得难以理解,可以尝试用对象的方式来思考。我们做的类似于……game-card.props.gameData = game

别忘了:key

这里有个很大的陷阱要提一下,我们把球传给game了我们的game-data道具,但其实背后还有个:机关。你注意到了吗?

当我们给组件实例赋值时,有两种方法。以我们的例子为例,我们可以在赋值:语句前加上 `!`(这是 `!` 的简写)。这样可以确保 `!`后面v-bind:传递的数据JavaScript 用作变量或实际的代码片段。="<here>"

如果你输入的是 `!` gameData="game",那么Vue会将其视为将字符串gameData赋值给prop 。例如:`!` "game"game-card.props.gameData = "game"

不妨暂时放下理论,实际在浏览器中运行一下这段代码。你会发现,正如预期的那样,我们<game-card>组件的整个模板会针对每个元素进行渲染game

这样做最大的好处是,如果我们对 HTML 进行更改,应用程序中的所有代码都会同步更新。

此外,最重要的是组件允许你将特定组件的逻辑封装起来game-card。让我们再回顾一下这个increaseRating()方法。

组件数据与属性

组件的属性实际上是一个非常复杂的话题,但有一条非常重要的经验法则你必须始终牢记:属性绝对不能在组件内部修改。

事实上,如果你尝试这样做,Vue会在控制台中抛出各种警告并发出警告——因为这必然会导致意想不到的行为。如果你想了解更多,可以阅读以下文档:在 Vue2 中修改 props 是一种反模式

rating那么,我们该如何修改组件存储中的值呢?关键就在问题本身!我们需要将其复制prop到我们的存储中data,才能真正对其进行修改。

首先,让我们将它添加datagame-card组件中,并为其分配一个新的不冲突的名称(如果 props 和 data props 名称相同,则会冲突),然后用 prop 的值预先填充它。

data() {
  return {
    game: {...this.gameData}
  }
},
Enter fullscreen mode Exit fullscreen mode

这里有几点需要注意,但在此之前,如果你还不了解它的{...gameData}作用,它是一个展开运算符。我不会在这里详细解释,稍后会写一篇简短的文章来讲解,但简单来说,我们是在复制属性gameData因为我们永远不想在子对象中修改它。

data房产的return

当我们学习这个data属性时,我告诉过你它需要包含一个带有所有必要属性的对象,这也是我们一直以来在主Vue 实例中的做法。但是对于组件来说,我们实际上需要将其变成一个函数,方法是添加 ` ()$ ('$('$('$('$('$('$('$( return'$('$('$('$('$('$('$('$('$('$('$('$('$('$('$('$('$(1$(('$(('$(( ( ...) )`

但为什么?!😫

简单来说,你的组件可以有一个或多个实例,对吗?

每个实例都需要一个唯一的数据对象!你肯定不想让data所有实例共享同一个对象,否则它们都会共享同一个对象title——这样一来,整个应用程序的意义就荡然无存了。

所以,之所以把它做成一个函数返回一个对象,是因为Vue可以在每次创建我们的对象时调用这个函数game-cards。这样,​​每个对象都会获得一个唯一的数据对象来进行操作!

获取我们的道具:

当我们创建game` data`属性时,我们会对其进行赋值this.gameData,所以这里有几点需要注意。`data` 属性props可以像本地状态属性一样,通过 `.` 在组件脚本中访问。因此,在这里,我们将 `data` 属性的值设置为等于该属性的值。thisdatagamegameData

这意味着现在我们需要更新 HTML,所以在组件内部切换引用,gameData如下game所示:

<div style="border-radius: .25rem; border: 1px solid #ECECEC;">
  <h2>{{ game.name }} - <small>{{ game.console }}</small></h2>

  <span v-for="heart in game.rating">❤️</span>

  <button @click="increaseRating">Increase Rating</button>
</div>
Enter fullscreen mode Exit fullscreen mode

在浏览器中再次运行此程序,您应该会得到相同的结果。

终于,我们的increaseRating方法可以正常运行了!请前往该方法,并将注释替换为以下内容:

methods: {
  increaseRating() {
    this.game.rating++
  }
}
Enter fullscreen mode Exit fullscreen mode

每次点击,我们都会递增组件的内部 data属性,该属性保存的是game“s rating”,而不是 prop。


关于组件有很多理论需要学习,我只是略窥门径,但希望你现在能更清楚地了解为什么像Vue这样的框架如此流行,以及使用起来如此有趣。

从现在开始,我们将开始学习一些我认为是中级的主题,例如computed属性、watchers组件events等等。希望你们很快就能兴奋地了解 Vue 的核心内容。

如果您需要,这里是今天的完整代码,感谢阅读!🤗😋

<html>

<head>
  <title>Vue 101</title>
</head>

<body>
  <div id="app">
    <awesome-button></awesome-button>
    <game-card v-for="game in games" :game-data="game" :key="game.name"></game-card>
  </div>

  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

  <script>
    Vue.component('awesome-button', {
      template: `<button @click="clickHandler">Click me for some awesomeness</button>`,
      methods: {
        clickHandler() {
          alert('YAS. 😎');
        }
      }
    });

    Vue.component('game-card', {
        props: ['gameData'],
        data() {
          return {
            game: {...this.gameData}
          }
        },
        template: `<div style="border-radius: .25rem; border: 1px solid #ECECEC; width: 400px; margin: 1rem; padding: 1rem;">
          <h2>{{ game.name }} - <small>{{ game.console }}</small></h2>

          <span v-for="heart in game.rating">❤️</span>

          <button @click="increaseRating">Increase Rating</button>
        </div>`,
        methods: {
          increaseRating() {
            this.game.rating++
          }
        }
      });

    const app = new Vue({
      el: '#app',
      data: {
        games: [
          { name: 'Super Mario 64', console: 'Nintendo 64', rating: 4 },
          { name: 'The Legend of Zelda Ocarina of Time', console: 'Nintendo 64', rating: 5 },
          { name: 'Secret of Mana', console: 'Super Nintendo', rating: 4 },
          { name: 'Fallout 76', console: 'Multiple', rating: 1 },
          { name: 'Super Metroid', console: 'Super Nintendo', rating: 6 }
        ]
      }
    });
  </script>
</body>

</html>
Enter fullscreen mode Exit fullscreen mode
文章来源:https://dev.to/marinamosti/hands-on-vuejs-for-beginners-part-5--1jbi