Vue3x基础 - 介绍

介绍

提示
已经了解Vue2且仅想知道Vue3有哪些新功能?请参阅迁移指南

Vue.js是什么?

Vue(读音/vjuː/,像view一样发音)是一套用于构建用户界面的先进框架,不像其他僵化的框架,Vue被设计为全面的渐进式可扩展框架。该核心库只关注视图层,使用非常简单且易于与其他第三方类库或现有项目进行集成。另一方面当与现代化工具以及支持类库结合使用时,Vue也完全能够为复杂的单页面应用(SPA)提供完美支持。

开始使用

提示
官方手册认为HTML,Css,JavaScript你已达到中等水平。如果你是前端开发的新手,直接跳过基础学习Vue框架不是一个好主意,建议掌握基础知识以后再回来!了解其他框架对学习Vue有帮助,但也不是必须的。

最佳学习习Vue.js方法是验证使用Hello World示例。可以在新标签打开这个链接,跟着我们一起学习这些基础示例。

安装节已提供了多种安装Vue的方式。说明:不推荐初学者一开始就使用vue-cli,特别是你对基于Node.js构建工具不是非常熟悉的情况下。

声明式渲染

Vue.js的核心是让我们很简单的使用模板语法声明式渲染数据至DOM元素上。
完整代码如下:

<!DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>vue demo1</title>
    <script src="https://unpkg.com/vue@next"></script>
   </head>
   <body>
        <div id="counter">
            Counter:{{counter}} <br />
        </div>
   </body>
   <script type="text/javascript">
    const Counter = {
        data() {
            return {
                counter: 0
            }
        }
    }
    Vue.createApp(Counter).mount("#counter")
   </script>
</html>

运行结果如下:


hello world

我们已成功创建第一个Vue应用!这看起来跟渲染一个字符模板非常相似,但Vue在后台做了大量的工作。数据和DOM元素建立起了关联,并且所有都是响应式的。我们怎么知道是响应式的?看看下面这个例子,counter这个变量每秒增加,你将会看到界面上的DOM元素是如何变化的!

<!DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>vue demo1</title>
    <script src="https://unpkg.com/vue@next"></script>
   </head>
   <body>
        <div id="app">
            Counter:{{counter}} <br />
        </div>
   </body>
   <script type="text/javascript">
    const Counter = {
        data() {
            return {
                counter: 0
            }
        },
        mounted() {
            setInterval(() => {
              this.counter++
            }, 1000)
      }
    }
    Vue.createApp(Counter).mount("#app")
   </script>
</html>

除了文本插值,可以像这样绑定元素属性:

<!DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>vue demo1</title>
    <script src="https://unpkg.com/vue@next"></script>
   </head>
   <body>
        <div id="app">
            <span v-bind:title="message">
                鼠标放到我上面,将会看到动态绑定的title信息
            </span>
        </div>
   </body>
   <script type="text/javascript">
    const Counter = {
        data() {
            return {
                message: "页面载入时间为:"+ new Date().toLocaleString()
            }
        }
    }
    Vue.createApp(Counter).mount("#app")
   </script>
</html>
title插值

我们学习到了一些新的东西。你看到的v-bind属性我们称之为指令。指令是以v-打头表明是由Vue提供的特殊属性,你可能已经猜到了,他们可以响应式的渲染DOM。这里我们基本上可以说“这个实例是通过message这个变量动态的绑定到了html元素上”。

处理用户输入

为了让用户和界面进行交互,我们可以使用v-on指令绑定一个事件监听,调用在当前实例中定义的方法:

<!DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>vue demo1</title>
    <script src="https://unpkg.com/vue@next"></script>
   </head>
   <body>
        <div id="app">
            <span v-bind:title="message">
                {{message}}
                <br />
                <button v-on:click="reverseMessage">反转上文字</button>
            </span>
        </div>
   </body>
   <script type="text/javascript">
    const Counter = {
        data() {
            return {
                title: "页面载入时间为:"+ new Date().toLocaleString(),
                message: "鼠标放到我上面,将会看到动态绑定的title信息"
            }
        },
        methods: {
            reverseMessage() {
                this.message = this.message.split('').reverse().join('')
            }
        }
    }
    Vue.createApp(Counter).mount("#app")
   </script>
</html>

点击按钮后,message内容被反转为:


反转文字

