• vue使用&Mac+idea的vue开发环境配置


    开发环境配置

    npm+vue开发环境配置

    看博主都推荐使用vscode开发vue

    硬要使用idea的话,就需要安装vue.js插件

    在这里插入图片描述

    1、先安装vue环境

    brew install nodejs

    或者到官网 http://nodejs.cn/download/ 下载安装,速度快

    安装成功后可查看版本信息node -v

    我安装的版本是v17.9.0


    npm是随同nodejs一起安装的包管理工具,能解决nodejs代码部署上的很多问题,常见的使用场景有以下几种:

    • 允许用户从NPM服务器下载别人编写的第三方包到本地使用。
    • 允许用户从NPM服务器下载并安装别人编写的命令行程序到本地使用。
    • 允许用户将自己编写的包或命令行程序上传到NPM服务器供别人使用。

    输入npm -v来测试是否成功安装。

    我安装的版本是8.5.5

    npm基本使用

    npm install  <package>        # 本地安装
    npm install  <package>   -g   # 全局安装
    npm list –g                   #查看所有全局安装的模块
    npm uninstall  <package>      # 卸载模块
    npm update     <package>      # 更新模块
    
    • 1
    • 2
    • 3
    • 4
    • 5

    但npm用国外的服务器,速度比较慢,淘宝提供了一个cnpm命令,可以从淘宝镜像下载,淘宝镜像与官方同步频率目前为 10分钟 一次以保证尽量与官方服务同步。设置环境变量可以使得住任意目录下都可以使用cnpm、vue等命令,而不需要输入全路径。


    2、获取nodejs模块安装目录访问权限

    sudo chmod -R 777 /usr/local/lib/node_modules/
    
    • 1

    3、安装淘宝镜像

    cnpm用法和npm相同。

    npm install -g cnpm --registry=https://registry.npm.taobao.org
    
    • 1

    Ps:我看人家文章是因为在这一步失败,提示没有权限才有第2步在前的。

    我在第二步的时候,没找到那个文件夹,直接3,没有报错嘻嘻。

    4、安装webpack模版

    cnpm install webpack -g
    
    • 1

    5、安装vue脚手架

    cnpm install vue-cli -g
    
    • 1

    验证安装成功,查看版本号:vue --version,我的版本是2.9.6

    ps:在5之后(没有第4步也可以),就可以在idea里去直接创建新项目。(在JavaScript下找到vue.js,创建一个vue项目)

    运行后,在浏览器输入http://localhost:8080/。

    安装项目依赖:在idea里找到Terminal,输入cnpm install即可

    6、在硬盘上找一个文件夹放工程用的,在终端中进入该目录

    cd 目录路径
    
    • 1

    7、根据模板创建项目

    vue init webpack 工程名字<工程名字不能用中文>
    
    //例如
    vue init webpack demotree
    
    • 1
    • 2
    • 3
    • 4

    会有一些初始化的设置,如下输入:

    Target directory exists. Continue? (Y/n)直接回车默认(然后会下载 vue2.0模板,这里可能需要 连代理 )

    Project name (vue-test)直接回车默认。我写的是demoapple。

    Project description (A Vue.js project) 直接回车默认

    Author 写你自己的名字。我写的是shannon。

    cd demo1命令进入创建的工程目录

    注:最后三步⬇️都是要进入到当前工程目录后执行的。

    8、安装项目依赖

    npm install
    
    • 1

    比较慢,需要有点耐心……

    我的运行失败了

    9、安装 vue 路由模块vue-router和网络请求模块vue-resource

    cnpm install vue-router vue-resource --save
    
    • 1

    这个也运行失败了

    10、启动项目

    Terminal 输入npm run dev或者npm run serve命令,这主要看项目的package.json文件里的内容,博主前端项目在scripts中,并没有dev,而是serve,所以用npm run serve命令
    在这里插入图片描述

    我的是dev哈哈哈哈


    如果有产生错误,可能原因1:node和node-sass有版本对应关系。
    解决办法:首先先查询node和node-sass版本对应表,要么升版本要么降版本。

    以上错误俺没有遇到,俺遇到了新错误:

    那我就cnpm install webpack-dev-server -g 试试看

    木有解决

    尝试从idea创建项目,成功。

    在这里插入图片描述

    然后点击运行,就可以了


    成功运行

    mac降低node版本

    1、安装node版本管理模块 n

    sudo npm install n -g
    
    • 1

    2、可以根据自己的需要选择安装版本[可选]

    安装稳定版
    sudo n stable
    
    安装最新版
    sudo n latest
    
    版本降级/升级
    sudo n 版本号 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    可能原因2:Error: Cannot find module ‘node-sass

    解决办法是在Terminal里输入命令cnpm install node-sass@latest,然后重新运行

    vue语言

    https://www.runoob.com/vue2/vue-tutorial.html

    https://blog.csdn.net/weixin_46349544/article/details/124080704

    Vue.js(读音 /vjuː/, 类似于 view) 是一套构建用户界面的渐进式框架。

    Vue 只关注视图层, 采用自底向上增量开发的设计。

    Vue 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件。

    Vue.js安装:

    1、独立版本

    我们可以在 Vue.js 的官网上直接下载 vue.min.js 并用 <script> 标签引入。

    2、使用 CDN 方法

    3、NPM 方法(我采用的就是这个方法)

    vue的目录结构

    img

    目录说明:

    目录/文件说明
    build项目构建(webpack)相关代码
    config配置目录,包括端口号等。我们初学可以使用默认的。
    node_modulesnpm 加载的项目依赖模块
    src这里是我们要开发的目录,基本上要做的事情都在这个目录里。里面包含了几个目录及文件:assets: 放置一些图片,如logo等。components: 目录里面放了一个组件文件,可以不用。App.vue: 项目入口文件,我们也可以直接将组件写这里,而不使用 components 目录。main.js: 项目的核心文件。
    static静态资源目录,如图片、字体等。
    test初始测试目录,可删除
    .xxxx文件这些是一些配置文件,包括语法配置,git配置等。
    index.html首页入口文件,你可以添加一些 meta 信息或统计代码啥的。
    package.json项目配置文件。
    README.md项目的说明文档,markdown 格式

    起步

    尝试修改初始化的代码HelloWorld.vue:

    修改后运行效果

    在这里插入图片描述


    每个 Vue 应用都需要通过实例化 Vue 来实现。

    语法格式如下:

    var vm = new Vue({
      // 选项
    })
    
    • 1
    • 2
    • 3
    <!-- 准备好一个容器 -->
    <div id="vue_det">
        <h1>site : {{site}}</h1>
        <h1>url : {{url}}</h1>
        <h1>{{details()}}</h1>
    </div>
    <script type="text/javascript">
        var vm = new Vue({
            el: '#vue_det',//el用于指定当前Vue实例为哪个容器服务,值通常为css选择器字符串。
            data: {//data中用于存储数据,数据供el所指定的容器去使用
                site: "菜鸟教程",
                url: "www.runoob.com",
                alexa: "10000"
            },
            methods: {
                details: function() {
                    return  this.site + " - 学的不仅是技术,更是梦想!";
                }
            }
        })
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    看到在 Vue 构造器中有一个el 参数,它是 DOM 元素中的 id。在上面实例中是div元素的 id 为 vue_det。

    data 用于定义属性,实例中有三个属性分别为:site、url、alexa。

    methods 用于定义的函数,可以通过 return 来返回函数值。

    {{ }} 用于输出对象属性和函数返回值。

    当一个 Vue 实例被创建时,它向 Vue 的响应式系统中加入了其 data 对象中能找到的所有的属性。当这些属性的值发生改变时,html 视图将也会产生相应的变化。

    data与el的2种写法
    1.el有2种写法
    (1).new Vue时候配置el属性。
    (2).先创建Vue实例,随后再通过vm.$mount(‘#root’)指定el的值。
    2.data有2种写法
    (1).对象式
    (2).函数式
    如何选择:目前哪种写法都可以,以后学习到组件时,data必须使用函数式,否则会报错。
    3.一个重要的原则:
    由Vue管理的函数,一定不要写箭头函数,一旦写了箭头函数,this就不再是Vue实例了。

    除了数据属性,Vue 实例还提供了一些有用的实例属性与方法。它们都有前缀 $,以便与用户定义的属性区分开。

    <div id="vue_det">
        <h1>site : {{site}}</h1>
        <h1>url : {{url}}</h1>
        <h1>Alexa : {{alexa}}</h1>
    </div>
    <script type="text/javascript">
    // 我们的数据对象
    var data = { site: "菜鸟教程", url: "www.runoob.com", alexa: 10000}
    var vm = new Vue({
        el: '#vue_det',
        data: data
    })
     
    document.write(vm.$data === data) // true
    document.write("<br>") 
    document.write(vm.$el === document.getElementById('vue_det')) // true
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    模版语法

    Vue.js 使用了基于 HTML 的模板语法,允许开发者声明式地将 DOM 绑定至底层 Vue 实例的数据。

    Vue.js 的核心是一个允许你采用简洁的模板语法来声明式的将数据渲染进 DOM 的系统。

    结合响应系统,在应用状态改变时, Vue 能够智能地计算出重新渲染组件的最小代价并应用到 DOM 操作上。

    插值

    {{xxx}},xxx可自动读取到data中的所有属性。

    1、文本

    使用 {{...}}(双大括号)的文本插值。

    2、html

    使用 v-html 指令用于输出 html 代码

    <div id="app">
        <div v-html="message"></div>
    </div>
        
    <script>
    new Vue({
      el: '#app',
      data: {
        message: '<h1>菜鸟教程</h1>'
      }
    })
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    3、属性

    HTML 属性中的值应使用 v-bind 指令。

    以下实例判断 use 的值,如果为 true 使用 class1 类的样式,否则不使用该类。

    <style>
    .class1{
      background: #444;
      color: #eee;
    }
    </style>
    <body>
    <script src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js"></script>
    
    <div id="app">
      <label for="r1">修改颜色</label><input type="checkbox" v-model="use" id="r1">
      <br><br>
      <div v-bind:class="{'class1': use}">
        v-bind:class 指令
      </div>
    </div>
        
    <script>
    new Vue({
        el: '#app',
      data:{
          use: false
      }
    });
    </script>
    </body>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    4、表达式

    Vue.js 都提供了完全的 JavaScript 表达式支持。

    <div id="app">
        {{5+5}}<br>
        {{ ok ? 'YES' : 'NO' }}<br>
        {{ message.split('').reverse().join('') }}
        <div v-bind:id="'list-' + id">菜鸟教程</div>
    </div>
        
    <script>
    new Vue({
      el: '#app',
      data: {
        ok: true,
        message: 'RUNOOB',
        id : 1
      }
    })
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    注意区分:js表达式 和 js代码(语句)
    1.表达式:一个表达式会产生一个值,可以放在任何一个需要值的地方:
    (1). a
    (2). a+b
    (3). demo(1)
    (4). x === y ? ‘a’ : ‘b’

    2.js代码(语句)
    (1). if(){}
    (2). for(){}

    指令

    指令是带有 v- 前缀的特殊属性。

    指令用于在表达式的值改变时,将某些行为应用到 DOM 上。

    <div id="app">
        <p v-if="seen">现在你看到我了</p><!-- v-if 指令将根据表达式 seen 的值(truefalse )来决定是否插入 p 元素。-->
    </div>
        
    <script>
    new Vue({
      el: '#app',
      data: {
        seen: true
      }
    })
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    参数:在指令后以冒号指明。

    <div id="app">
        <pre><a v-bind:href="url">菜鸟教程</a></pre>
      <!-- href 是参数,告知 v-bind 指令将该元素的 href 属性与表达式 url 的值绑定。-->
    </div>
        
    <script>
    new Vue({
      el: '#app',
      data: {
        url: 'http://www.runoob.com'
      }
    })
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    v-on 指令,它用于监听 DOM 事件:

    <a v-on:click="doSomething">
      <!--在这里参数是监听的事件名。-->
    
    • 1
    • 2

    修饰符:是以半角句号 . 指明的特殊后缀,用于指出一个指令应该以特殊方式绑定。例如,.prevent 修饰符告诉 v-on 指令对于触发的事件调用 event.preventDefault()

    <form v-on:submit.prevent="onSubmit"></form>
    
    • 1
    内置指令

    我们学过的指令:
    v-bind : 单向绑定解析表达式, 可简写为 :xxx
    v-model : 双向数据绑定
    v-for : 遍历数组/对象/字符串
    v-on : 绑定事件监听, 可简写为@
    v-if : 条件渲染(动态控制节点是否存存在)
    v-else : 条件渲染(动态控制节点是否存存在)
    v-show : 条件渲染 (动态控制节点是否展示)


    v-text指令

    作用:向其所在的节点中渲染文本内容。

    与插值语法的区别:v-text会替换掉节点中的内容,{{xx}}则不会。

    v-html指令
    1.作用:向指定节点中渲染包含html结构的内容。

    2.与插值语法的区别:
    (1).v-html会替换掉节点中所有的内容,{{xx}}则不会。
    (2).v-html可以识别html结构。

    3.严重注意:v-html有安全性问题
    (1).在网站上动态渲染任意HTML是非常危险的,容易导致XSS攻击。
    (2).一定要在可信的内容上使用v-html,永不要用在用户提交的内容上

    **v-cloak指令(没有值) **

    本质是一个特殊属性,Vue实例创建完毕并接管容器后,会删掉v-cloak属性。

    使用css配合v-cloak可以解决网速慢时页面展示出{{xxx}}的问题。

    v-once指令

    v-once所在节点在初次动态渲染后,就视为静态内容了。

    以后数据的改变不会引起v-once所在结构的更新,可以用于优化性能。

    v-pre指令

    跳过其所在节点的编译过程。

    可利用它跳过:没有使用指令语法、没有使用插值语法的节点,会加快编译。

    用户输入

    在 input 输入框中我们可以使用 v-model 指令来实现双向数据绑定

    v-bind是单向数据绑定,只存在从 数据data ----->view页面 这条线,不存在从view->data这条线
    v-model是双向数据绑定,data<------>view这两台条线是双向的

    1. 双向绑定一般都应用在表单类元素上(如:input、select等)

    2. v-model:value 可以简写为 v-model,因为v-model默认收集的就是value值。

    	<!-- 普通写法 -->
    			单向数据绑定:<input type="text" v-bind:value="name"><br/>
    			双向数据绑定:<input type="text" v-model:value="name"><br/> 
     <!-- 简写 -->
    		单向数据绑定:<input type="text" :value="name"><br/>
    		双向数据绑定:<input type="text" v-model="name"><br/>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    <div id="app">
        <p>{{ message }}</p>
        <input v-model="message">
    </div>
        
    <script>
    new Vue({
      el: '#app',
      data: {
        message: 'Runoob!'
      }
    })
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    v-model 指令用来在 input、select、textarea、checkbox、radio 等表单控件元素上创建双向数据绑定,根据表单上的值,自动更新绑定的元素的值。

    按钮的事件我们可以使用 v-on 监听事件,并对用户的输入进行响应。

    <div id="app">
        <p>{{ message }}</p>
        <button v-on:click="reverseMessage">反转字符串</button>
    </div>
        
    <script>
    new Vue({
      el: '#app',
      data: {
        message: 'Runoob!'
      },
      methods: {
        reverseMessage: function () {
          this.message = this.message.split('').reverse().join('')
        }
      }
    })
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    过滤器

    过滤器:
    定义:对要显示的数据进行特定格式化后再显示(适用于一些简单逻辑的处理)。
    语法:
    1.注册过滤器:Vue.filter(name,callback)new Vue{filters:{}}
    2.使用过滤器:{{ xxx | 过滤器名}} v-bind:属性 = "xxx | 过滤器名"
    备注:
    1.过滤器也可以接收额外参数、多个过滤器也可以串联
    2.并没有改变原本的数据, 是产生新的对应的数据


    Vue.js 允许你自定义过滤器,被用作一些常见的文本格式化。由 " 管道符 " 指示, 格式如下:

    <!-- 在两个大括号中 -->
    {{ message | capitalize }}
    
    <!-- 在 v-bind 指令中 -->
    <div v-bind:id="rawId | formatId"></div>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    <div id="app">
      {{ message | capitalize }}<!--message-->
    </div>
        
    <script>
    new Vue({
      el: '#app',
      data: {
        message: 'runoob'
      },
      filters: {
        capitalize: function (value) {<!--过滤器函数接受表达式的值作为第一个参数。即 message-->
          if (!value) return ''
          value = value.toString()
          return value.charAt(0).toUpperCase() + value.slice(1)
        }
      }
    })
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    过滤器串联

    {{ message | filterA | filterB }}
    <!--过滤器是 JavaScript 函数,因此可以接受参数:-->
    {{ message | filterA('arg1', arg2) }}
    
    • 1
    • 2
    • 3

    message 是第一个参数,字符串 ‘arg1’ 将传给过滤器作为第二个参数, arg2 表达式的值将被求值然后传给过滤器作为第三个参数。

    缩写

    Vue.js 为两个最为常用的指令提供了特别的缩写:

    v-bind 缩写:

    <!-- 完整语法 -->
    <a v-bind:href="url"></a>
    <!-- 缩写 -->
    <a :href="url"></a>
    
    • 1
    • 2
    • 3
    • 4

    v-on 缩写:

    <!-- 完整语法 -->
    <a v-on:click="doSomething"></a>
    <!-- 缩写 -->
    <a @click="doSomething"></a>
    
    • 1
    • 2
    • 3
    • 4

    条件&循环

    条件判断使用 v-if 指令。

    1、适用于:切换频率较低的场景。

    2、特点:不展示的DOM元素直接被移除。

    可以用 v-else 指令给 v-if 添加一个 “else” 块

    v-else-if 在 2.1.0 新增,顾名思义,用作 v-if 的 else-if 块。可以链式的多次使用

    <div id="app">
        <div v-if="type === 'A'">
          A
        </div>
        <div v-else-if="type === 'B'">
          B
        </div>
        <div v-else-if="type === 'C'">
          C
        </div>
        <div v-else>
          Not A/B/C
        </div>
    </div>
        
    <script>
    new Vue({
      el: '#app',
      data: {
        type: 'C'
      }
    })
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    template标签可以不会破坏HTML的结构,在最后页面渲染的时候,template标签将被移除掉
    template标签不能配合v-show使用只能配合v-if使用

    <!-- v-if与template的配合使用 -->
    			<template v-if="n === 1">
    				<h2>你好</h2>
    			</template>
    
    • 1
    • 2
    • 3
    • 4

    使用 v-show 指令来根据条件展示元素

    1、适用于:切换频率较高的场景。

    2、特点:不展示的DOM元素未被移除,仅仅是使用样式隐藏掉

    注:使用v-if的时,元素可能无法获取到,而使用v-show一定可以获取到。

    <body>
    <div id="app">
        <h1 v-show="ok">Hello!</h1>
    </div>
    	
    <script>
    new Vue({
      el: '#app',
      data: {
        ok: true
      }
    })
    </script>
    </body>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    循环使用 v-for 指令。

    v-for指令:

    1.用于展示列表数据

    2.语法:v-for=“(item, index) in xxx” :key=“yyy”

    3.可遍历:数组、对象、字符串(用的很少)、指定次数(用的很少)

    v-for 指令需要以 site in sites 形式的特殊语法, sites 是源数据数组并且 site 是数组元素迭代的别名。

    v-for 可以绑定数据到数组来渲染一个列表

    <body>
    <div id="app">
      <ol>
        <li v-for="site in sites">
          {{ site.name }}
        </li>
      </ol>
    </div>
    
    <script>
    new Vue({
      el: '#app',
      data: {
        sites: [
          { name: 'Runoob' },
          { name: 'Google' },
          { name: 'Taobao' }
        ]
      }
    })
    </script>
    </body>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    v-for 迭代对象

    v-for 可以通过一个对象的属性来迭代数据

    <div id="app">
      <ul>
        <li v-for="value in object">
        {{ value }}
        </li>
      </ul>
    </div>
     
    <script>
    new Vue({
      el: '#app',
      data: {
        object: {
          name: '菜鸟教程',
          url: 'http://www.runoob.com',
          slogan: '学的不仅是技术,更是梦想!'
        }
      }
    })
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    也可以提供第二个的参数为键名

    <li v-for="(value, key) in object">
        {{ key }} : {{ value }}
    </li>
    
    <!--也可以第三个参数为索引-->
    <li v-for="(value, key, index) in object">
         {{ index }}. {{ key }} : {{ value }}
    </li>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    v-for 迭代整数

    v-for 也可以循环整数

    <div id="app">
      <ul>
        <li v-for="n in 10">
         {{ n }}
        </li>
      </ul>
    </div>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    计算属性

    在插值语法中不要出现太多的计算,如果确实需要经过很多计算,应该写计算属性computed

    计算属性在处理一些复杂逻辑时是很有用的。


    计算属性:
    1.定义:要用的属性不存在,要通过已有属性计算得来。
    2.原理:底层借助了Objcet.defineproperty方法提供的getter和setter。
    3.get函数什么时候执行?
    (1).初次读取时会执行一次。
    (2).当依赖的数据发生改变时会被再次调用。
    4.优势:与methods实现相比,内部有缓存机制(复用),效率更高,调试方便。
    5.备注:
    1.计算属性最终会出现在vm上,直接读取使用即可。
    2.如果计算属性要被修改,那必须写set函数去响应修改,且set中要引起计算时依赖的数据发生改变。

    <div id="app">
      <p>原始字符串: {{ message }}</p>
      <p>计算后反转字符串: {{ reversedMessage }}</p>
    </div>
     
    <script>
    var vm = new Vue({
      el: '#app',
      data: {
        message: 'Runoob!'
      },
      computed: {
        // 计算属性的 getter
        reversedMessage: function () {
          // this 指向 vm 实例
          return this.message.split('').reverse().join('')
        }
      }
    })
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    声明了一个计算属性 reversedMessage 。

    提供的函数将用作属性 vm.reversedMessage 的 getter 。

    vm.reversedMessage 依赖于 vm.message,在 vm.message 发生改变时,vm.reversedMessage 也会更新。

    姓名案例:https://blog.csdn.net/weixin_46349544/article/details/124080704

    <!DOCTYPE html>
    <html>
    	<head>
    		<meta charset="UTF-8" />
    		<title>姓名案例_计算属性实现</title>
    		<!-- 引入Vue -->
    		<script type="text/javascript" src="../js/vue.js"></script>
    	</head>
    	<body>
    		<!-- 准备好一个容器-->
    		<div id="root">
    			姓:<input type="text" v-model="firstName"> <br/><br/>
    			名:<input type="text" v-model="lastName"> <br/><br/>
    			全名:<span>{{fullName}}</span> <br/><br/>
    		</div>
    	</body>
    
    	<script type="text/javascript">
    		Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
    
    		const vm = new Vue({
    			el:'#root',
    			data:{
    				firstName:'张',
    				lastName:'三',
    			},
    			computed:{
    				//完整写法
    				/* fullName:{
    					get(){
    						console.log('get被调用了')
    						return this.firstName + '-' + this.lastName
    					},
    					set(value){
    						console.log('set',value)
    						const arr = value.split('-')
    						this.firstName = arr[0]
    						this.lastName = arr[1]
    					}
    				} */
    				//简写
    				fullName(){
    					console.log('get被调用了')
    					return this.firstName + '-' + this.lastName
    				}
    			}
    		})
    	</script>
    </html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49

    computed setter

    computed 属性默认只有 getter ,不过在需要时也可以提供一个 setter

    var vm = new Vue({
      el: '#app',
      data: {
        name: 'Google',
        url: 'http://www.google.com'
      },
      computed: {
        site: {
          // getter
          get: function () {
            return this.name + ' ' + this.url
          },
          // setter
          set: function (newValue) {
            var names = newValue.split(' ')
            this.name = names[0]
            this.url = names[names.length - 1]
          }
        }
      }
    })
    // 调用 setter, vm.name 和 vm.url 也会被对应更新
    vm.site = '菜鸟教程 http://www.runoob.com';
    document.write('name: ' + vm.name);
    document.write('<br>');
    document.write('url: ' + vm.url);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    在运行 vm.site = '菜鸟教程 http://www.runoob.com'; 时,setter 会被调用, vm.name 和 vm.url 也会被对应更新。

    computed vs methods:

    我们可以使用 methods 来替代 computed,效果上两个都是一样的,但是 computed 是基于它的依赖缓存,只有相关依赖发生改变时才会重新取值。而使用 methods ,在重新渲染的时候,函数总会重新调用执行。

    可以说使用 computed 性能会更好,但如果不希望缓存,可以使用 methods 属性。

    methods: {
      reversedMessage2: function () {
        return this.message.split('').reverse().join('')
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    Vue中的数据代理

    原文链接:https://blog.csdn.net/weixin_46349544/article/details/124080704

    数据代理:通过一个对象代理对另一个对象中属性的操作(读/写)

    			1. Vue中的数据代理:
    						通过vm对象来代理data对象中属性的操作(读/写)
    			1. Vue中数据代理的好处:
    					更加方便的操作data中的数据
    			1. 基本原理:
    				通过Object.defineProperty()把data对象中所有属性添加到vm上。
    				为每一个添加到vm上的属性,都指定一个getter/setter。
    				在getter/setter内部去操作(读/写)data中对应的属性。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    js中的Object.defineproperty方法

    <!DOCTYPE html>
    <html>
    	<head>
    		<meta charset="UTF-8" />
    		<title>回顾Object.defineproperty方法</title>
    	</head>
    	<body>
    		<script type="text/javascript" >
    			let number = 18
    			let person = {
    				name:'张三',
    				sex:'男',
    			}
    
    			Object.defineProperty(person,'age',{
    				// value:18,
    				// enumerable:true, //控制属性是否可以枚举,默认值是false
    				// writable:true, //控制属性是否可以被修改,默认值是false
    				// configurable:true //控制属性是否可以被删除,默认值是false
    
    				//当有人读取person的age属性时,get函数(getter)就会被调用,且返回值就是age的值
    				get(){
    					console.log('有人读取age属性了')
    					return number
    				},
    
    				//当有人修改person的age属性时,set函数(setter)就会被调用,且会收到修改的具体值
    				set(value){
    					console.log('有人修改了age属性,且值是',value)
    					number = value
    				}
    
    			})
    
    			// console.log(Object.keys(person))
    
    			console.log(person)
    		</script>
    	</body>
    </html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    监听属性

    监视属性watch:
    1.当被监视的属性变化时, 回调函数自动调用, 进行相关操作
    2.监视的属性必须存在,才能进行监视!!
    3.监视的两种写法:
    (1).new Vue时传入watch配置
    (2).通过vm.$watch监视


    Vue.js 监听属性 watch,通过 watch 来响应数据的变化

    <div id = "app">
        <p style = "font-size:25px;">计数器: {{ counter }}</p>
        <button @click = "counter++" style = "font-size:25px;">点我</button>
    </div>
    <script type = "text/javascript">
    var vm = new Vue({
        el: '#app',
        data: {
            counter: 1
        }
    });
    vm.$watch('counter', function(nval, oval) {//监听counter变化
        alert('计数器值的变化 :' + oval + ' 变为 ' + nval + '!');
    });
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    千米与米换算示例:

    <div id = "computed_props">
        千米 : <input type = "text" v-model = "kilometers">
         : <input type = "text" v-model = "meters">
    </div>
    <p id="info"></p>
    <script type = "text/javascript">
        var vm = new Vue({
        el: '#computed_props',
        data: {
            kilometers : 0,
            meters:0
        },
        methods: {
        },
        computed :{
        },
        watch : {
            kilometers:function(val) {
                this.kilometers = val;
                this.meters = this.kilometers * 1000
            },
            meters : function (val) {
                this.kilometers = val/ 1000;
                this.meters = val;
            }
        }
        });
        // $watch 是一个实例方法
        vm.$watch('kilometers', function (newValue, oldValue) {
        // 这个回调将在 vm.kilometers 改变后调用
        document.getElementById ("info").innerHTML = "修改前值为: " + oldValue + ",修改后值为: " + newValue;
    })
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    天气案例:

    <!DOCTYPE html>
    <html>
    	<head>
    		<meta charset="UTF-8" />
    		<title>天气案例_监视属性_简写</title>
    		<!-- 引入Vue -->
    		<script type="text/javascript" src="../js/vue.js"></script>
    	</head>
    	<body>
    		<!-- 准备好一个容器-->
    		<div id="root">
    			<h2>今天天气很{{info}}</h2>
    			<button @click="changeWeather">切换天气</button>
    		</div>
    	</body>
    
    	<script type="text/javascript">
    		Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
    		
    		const vm = new Vue({
    			el:'#root',
    			data:{
    				isHot:true,
    			},
    			computed:{
    				info(){
    					return this.isHot ? '炎热' : '凉爽'
    				}
    			},
    			methods: {
    				changeWeather(){
    					this.isHot = !this.isHot
    				}
    			},
    			watch:{
    				//正常写法
    				/* isHot:{
    					// immediate:true, //初始化时让handler调用一下
    					// deep:true,//深度监视
    					handler(newValue,oldValue){
    						console.log('isHot被修改了',newValue,oldValue)
    					}
    				}, */
    				//简写
    				/* isHot(newValue,oldValue){
    					console.log('isHot被修改了',newValue,oldValue,this)
    				} */
    			}
    		})
    
    		//正常写法
    		/* vm.$watch('isHot',{
    			immediate:true, //初始化时让handler调用一下
    			deep:true,//深度监视
    			handler(newValue,oldValue){
    				console.log('isHot被修改了',newValue,oldValue)
    			}
    		}) */
    
    		//简写
    		/* vm.$watch('isHot',(newValue,oldValue)=>{
    			console.log('isHot被修改了',newValue,oldValue,this)
    		}) */
    
    	</script>
    </html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66

    computed和watch之间的区别:
    1.computed能完成的功能,watch都可以完成。
    2.watch能完成的功能,computed不一定能完成,例如:watch可以进行异步操作。

    两个重要的小原则:
    1.所被Vue管理的函数,最好写成普通函数,这样this的指向才是vm 或 组件实例对象。
    2.所有不被Vue所管理的函数(定时器的回调函数、ajax的回调函数等、Promise的回调函数),最好写成箭头函数,
    这样this的指向才是vm 或 组件实例对象。

    样式绑定

    class 与 style 是 HTML 元素的属性,用于设置元素的样式,我们可以用 v-bind 来设置样式属性。

    v-bind 在处理 class 和 style 时, 专门增强了它。表达式的结果类型除了字符串之外,还可以是对象或数组。

    绑定样式:

    1、 class样式
    写法:class=“xxx” xxx可以是字符串、对象、数组。
    字符串写法适用于:类名不确定,要动态获取。
    对象写法适用于:要绑定多个样式,个数不确定,名字也不确定。
    数组写法适用于:要绑定多个样式,个数确定,名字也确定,但不确定用不用。

    2、style样式
    :style="{fontSize: xxx}“其中xxx是动态值。
    :style=”[a,b]"其中a、b是样式对象。

    <!-- 准备好一个容器-->
    		<div id="root">
    			<!-- 绑定class样式--字符串写法,适用于:样式的类名不确定,需要动态指定 -->
    			<div class="basic" :class="mood" @click="changeMood">{{name}}</div> 	
    			<!-- 绑定class样式--数组写法,适用于:要绑定的样式个数不确定、名字也不确定 -->
    		<div class="basic" :class="classArr">{{name}}</div> <br/><br/>
    
    		<!-- 绑定class样式--对象写法,适用于:要绑定的样式个数确定、名字也确定,但要动态决定用不用 -->
    		<div class="basic" :class="classObj">{{name}}</div> <br/><br/>
    
    		<!-- 绑定style样式--对象写法 -->
    		<div class="basic" :style="styleObj">{{name}}</div> <br/><br/>
    		<!-- 绑定style样式--数组写法 -->
    		<div class="basic" :style="styleArr">{{name}}</div>
    	</div>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    1、class属性绑定

    为 v-bind:class 设置一个对象,从而动态的切换 class。实例中将 isActive 设置为 true 显示了一个绿色的 div 块,如果设置为 false 则不显示:

    <style>
    .active {
    	width: 100px;
    	height: 100px;
    	background: green;
    }
    </style>
    </head>
    <body>
    <div id="app">
      <div v-bind:class="{ 'active': isActive }"></div>
    </div>
    
    <script>
    new Vue({
      el: '#app',
      data: {
        isActive: true
      }
    })
    </script>
    </body>
    
    <!--也可以在对象中传入更多属性用来动态切换多个 class-->
    <div class="static"
         v-bind:class="{ 'active' : isActive, 'text-danger' : hasError }">
    </div>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    也可以直接绑定数据里的一个对象:

    <style>
    .active {
    	width: 100px;
    	height: 100px;
    	background: green;
    }
    .text-danger {
    	background: red;
    }
    </style>
    </head>
    <body>
    <div id="app">
      <div v-bind:class="classObject"></div>
    </div>
    
    <script>
    new Vue({
      el: '#app',
      data: {
        classObject: {
          active: true,
          'text-danger': true
        }
      }
    })
    </script>
    </body>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    也可以在这里绑定返回对象的计算属性:classObject

    <script>
    new Vue({
      el: '#app',
      data: {
        isActive: true,
        error: {
          value: true,
          type: 'fatal'
        }
      },
      computed: {
        classObject: function () {
          return {
      base: true,
            active: this.isActive && !this.error.value,
            'text-danger': this.error.value && this.error.type === 'fatal',
          }
        }
      }
    })
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    数组语法

    把一个数组传给 v-bind:class

    <body>
    <div id="app">
    	<div v-bind:class="[activeClass, errorClass]"></div>
    </div>
    
    <script>
    new Vue({
      el: '#app',
      data: {
        activeClass: 'active',
        errorClass: 'text-danger'
      }
    })
    </script>
    </body>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    使用三元表达式来切换列表中的 class:

    <div v-bind:class="[errorClass ,isActive ? activeClass : '']"></div>
    
    • 1

    2、内联样式

    在 v-bind:style 直接设置样式:

    <body>
    <div id="app">
    	<div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }">菜鸟教程</div>
    </div>
    
    <script>
    new Vue({
      el: '#app',
      data: {
        activeColor: 'green',
    	fontSize: 30
      }
    })
    </script>
    </body>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    也可以直接绑定到一个样式对象,让模板更清晰

    <body>
    <div id="app">
      <div v-bind:style="styleObject">菜鸟教程</div>
    </div>
    
    <script>
    new Vue({
      el: '#app',
      data: {
        styleObject: {
          color: 'green',
          fontSize: '30px'
        }
      }
    })
    </script>
    </body>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    v-bind:style 可以使用数组将多个样式对象应用到一个元素上

    <body>
    <div id="app">
      <div v-bind:style="[baseStyles, overridingStyles]">菜鸟教程</div>
    </div>
    
    <script>
    new Vue({
      el: '#app',
      data: {
        baseStyles: {
          color: 'green',
          fontSize: '30px'
        },
    	overridingStyles: {
          'font-weight': 'bold'
        }
      }
    })
    </script>
    </body>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    事件处理器

    事件的基本使用:

    1.使用v-on:xxx 或 @xxx 绑定事件,其中xxx是事件名,如click;

    2.事件的回调需要配置在methods对象中,最终会在vm上;

    3.methods中配置的函数,不要用箭头函数!否则this就不是vm了;

    4.methods中配置的函数,都是被Vue所管理的函数,this的指向是vm 或 组件实例对象;

    5.@click="demo"@click="demo($event)" 效果一致,但后者可以传参;


    事件监听可以使用 v-on 指令

    <div id="app">
      <button v-on:click="counter += 1">增加 1</button>
      <p>这个按钮被点击了 {{ counter }} 次。</p>
    </div>
     
    <script>
    new Vue({
      el: '#app',
      data: {
        counter: 0
      }
    })
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    通常情况下,我们需要使用一个方法来调用 JavaScript 方法。

    v-on 可以接收一个定义的方法来调用。

    <div id="app">
       <!-- greet 是在下面定义的方法名 -->
      <button v-on:click="greet">Greet</button>
    </div>
     
    <script>
    var app = new Vue({
      el: '#app',
      data: {
        name: 'Vue.js'
      },
      // 在 methods 对象中定义方法
      methods: {
        greet: function (event) {
          // this 在方法里指当前 Vue 实例
          alert('Hello ' + this.name + '!')
          // event 是原生 DOM 事件
          if (event) {
              alert(event.target.tagName)
          }
        }
      }
    })
    // 也可以用 JavaScript 直接调用方法
    app.greet() // -> 'Hello Vue.js!'
    </script>
    
    <!-- 还有这种 -->
    <div id="app">
      <button v-on:click="say('hi')">Say hi</button>
      <button v-on:click="say('what')">Say what</button>
    </div>
     
    <script>
    new Vue({
      el: '#app',
      methods: {
        say: function (message) {
          alert(message)
        }
      }
    })
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    事件修饰符

    Vue.js 为 v-on 提供了事件修饰符来处理 DOM 事件细节,如:event.preventDefault() 或 event.stopPropagation()。

    Vue.js 通过由点 . 表示的指令后缀来调用修饰符。

    • .stop - 阻止冒泡
    • .prevent - 阻止默认事件
    • .capture - 阻止捕获
    • .self - 只监听触发该元素的事件
    • .once - 只触发一次
    • .left - 左键事件
    • .right - 右键事件
    • .middle - 中间滚轮事件
    <!-- 阻止单击事件冒泡 -->
    <a v-on:click.stop="doThis"></a>
    <!-- 提交事件不再重载页面 -->
    <form v-on:submit.prevent="onSubmit"></form>
    <!-- 修饰符可以串联  -->
    <a v-on:click.stop.prevent="doThat"></a>
    <!-- 只有修饰符 -->
    <form v-on:submit.prevent></form>
    <!-- 添加事件侦听器时使用事件捕获模式 -->
    <div v-on:click.capture="doThis">...</div>
    <!-- 只当事件在该元素本身(而不是子元素)触发时触发回调 -->
    <div v-on:click.self="doThat">...</div>
    
    <!-- click 事件只能点击一次,2.1.4版本新增 -->
    <a v-on:click.once="doThis"></a>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    按键修饰符

    Vue 允许为 v-on 在监听键盘事件时添加按键修饰符:

    <!-- 只有在 keyCode 是 13 时调用 vm.submit() -->
    <input v-on:keyup.13="submit">
    
    <!--记住所有的 keyCode 比较困难,所以 Vue 为最常用的按键提供了别名-->
    <!-- 同上 -->
    <input v-on:keyup.enter="submit">
    <!-- 缩写语法 -->
    <input @keyup.enter="submit">
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    全部的按键别名:

    • .enter
    • .tab 换行(特殊,必须配合keydown去使用)
    • .delete (捕获 “删除” 和 “退格” 键)
    • .esc 退出
    • .space
    • .up
    • .down
    • .left
    • .right

    ⬇️ 系统修饰键(用法特殊):

    (1) 配合keyup使用:按下修饰键的同时,再按下其他键,随后释放其他键,事件才被触发。

    (2) 配合keydown使用:正常触发事件。

    • .ctrl
    • .alt
    • .shift
    • .meta
    <p><!-- Alt + C -->
    <input @keyup.alt.67="clear">
    <!-- Ctrl + Click -->
    <div @click.ctrl="doSomething">Do something</div>
    
    • 1
    • 2
    • 3
    • 4

    也可以使用keyCode去指定具体的按键(不推荐)

    Vue.config.keyCodes.自定义键名 = 键码,可以去定制按键别名

    表单

    用 v-model 指令在表单控件元素上创建双向数据绑定

    v-model 会根据控件类型自动选取正确的方法来更新元素。

    img

    MVVM模型
    1、M:模型(Model):对应 data 中的数据
    2、V:视图(View):模板
    3、VM:视图模型(ViewModel): Vue 实例对象


    输入框:

    复选框:

    <div id="app">
      <p>单个复选框:</p>
      <input type="checkbox" id="checkbox" v-model="checked">
      <label for="checkbox">{{ checked }}</label>
        
      <p>多个复选框:</p>
      <input type="checkbox" id="runoob" value="Runoob" v-model="checkedNames">
      <label for="runoob">Runoob</label>
      <input type="checkbox" id="google" value="Google" v-model="checkedNames">
      <label for="google">Google</label>
      <input type="checkbox" id="taobao" value="Taobao" v-model="checkedNames">
      <label for="taobao">taobao</label>
      <br>
      <span>选择的值为: {{ checkedNames }}</span>
    </div>
     
    <script>
    new Vue({
      el: '#app',
      data: {
        checked : false,
        checkedNames: []
      }
    })
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    单选按钮:

    select列表:

    修饰符

    1、.lazy

    在默认情况下, v-model 在 input 事件中同步输入框的值与数据,但你可以添加一个修饰符 lazy ,从而转变为在 change 事件中同步:

    <!--"change" 而不是 "input" 事件中更新 -->
    <input v-model.lazy="msg" >
    
    • 1
    • 2

    2、.number

    如果想自动将用户的输入值转为 Number 类型(如果原值的转换结果为 NaN 则返回原值),可以添加一个修饰符 number 给 v-model 来处理输入值:

    <input v-model.number="age" type="number">
    
    • 1

    这通常很有用,因为在 type=“number” 时 HTML 中输入的值也总是会返回字符串类型。

    3、.trim

    如果要自动过滤用户输入的首尾空格,可以添加 trim 修饰符到 v-model 上过滤输入:

    <input v-model.trim="msg">
    
    • 1

    组件

    组件可以扩展 HTML 元素,封装可重用的代码。

    组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的应用的界面都可以抽象为一个组件树

    img

    单文件组件:

    最基本的结构:
    main.js是入口
    App.vue是管理所有组件的组件

    在这里插入图片描述


    以下都是非单文件组件的内容 ⬇️

    Vue中使用组件的三大步骤:
    一、定义组件(创建组件)
    二、注册组件
    三、使用组件(写组件标签)

    如何定义一个组件?
    使用Vue.extend(options)创建,其中options和new Vue(options)时传入的那个options几乎一样,但也有点区别;

    区别如下:
    1.el不要写,为什么? ——— 最终所有的组件都要经过一个vm的管理,由vm中的el决定服务哪个容器。
    2.data必须写成函数,为什么? ———— 避免组件被复用时,数据存在引用关系。

    备注:使用template可以配置组件结构。

    关于组件标签:

    第一种写法:<school></school>

    第二种写法:<school/> ,不用使用脚手架时,<school/>会导致后续组件不能渲染。


    注册一个全局组件语法格式如下:

    Vue.component(tagName, options)
    
    <!--tagName 为组件名,options 为配置选项。注册后,我们可以使用以下方式来调用组件:-->
    <tagName></tagName>
    
    • 1
    • 2
    • 3
    • 4

    全局组件:所有实例都能使用

    <div id="app">
        <runoob></runoob>
    </div>
     
    <script>
    // 注册
    Vue.component('runoob', {
      template: '<h1>自定义组件!</h1>'
    })
    // 创建根实例
    new Vue({
      el: '#app'
    })
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    局部组件:在实例选项中注册局部组件,这样组件只能在这个实例中使用

    <div id="app">
        <runoob></runoob>
    </div>
     
    <script>
    var Child = {
      template: '<h1>自定义组件!</h1>'
    }
     
    // 创建根实例
    new Vue({
      el: '#app',
      components: {
        // <runoob> 将只在父模板可用
        'runoob': Child
      }
    })
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    关于VueComponent:

    1.school组件本质是一个名为VueComponent的构造函数,且不是程序员定义的,是Vue.extend生成的。

    2.我们只需要写<school/> <school></school>,Vue解析时会帮我们创建school组件的实例对象,
    即Vue帮我们执行的:new VueComponent(options)。

    3.特别注意:每次调用Vue.extend,返回的都是一个全新的VueComponent

    4.关于this指向:

    (1).组件配置中:data函数、methods中的函数、watch中的函数、computed中的函数 它们的this均是【VueComponent实例对象】。

    (2).new Vue(options)配置中:data函数、methods中的函数、watch中的函数、computed中的函数 它们的this均是【Vue实例对象】。

    5.VueComponent的实例对象,以后简称vc(也可称之为:组件实例对象)。
    Vue的实例对象,以后简称vm。

    Prop

    prop 是子组件用来接受父组件传递过来的数据的一个自定义属性。

    父组件的数据需要通过 props 把数据传给子组件,子组件需要显式地用 props 选项声明 “prop”:

    <div id="app">
        <child message="hello!"></child>
    </div>
     
    <script>
    // 注册
    Vue.component('child', {
      // 声明 props
      props: ['message'],
      // 同样也可以在 vm 实例中像 "this.message" 这样使用
      template: '<span>{{ message }}</span>'
    })
    // 创建根实例
    new Vue({
      el: '#app'
    })
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    动态 Prop

    类似于用 v-bind 绑定 HTML 特性到一个表达式,也可以用 v-bind 动态绑定 props 的值到父组件的数据中。每当父组件的数据变化时,该变化也会传导给子组件:

    <div id="app">
        <div>
          <input v-model="parentMsg">
          <br>
          <child v-bind:message="parentMsg"></child>
        </div>
    </div>
     
    <script>
    // 注册
    Vue.component('child', {
      // 声明 props
      props: ['message'],
      // 同样也可以在 vm 实例中像 "this.message" 这样使用
      template: '<span>{{ message }}</span>'
    })
    // 创建根实例
    new Vue({
      el: '#app',
      data: {
        parentMsg: '父组件内容'
      }
    })
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    以下实例中使用 v-bind 指令将 todo 传到每一个重复的组件中:

    <div id="app">
        <ol>
        <todo-item v-for="item in sites" v-bind:todo="item"></todo-item>
          </ol>
    </div>
     
    <script>
    Vue.component('todo-item', {
      props: ['todo'],
      template: '<li>{{ todo.text }}</li>'
    })
    new Vue({
      el: '#app',
      data: {
        sites: [
          { text: 'Runoob' },
          { text: 'Google' },
          { text: 'Taobao' }
        ]
      }
    })
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    注:prop 是单向绑定的。当父组件的属性变化时,将传导给子组件,但是不会反过来。


    Prop 验证

    组件可以为 props 指定验证要求。

    为了定制 prop 的验证方式,你可以为 props 中的值提供一个带有验证需求的对象,而不是一个字符串数组。

    Vue.component('my-component', {
      props: {
        // 基础的类型检查 (`null` 和 `undefined` 会通过任何类型验证)
        propA: Number,
        // 多个可能的类型
        propB: [String, Number],
        // 必填的字符串
        propC: {
          type: String,
          required: true
        },
        // 带有默认值的数字
        propD: {
          type: Number,
          default: 100
        },
        // 带有默认值的对象
        propE: {
          type: Object,
          // 对象或数组默认值必须从一个工厂函数获取
          default: function () {
            return { message: 'hello' }
          }
        },
        // 自定义验证函数
        propF: {
          validator: function (value) {
            // 这个值必须匹配下列字符串中的一个
            return ['success', 'warning', 'danger'].indexOf(value) !== -1
          }
        }
      }
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    当 prop 验证失败的时候,(开发环境构建版本的) Vue 将会产生一个控制台的警告。

    type 可以是下面原生构造器:

    • String
    • Number
    • Boolean
    • Array
    • Object
    • Date
    • Function
    • Symbol

    type 也可以是一个自定义构造器,使用 instanceof 检测。

    自定义事件

    父组件是使用 props 传递数据给子组件,但如果子组件要把数据传递回去,就需要使用自定义事件!

    我们可以使用 v-on 绑定自定义事件, 每个 Vue 实例都实现了事件接口(Events interface),即:

    • 使用 $on(eventName) 监听事件
    • 使用 $emit(eventName) 触发事件

    另外,父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。

    以下实例中子组件已经和它外部完全解耦了。它所做的只是触发一个父组件关心的内部事件。

    <div id="app">
        <div id="counter-event-example">
          <p>{{ total }}</p>
          <button-counter v-on:increment="incrementTotal"></button-counter>
          <button-counter v-on:increment="incrementTotal"></button-counter>
        </div>
    </div>
     
    <script>
    Vue.component('button-counter', {
      template: '<button v-on:click="incrementHandler">{{ counter }}</button>',
      data: function () {
        return {
          counter: 0
        }
      }, <!--data 不是一个对象,而是一个函数.这样的好处就是每个实例可以维护一份被返回对象的独立的拷贝,如果 data 是一个对象则会影响到其他实例-->
      methods: {
        incrementHandler: function () {
          this.counter += 1
          this.$emit('increment')
        }
      },
    })
    new Vue({
      el: '#counter-event-example',
      data: {
        total: 0
      },
      methods: {
        incrementTotal: function () {
          this.total += 1
        }
      }
    })
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    如果你想在某个组件的根元素上监听一个原生事件。可以使用 .native 修饰 v-on 。例如:

    <my-component v-on:click.native="doTheThing"></my-component>
    
    • 1

    自定义组件的 v-model

    组件上的 v-model 默认会利用名为 value 的 prop 和名为 input 的事件。

    <input v-model="parentData">
    
    <!--等价于:-->
    <input 
        :value="parentData"
        @input="parentData = $event.target.value"
    >
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    以下实例自定义组件 runoob-input,父组件的 num 的初始值是 100,更改子组件的值能实时更新父组件的 num:

    <div id="app">
        <runoob-input v-model="num"></runoob-input>
        <p>输入的数字为:{{num}}</p>
    </div>
    <script>
    Vue.component('runoob-input', {
        template: `
        <p>   <!-- 包含了名为 input 的事件 -->
          <input
           ref="input"
           :value="value" 
           @input="$emit('input', $event.target.value)"
          >
        </p>
        `,
        props: ['value'], // 名为 value 的 prop
    })
       
    new Vue({
        el: '#app',
        data: {
            num: 100,
        }
    })
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    由于 v-model 默认传的是 value,不是 checked,所以对于复选框或者单选框的组件时,我们需要使用 model 选项,model 选项可以指

    定当前的事件类型和传入的 props。

    实例中 lovingVue 的值会传给 checked 的 prop,同时当<base-checkbox>触发 change 事件时, lovingVue 的值也会更新。

    <div id="app">
        <base-checkbox v-model="lovingVue"></base-checkbox> 
         <div v-show="lovingVue"> 
            如果选择框打勾我就会显示。 
        </div>
    </div> 
    <script>
    // 注册
    Vue.component('base-checkbox', {
     
      model: {
        prop: 'checked',
        event: 'change'  // onchange 事件
      },
      props: {
        checked: Boolean
      },
       
      template: `
        <input
          type="checkbox"
          v-bind:checked="checked"
          v-on:change="$emit('change', $event.target.checked)"
        >
      `
    })
    // 创建根实例
    new Vue({
      el: '#app',
      data: {
        lovingVue: true
      }
    })
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    收集表单数据:
    若:<input type="text"/>,则v-model收集的是value值,用户输入的就是value值。
    若:<input type="radio"/>,则v-model收集的是value值,且要给标签配置value值。
    若:<input type="checkbox"/>
    1.没有配置input的value属性,那么收集的就是checked(勾选 or 未勾选,是布尔值)
    2.配置input的value属性:
    (1)v-model的初始值是非数组,那么收集的就是checked(勾选 or 未勾选,是布尔值)
    (2)v-model的初始值是数组,那么收集的的就是value组成的数组
    备注:v-model的三个修饰符:
    lazy:失去焦点再收集数据
    number:输入字符串转为有效的数字
    trim:输入首尾空格过滤

    自定义指令

    指令定义时不加v-,但使用时要加v-;

    指令名如果是多个单词,要使用kebab-case命名方式,不要用camelCase命名。

    配置对象中常用的3个回调:

    (1).bind:指令与元素成功绑定时调用。

    (2).inserted:指令所在元素被插入页面时调用。

    (3).update:指令所在模板结构被重新解析时调用。

    Vue.directive('fbind',{
    			//指令与元素成功绑定时(一上来)
    			bind(element,binding){
    				element.value = binding.value
    			},
    			//指令所在元素被插入页面时
    			inserted(element,binding){
    				element.focus()
    			},
    			//指令所在的模板被重新解析时
    			update(element,binding){
    				element.value = binding.value
    			}
    		})
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    注册一个全局指令 v-focus, 该指令的功能是在页面加载时,元素获得焦点:

    需要传入指令名称以及一个包含指令钩子函数的对象,该对象的键即钩子函数的函数名,值即函数体,钩子函数可以有多个。

    <div id="app">
        <p>页面载入时,input 元素自动获取焦点:</p>
        <input v-focus>
    </div>
     
    <script>
    // 注册一个全局自定义指令 v-focus
    Vue.directive('focus', {
      // 当绑定元素插入到 DOM 中。
      inserted: function (el) {
        // 聚焦元素
        el.focus()
      }
    })
    // 创建根实例
    new Vue({
      el: '#app'
    })
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    也可以在实例使用 directives 选项来注册 局部指令,这样指令只能在这个实例中使用

    直接向创建的 Vue 实例的 directives 字典属性添加键值对,键值对即需要添加的自定义指令及对应钩子函数字典对象。键值对可以有多个,对应多个自定义指令。


    钩子

    1、钩子函数

    指令定义函数提供了几个钩子函数(可选):

    • bind: 只调用一次,指令第一次绑定到元素时调用,用这个钩子函数可以定义一个在绑定时执行一次的初始化动作。
    • inserted: 被绑定元素插入父节点时调用(父节点存在即可调用,不必存在于 document 中)。
    • update: 被绑定元素所在的模板更新时调用,而不论绑定值是否变化。通过比较更新前后的绑定值,可以忽略不必要的模板更新(详细的钩子函数参数见下)。
    • componentUpdated: 被绑定元素所在模板完成一次更新周期时调用。
    • unbind: 只调用一次, 指令与元素解绑时调用。

    2、钩子函数参数

    钩子函数的参数有:

    • el: 指令所绑定的元素,可以用来直接操作 DOM 。

    • binding
      一个对象,包含以下属性:
      • name: 指令名,不包括 v- 前缀。
      • value: 指令的绑定值, 例如: v-my-directive="1 + 1", value 的值是 2
      • oldValue: 指令绑定的前一个值,仅在 updatecomponentUpdated 钩子中可用。无论值是否改变都可用。
      • expression: 绑定值的表达式或变量名。 例如 v-my-directive="1 + 1" , expression 的值是 "1 + 1"
      • arg: 传给指令的参数。例如 v-my-directive:foo, arg 的值是 "foo"
      • modifiers: 一个包含修饰符的对象。 例如: v-my-directive.foo.bar, 修饰符对象 modifiers 的值是 { foo: true, bar: true }
    • vnode: Vue 编译生成的虚拟节点。

    • oldVnode: 上一个虚拟节点,仅在 updatecomponentUpdated 钩子中可用。

    <div id="app"  v-runoob:hello.a.b="message">
    </div>
     
    <script>
    Vue.directive('runoob', {
      bind: function (el, binding, vnode) {
        var s = JSON.stringify
        el.innerHTML =
          'name: '       + s(binding.name) + '<br>' +
          'value: '      + s(binding.value) + '<br>' +
          'expression: ' + s(binding.expression) + '<br>' +
          'argument: '   + s(binding.arg) + '<br>' +
          'modifiers: '  + s(binding.modifiers) + '<br>' +
          'vnode keys: ' + Object.keys(vnode).join(', ')
      }
    })
    new Vue({
      el: '#app',
      data: {
        message: '菜鸟教程!'
      }
    })
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    有时候我们不需要其他钩子函数,我们可以简写函数,如下格式:

    Vue.directive('runoob', function (el, binding) {
      // 设置指令的背景颜色
      el.style.backgroundColor = binding.value.color
    })
    
    • 1
    • 2
    • 3
    • 4

    指令函数可接受所有合法的 JavaScript 表达式,以下实例传入了 JavaScript 对象:

    <div id="app">
        <div v-runoob="{ color: 'green', text: '菜鸟教程!' }"></div>
    </div>
     
    <script>
    Vue.directive('runoob', function (el, binding) {
        // 简写方式设置文本及背景颜色
        el.innerHTML = binding.value.text
        el.style.backgroundColor = binding.value.color
    })
    new Vue({
      el: '#app'
    })
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    生命周期

    https://blog.csdn.net/weixin_46349544/article/details/124080704

    生命周期:

    1.又名:生命周期回调函数、生命周期函数、生命周期钩子。

    2.是什么:Vue在关键时刻帮我们调用的一些特殊名称的函数。

    3.生命周期函数的名字不可更改,但函数的具体内容是程序员根据需求编写的。

    4.生命周期函数中的this指向是vm 或 组件实例对象。

     new Vue({
    			el:'#root',
    			data:{
    				opacity:1
    			},
    			methods: {
    				stop(){
    					this.$destroy()
    				}
    			},
    			//Vue完成模板的解析并把初始的真实DOM元素放入页面后(挂载完毕)调用mounted
    			mounted(){
    				console.log('mounted',this)
    				this.timer = setInterval(() => {
    					console.log('setInterval')
    					this.opacity -= 0.01
    					if(this.opacity <= 0) this.opacity = 1
    				},16)
    			},
    			beforeDestroy() {
    				clearInterval(this.timer)
    				console.log('vm即将驾鹤西游了')
    			},
    		})
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    常用的生命周期钩子:
    1.mounted: 发送ajax请求、启动定时器、绑定自定义事件、订阅消息等【初始化操作】。
    2.beforeDestroy: 清除定时器、解绑自定义事件、取消订阅消息等【收尾工作】。

    关于销毁Vue实例:
    1.销毁后借助Vue开发者工具看不到任何信息。
    2.销毁后自定义事件会失效,但原生DOM事件依然有效。
    3.一般不会在beforeDestroy操作数据,因为即便操作数据,也不会再触发更新流程了。

    路由

    Vue.js 路由允许我们通过不同的 URL 访问不同的内容。

    通过 Vue.js 可以实现多视图的单页Web应用(single page web application,SPA)

    Vue.js 路由需要载入 vue-router 库

    中文文档地址:vue-router文档

    安装

    1、直接下载 / CDN

    https://unpkg.com/vue-router/dist/vue-router.js
    
    • 1

    2、NPM

    推荐使用淘宝镜像:

    cnpm install vue-router
    
    • 1

    简单实例

    Vue.js + vue-router 可以很简单的实现单页应用。

    <router-link> 是一个组件,该组件用于设置一个导航链接,切换不同 HTML 内容。 to 属性为目标地址, 即要显示的内容。

    以下实例中我们将 vue-router 加进来,然后配置组件和路由映射,再告诉 vue-router 在哪里渲染它们。代码如下所示:

    Html:

    <script src="https://unpkg.com/vue/dist/vue.js"></script>
    <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
     
    <div id="app">
      <h1>Hello App!</h1>
      <p>
        <!-- 使用 router-link 组件来导航. -->
        <!-- 通过传入 `to` 属性指定链接. -->
        <!-- <router-link> 默认会被渲染成一个 `<a>` 标签 -->
        <router-link to="/foo">Go to Foo</router-link>
        <router-link to="/bar">Go to Bar</router-link>
      </p>
      <!-- 路由出口 -->
      <!-- 路由匹配到的组件将渲染在这里 -->
      <router-view></router-view>
    </div>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    JavaScript:

    // 0. 如果使用模块化机制编程,导入 Vue 和 VueRouter,要调用 Vue.use(VueRouter)
     
    // 1. 定义(路由)组件。
    // 可以从其他文件 import 进来
    const Foo = { template: '<div>foo</div>' }
    const Bar = { template: '<div>bar</div>' }
     
    // 2. 定义路由
    // 每个路由应该映射一个组件。 其中"component" 可以是
    // 通过 Vue.extend() 创建的组件构造器,
    // 或者,只是一个组件配置对象。
    // 我们晚点再讨论嵌套路由。
    const routes = [
      { path: '/foo', component: Foo },
      { path: '/bar', component: Bar }
    ]
     
    // 3. 创建 router 实例,然后传 routes 配置
    // 还可以传别的配置参数, 不过先这么简单着吧。
    const router = new VueRouter({
      routes // (缩写)相当于 routes: routes
    })
     
    // 4. 创建和挂载根实例。
    // 记得要通过 router 配置参数注入路由,
    // 从而让整个应用都有路由功能
    const app = new Vue({
      router
    }).$mount('#app')
     
    // 现在,应用已经启动了!
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    <router-link> 相关属性:

    to:表示目标路由的链接。

    当被点击后,内部会立刻把 to 的值传到 router.push(),所以这个值可以是一个字符串或者是描述目标位置的对象。

    <!-- 字符串 -->
    <router-link to="home">Home</router-link>
    <!-- 渲染结果 -->
    <a href="home">Home</a>
    
    <!-- 使用 v-bind 的 JS 表达式 -->
    <router-link v-bind:to="'home'">Home</router-link>
    
    <!-- 不写 v-bind 也可以,就像绑定别的属性一样 -->
    <router-link :to="'home'">Home</router-link>
    
    <!-- 同上 -->
    <router-link :to="{ path: 'home' }">Home</router-link>
    
    <!-- 命名的路由 -->
    <router-link :to="{ name: 'user', params: { userId: 123 }}">User</router-link>
    
    <!-- 带查询参数,下面的结果为 /register?plan=private -->
    <router-link :to="{ path: 'register', query: { plan: 'private' }}">Register</router-link>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    replace:当点击时,会调用 router.replace() 而不是 router.push(),导航后不会留下 history 记录。

    <router-link :to="{ path: '/abc'}" replace></router-link>
    
    • 1

    append:设置 append 属性后,则在当前 (相对) 路径前添加其路径。

    例如,我们从 /a 导航到一个相对路径 b,如果没有配置 append,则路径为 /b,如果配了,则为 /a/b

    <router-link :to="{ path: 'relative/path'}" append></router-link>
    
    • 1

    tag:有时候想要 <router-link> 渲染成某种标签,例如 <li>

    于是我们使用 tag prop 类指定何种标签,同样它还是会监听点击,触发导航。

    <router-link to="/foo" tag="li">foo</router-link>
    <!-- 渲染结果 -->
    <li>foo</li>
    
    • 1
    • 2
    • 3

    active-class

    设置 链接激活时使用的 CSS 类名。可以通过以下代码来替代。

    <style>
       ._active{
          background-color : red;
       }
    </style>
    <p>
       <router-link v-bind:to = "{ path: '/route1'}" active-class = "_active">Router Link 1</router-link>
       <router-link v-bind:to = "{ path: '/route2'}" tag = "span">Router Link 2</router-link>
    </p>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    注意这里 class 使用 active-class=“_active”。

    exact-active-class

    配置当链接被精确匹配的时候应该激活的 class。可以通过以下代码来替代。

    <p>
       <router-link v-bind:to = "{ path: '/route1'}" exact-active-class = "_active">Router Link 1</router-link>
       <router-link v-bind:to = "{ path: '/route2'}" tag = "span">Router Link 2</router-link>
    </p>
    
    • 1
    • 2
    • 3
    • 4

    event

    声明可以用来触发导航的事件。可以是一个字符串或是一个包含字符串的数组。

    <router-link v-bind:to = "{ path: '/route1'}" event = "mouseover">Router Link 1</router-link>
    
    • 1

    以上代码设置了 event 为 mouseover ,及在鼠标移动到 Router Link 1 上时导航的 HTML 内容会发生改变。

    过渡 & 动画


    过渡

    Vue 在插入、更新或者移除 DOM 时,提供多种不同方式的应用过渡效果。

    Vue 提供了内置的过渡封装组件,该组件用于包裹要实现过渡效果的组件。

    <transition name = "nameoftransition">
       <div></div>
    </transition>
    
    • 1
    • 2
    • 3

    示例:通过点击 “点我” 按钮将变量 show 的值从 true 变为 false。如果为 true 显示子元素 p 标签的内容。

    <div id = "databinding">
    <button v-on:click = "show = !show">点我</button>
    <transition name = "fade">
        <p v-show = "show" v-bind:style = "styleobj">动画实例</p>
    </transition>
    </div>
    <script type = "text/javascript">
    var vm = new Vue({
    el: '#databinding',
        data: {
            show:true,
            styleobj :{
                fontSize:'30px',
                color:'red'
            }
        },
        methods : {
        }
    });
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    过渡其实就是一个淡入淡出的效果。Vue在元素显示与隐藏的过渡中,提供了 6 个 class 来切换:

    • v-enter:定义进入过渡的开始状态。在元素被插入之前生效,在元素被插入之后的下一帧移除。
    • v-enter-active:定义进入过渡生效时的状态。在整个进入过渡的阶段中应用,在元素被插入之前生效,在过渡/动画完成之后移除。这个类可以被用来定义进入过渡的过程时间,延迟和曲线函数。
    • v-enter-to: 2.1.8版及以上 定义进入过渡的结束状态。在元素被插入之后下一帧生效 (与此同时 v-enter 被移除),在过渡/动画完成之后移除。
    • v-leave: 定义离开过渡的开始状态。在离开过渡被触发时立刻生效,下一帧被移除。
    • v-leave-active:定义离开过渡生效时的状态。在整个离开过渡的阶段中应用,在离开过渡被触发时立刻生效,在过渡/动画完成之后移除。这个类可以被用来定义离开过渡的过程时间,延迟和曲线函数。
    • v-leave-to: 2.1.8版及以上 定义离开过渡的结束状态。在离开过渡被触发之后下一帧生效 (与此同时 v-leave 被删除),在过渡/动画完成之后移除。
    img

    对于这些在过渡中切换的类名来说,如果你使用一个没有名字的 <transition>,则 v- 是这些类名的默认前缀。如果你使用了 <transition name="my-transition">,那么 v-enter 会替换为 my-transition-enter

    v-enter-activev-leave-active 可以控制进入/离开过渡的不同的缓和曲线,在下面章节会有个示例说明。

    CSS过渡

    <style>
    /* 可以设置不同的进入和离开动画 */
    /* 设置持续时间和动画函数 */
    .slide-fade-enter-active {
      transition: all .3s ease;
    }
    .slide-fade-leave-active {
      transition: all .8s cubic-bezier(1.0, 0.5, 0.8, 1.0);
    }
    .slide-fade-enter, .slide-fade-leave-to
    /* .slide-fade-leave-active 用于 2.1.8 以下版本 */ {
      transform: translateX(10px);
      opacity: 0;
    }
    </style>
    </head>
    <body>
    <div id = "databinding">
    <button v-on:click = "show = !show">点我</button>
    <transition name="slide-fade">
        <p v-if="show">菜鸟教程</p>
    </transition>
    </div>
    <script type = "text/javascript">
    new Vue({
        el: '#databinding',
        data: {
            show: true
        }
    })
    </script>
    </body>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    CSS 动画

    CSS 动画用法类似 CSS 过渡,但是在动画中 v-enter 类名在节点插入 DOM 后不会立即删除,而是在 animationend 事件触发时删除。

    自定义过渡的类名

    我们可以通过以下特性来自定义过渡类名:

    • enter-class
    • enter-active-class
    • enter-to-class (2.1.8+)
    • leave-class
    • leave-active-class
    • leave-to-class (2.1.8+)

    自定义过渡的类名优先级高于普通的类名,这样就能很好的与第三方(如:animate.css)的动画库结合使用。

    还有很多,但我懒得写了:https://www.runoob.com/vue2/vue-transitions.html

    混入

    混入 (mixins)定义了一部分可复用的方法或者计算属性。

    混入对象可以包含任意组件选项。当组件使用混入对象时,所有混入对象的选项将被混入该组件本身的选项。

    var vm = new Vue({
        el: '#databinding',
        data: {
        },
        methods : {
        },
    });
    // 定义一个混入对象
    var myMixin = {
        created: function () {
            this.startmixin()
        },
        methods: {
            startmixin: function () {
                document.write("欢迎来到混入实例");
            }
        }
    };
    var Component = Vue.extend({
        mixins: [myMixin]
    })
    var component = new Component();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    选项合并

    当组件和混入对象含有同名选项时,这些选项将以恰当的方式混合。

    比如,数据对象在内部会进行浅合并 (一层属性深度),在和组件的数据发生冲突时以组件数据优先。

    以下实例中,Vue 实例与混入对象包含了相同的方法。从输出结果可以看出两个选项合并了。

    var mixin = {
    	created: function () {
    		document.write('混入调用' + '<br>')    
    } 
    } 
    new Vue({    
    	mixins: [mixin],        
    		created: function () {       
    		document.write('组件调用' + '<br>')    
    }
    });
    输出结果为:
    混入调用
    组件调用
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    如果 methods 选项中有相同的函数名,则 Vue 实例优先级会较高。

    全局混入

    也可以全局注册混入对象。注意使用! 一旦使用全局混入对象,将会影响到 所有 之后创建的 Vue 实例。使用恰当时,可以为自定义对象注入处理逻辑。

    // 为自定义的选项 'myOption' 注入一个处理器。
    Vue.mixin({
      created: function () {
        var myOption = this.$options.myOption
        if (myOption) {
          console.log(myOption)
        }
      }
    })
     
    new Vue({
      myOption: 'hello!'
    })
    // => "hello!"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    Ajax(axios)

    Vue.js 2.0 版本推荐使用 axios 来完成 ajax 请求。

    Axios 是一个基于 Promise 的 HTTP 库,可以用在浏览器和 node.js 中。

    Github开源地址: https://github.com/axios/axios

    安装方法

    使用 cdn:
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script><script src="https://cdn.staticfile.org/axios/0.18.0/axios.min.js"></script>
    使用 npm:
    $ npm install axios
    使用 bower:
    $ bower install axios
    使用 yarn:
    $ yarn add axios
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    vue脚手架 vue cli

    https://blog.csdn.net/weixin_46349544/article/details/124135361

    Vue 官方提供的标准化开发工具(开发平台)

    cli就是command line interface vue命令行接口,就是用来创建一个vue工程的一个工具

    初始化脚手架:

    1、淘宝下载(详见第一章-开发环境配置)

    2、创建一个vue项目 vue create xxxx

    3、用vscode打开创建的这个工程,执行npm run serve(查看package.json文件)

    分析脚手架结构:

    ├── node_modules
    ├── public
    │ ├── favicon.ico: 页签图标
    │ └── index.html: 主页面
    ├── src
    │ ├── assets: 存放静态资源
    │ │ └── logo.png
    │ │── components: 存放组件
    │ │ └── HelloWorld.vue
    │ │── App.vue: 汇总所有组件
    │ │── main.js: 入口文件
    ├── .gitignore: git版本管制忽略的配置
    ├── babel.config.js: babel的配置文件
    ├── package.json: 应用包配置文件
    ├── README.md: 应用描述文件
    ├── package-lock.json:包版本控制文件

    大概执行顺序:

    1. 在执行npm run serve命令后就先执行main.js
    2. 将APP组件渲染到容器上(APP是管理所有组件的组件,就是APP是所有组件的父组件)
    3. 渲染index.html

    后面还有还有看起来比较高层次的内容:懒得写了

    Vue教程_vuex(三) https://blog.csdn.net/weixin_46349544/article/details/124238467
    Vue教程_vue-router(四) https://blog.csdn.net/weixin_46349544/article/details/124240360

  • 相关阅读:
    vue的计算属性(computed)
    290_C++_截取的一部分FTP视频上传代码,任务信息中读取视频帧数据并将其提供给 libcurl 用于上传。
    计算机组成原理知识总结(七)外围设备
    [cpp primer随笔] 12. 函数指针
    【Bug——VMware Workstation】虚拟机桥接网络没有 VMnet0
    2023年最热门的网络安全岗位分析
    Spring 如何实现一个CGLlB动态代理呢?
    微信公众号怎么把个人改成企业?
    解决 /bin/bash^M: bad interpreter: No such file or directory
    vue3+vite3+vant搭建移动端简易模版
  • 原文地址:https://blog.csdn.net/weixin_43123409/article/details/125624203