注意这个方法没有使用DOM就更新了界面上的内容 - 所有DOM都由Vue进行操作,而你的代码只要关注具体的业务逻辑即可。
同时Vue提供了v-model指令,可以轻而易举的实现表单文本框和界面元素(app state)的双向绑定:

<!DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>vue demo1</title>
    <script src="https://unpkg.com/vue@next"></script>
   </head>
   <body>
        <div id="app">
            <p>{{ message }} </p>
            <input v-model="message" />
        </div>
   </body>
   <script type="text/javascript">
    const Counter = {
        data() {
            return {
                message: "你好世界!"
            }
        },
    }
    Vue.createApp(Counter).mount("#app")
   </script>
</html>
你好世界

(你可以想象一下,用jquery,你需要多少行代码来实现双向绑定?其实我不是黑jquery,当年jquery节省了我们大量时间调浏览器兼容性和可以调用一些强大的方法)

条件分支及循环

非常容易切换一个元素的显示状态:

<!DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>vue demo1</title>
    <script src="https://unpkg.com/vue@next"></script>
   </head>
   <body>
        <div id="app">
            <span v-if="seen">看的见我?看不见我?</span>
        </div>
   </body>
   <script type="text/javascript">
    const Counter = {
        data() {
            return {
                seen: true
            }
        },
    }
    Vue.createApp(Counter).mount("#app")
   </script>
</html>

(只需要控制seen变量为true或false就能显示/隐藏span标签)
这个示例演示了DOM元素不仅能绑定字符和属性,同时也可以绑定DOM结构(控制DOM的展示?),另外,Vue提供了强大的转场效果系统,当我们在界面上插入/更新/移除元素时会自动应用转场效果。

还有很多其他指令,每个都有自己独特的功能。例如v-for指令可以将一个数组的每个元素展示成一个列表:

<!DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>vue demo1</title>
    <script src="https://unpkg.com/vue@next"></script>
   </head>
   <body>
        <div id="app">
            <ul>
                <li v-for="(item,index) in todos">
                    {{ item.week }} : {{ item.text }}
                </li>
            </ul>
        </div>
   </body>
   <script type="text/javascript">
    const app = {
        data() {
            return {
                todos: [
                    {"week":"周一","text":"学习java"},
                    {"week":"周二","text":"学习oracle"},
                    {"week":"周三","text":"学习python"},
                    {"week":"周四","text":"学习uni-app"},
                    {"week":"周五","text":"看电影"},
                    {"week":"周六","text":"休息"},
                    {"week":"周日","text":"休息"}
                ]
            }
        },
    }
    Vue.createApp(app).mount("#app")
   </script>
</html>

运行结果如下:


列表

组件化

组件系统是Vue中另一个非常重要的概念,因为是一种抽像,允许我们使用小型 、自包含、可反复使用的组件构建大型应用。如果我们仔细想一想,几乎所有的用户界面都可以抽像成一个组件树。


组件树

Vue中,组件本质上是拥有预定义选项的实例。Vue中注册组件也很简单:像应创建应用对象一样创建组件,然后在父页面中components选项中进行定义 :

//js
// 创建Vue应用
const app = Vue.createApp(...)

// Define a new component called todo-item
app.component('todo-item', {
  template: `<li>This is a todo</li>`
})

// 挂载Vue应用
app.mount(...)

现在你就可以在其他页面的模板中调用这个组件了

<ol>
  <!-- 创建一个todo-item组件的实例 -->
  <todo-item></todo-item>
</ol>

但这样每个todo渲染的文字内容都是一样的,没有意思。我们可以从父页面传递数据到子组件。接下来让我们改造下组件定义来接收一个prop:

app.component('todo-item', {
  props: ['todo'],
  template: `<li>{{ todo.text }}</li>`
})

然后我们在使用组件的地方可以传递不同的todo参数:

<div id="todo-list-app">
  <ol>
    <!--
    现在我们提供含有todo-item的todo对象变量,
    这意味着组件内容是动态变化的。
    我们同时需要为每个组件指定一个“key”,后面再做解释。
    -->
    <todo-item
      v-for="item in groceryList"
      v-bind:todo="item"
      v-bind:key="item.id"
    ></todo-item>
  </ol>
</div>
const TodoList = {
  data() {
    return {
      groceryList: [
        { id: 0, text: '蔬菜' },
        { id: 1, text: '芝士' },
        { id: 2, text: '任何人类能吃的食品 }
      ]
    }
  }
}

const app = Vue.createApp(TodoList)

app.component('todo-item', {
  props: ['todo'],
  template: `<li>{{ todo.text }}</li>`
})

app.mount('#todo-list-app')

看一个完整的例子:

<html lang="en-US">
    <head>
      <meta charset="utf-8">
      <meta name="viewport" content="width=device-width,initial-scale=1">
      <title>vue demo1</title>
      <script src="https://unpkg.com/vue@next"></script>
     </head>
     <body>
          <div id="app">
              <ul>
                 <todo-item
                    v-for="(item,index) in todos"
                    v-bind:todo="item"
                    v-bind:key="index"
                 ></todo-item>
              </ul>
          </div>
     </body>
     <script type="text/javascript">
      const todoList = {
          data() {
              return {
                  todos: [
                      {"week":"周一","text":"学习java"},
                      {"week":"周二","text":"学习oracle"},
                      {"week":"周三","text":"学习python"},
                      {"week":"周四","text":"学习uni-app"},
                      {"week":"周五","text":"看电影"},
                      {"week":"周六","text":"休息"},
                      {"week":"周日","text":"休息"}
                  ]
              }
          }
      }
      const app = Vue.createApp(todoList)
      app.component('todo-item',{
          props: ['todo'],
          template: '<li>{{todo.week}}:{{todo.text}}</li>'
      })
      app.mount("#app")
     </script>
  </html>

这是一个非预想中的示例,但是我们已将应用分隔成两个单元,且父应用通过props接口合乎逻辑的分隔出了一个子组件,我们可以进一步的完善<todo-item>组件实现复杂的模板和逻辑而不影响父应用。
在大型应用中,有必要将整个应用分割成不同的组件使得开发更加便于管理。在后续章节中我们会更多的谈到组件,下面简单演示一个(想像)示例展示组件是如何在模板中使用的:

<div id="app">
  <app-nav></app-nav>
  <app-view>
    <app-sidebar></app-sidebar>
    <app-content></app-content>
  </app-view>
</div>

关于自定义标签

你可能已经注意到了,Vue组件和HTML的自定义标签非常像,属于Web 组件规则的一部分。这是因为Vue组件语法比Web组件规则更加宽松的模型。举个例子,Vue组件实现了插槽API和特殊属性。但是仍然有一些不同点:

  1. WEB组件已经被确定但不是所有浏览器能原生支持。Safari 10.1+,Chrome 54+ 和Firefox 63+ 原生已支持WEB组件。相对而言,Vue组件一如既往的在所有支持的浏览器中均能工作(兼容IE11及以上)。如果有必要,Vue组件还可以放置进一个原生的标签中。
  2. Vue组件提供了简单的定制标签提不具备的功能,突出的包括组件间数据流,标准事件通信以及构建工具集成。

即便Vue内部并不使用定制标签,但在使用和发布自定义标签时仍然具备很强的互操作性。Vue CLI同时也提供将Vue组件注册为原生自定义标签的支持。

准备好了吗?

我们已经对Vue.js核心功能做了简要的介绍 - 手册的剩余部分,我们将再次详细介绍并包含很多高级功能点和细节,所以,请务必通读该教程!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,504评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,434评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,089评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,378评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,472评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,506评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,519评论 3 413
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,292评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,738评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,022评论 2 329
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,194评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,873评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,536评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,162评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,413评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,075评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,080评论 2 352

推荐阅读更多精彩内容

  • 夜莺2517阅读 127,717评论 1 9
  • 版本:ios 1.2.1 亮点: 1.app角标可以实时更新天气温度或选择空气质量,建议处女座就不要选了,不然老想...
    我就是沉沉阅读 6,887评论 1 6
  • 我是黑夜里大雨纷飞的人啊 1 “又到一年六月,有人笑有人哭,有人欢乐有人忧愁,有人惊喜有人失落,有的觉得收获满满有...
    陌忘宇阅读 8,532评论 28 53
  • 兔子虽然是枚小硕 但学校的硕士四人寝不够 就被分到了博士楼里 两人一间 在学校的最西边 靠山 兔子的室友身体不好 ...
    待业的兔子阅读 2,597评论 2 9