zoukankan      html  css  js  c++  java
  • Vue.js 学习笔记

    Vue.js

    基础

    一套用于构建用户界面的渐进式框架, 核心库只关注视图层,易于上手,便于与第三方库或现有项目整合,且轻量。

    声明式渲染

    使用插值表达式,基于 MVVM 来动态的影响页面与变量

    # 页面上键入插值表达式
    <div id="app">
      {{ message }} # View 角色
    </div>
    
    # 然后,进行	ViewModle 数据绑定。是 VM 角色
    var app = new Vue({ # 新建 Vue 实例
      el: '#app', # 通过ID选择器,来接管 div 区域
      data: { 
        message: 'Hello Vue!' # 是 Model 角色
      }
    })
    

    双向绑定

    使用 v-modle 指令实现双向绑定

    可以在一个 app 块中绑定多个变量,在赋值的时候使用逗号隔开。这样就渐渐的相当于 angula.js 使用 ng-app 声明在 body上占地为王一样

    var app = new Vue({
        el:'#app',
        data:{
            flag:true,
            user:"张三"
        }
    });
    

    并且可以在浏览器调试页,使用 app.变量名 = 值 ,替换变量的值。

    条件与循环

    条件:v-if="变量名";

    当变量的值为 true 时,显示被 v-if 指令所在标签包裹的HTML内容。当值为 false 删除其所在html标签

    <div id="app-3">
        <span v-if="flag">
            你能看见我吗?
        </span>
    </div>
    
    var app3 = new Vue({
        el:'#app-3',
        data:{
            flag:true
        }
    });
    

    隐藏:v-show = "变量名";

    当变量的值为 false 时,为DOM的HTML标签添加CSS属性: style="display: none;"

    因此:对于经常需要进行显示/隐藏切换的DOM标签,使用 v-show 性能更加优异

    循环:v-for="临时变量 in 变量"

    <div id="app">
        <ur v-for="user in users">
            <li>{{user.name}}---{{user.age}} </li>
        </ur>
    </div>
    
    var app = new Vue({
        el:'#app',
        data:{
            users:[
                {"name":"张三","age":23}, # JSON格式定义对象
                {"name":"李四","age":24},
                {"name":"王五","age":25},
                {"name":"赵六","age":26}
            ]
        }
    });
    
    • 在调试页中可以使用 app.users.push({"name":"xxx","age":23}) 动态添加数据
    • 定义一个唯一的字段作为 key ,可以提高遍历效率
    • 在遍历时以如下方式使用 index
    <ur v-for="(user, index) in users":key="index">
        <li>{{index + 1}} {{user.name}}---{{user.age}}</li>
    </ur>
    

    处理用户输入

    组件化

    组件:页面上的某一部分,当一个网页非常大时,可以将该网页的内容拆分成几个部分,便于维护

    定义组件

    1. 定义全局组件
    Vue.component('todo-item', { # 通过 Vue.component('组件名',{组件内容}) 定义组件
       template : "<li>Item</li>" # 通过 template 属性定义组件的内容
    });
    
    
    <ul>
        <todo-item></todo-item> <!-- 在页面以标签的方式使用组件 -->
    </ul>
    
    
    1. 定义局部组件
    // 定义局部组件
    var TodoList = {
        template : "<li>Item</li>"
    };
    // 注册局部组件
    new Vue({
        el: '#app',
        components : {
            "todo-item" : TodoList # 仍然在页面使用 todo-item 这个名字来使用组件
    	})
    
    

    利用组件实现 todolist

    <ul>
        <!-- 在使用组件的时候,可以进行传值,使用 : 变量名 = “值” -->
        <todo-item
                v-for="(content, index) in list"  
                :key="index" 
                :content="content" 
        ></todo-item>
    </ul>
    
    
    // 全局组件
    Vue.component('todo-item', {
        props : ['content'], # 用来接收传过来的值
        template: "<li>{{content}}</li>" # 使用插值表达式来显示值
    });
    
    

    组件和实例的关系

    一个组件也是一个实例

    ​ 组件里面也可以写:methods / data / computed 属性

    任何Vue项目都是由 n 个实例构成的

    ​ 对于根实例,虽然没有显式的定义 template 模板属性,但是Vue会根据 el 属性,去找挂载点,将挂载点里面的全部内容作为模板

    组件之间的交互

    父子组件之间的交互

    父组件向子组件传递数据:

    ​ 使用 : 属性名 = “值” 的方式传递,子组件 使用 props : ["属性名1", "属性名2"] 的方式接收

    子组件向父组件传递数据:

    ​ 使用 : this.$emit("消息名", 参数) 的方式来发送消息,在父组件的模板中使用 @消息名 = “函数名” 的方式来接收消息并处理。

    具体的使用见练习2.

    挂载点、模板、实例

    挂载点: el 属性绑定的DOM标签。用来声明Vue的作用域。不包含标签内部的变量

    模板: 挂载点内部的HTML内容统称为模板。模板的定义方式有两种:

    • 直接定义在挂载点所在的标签体内
    • 在 Vue 实例里使用 template 定义:
    var app = new Vue({
        el:'#app',
        # 模板内容会覆盖原本挂载点里面的内容,请注意
        template:"<h1>Hello {{msg}}</h1>", # 定义模板时,需要用标签来包装内容,否则无法识别
        data:{
            msg:"Hello World"
        }
    });
    
    

    实例:创建的 Vue 对象

    使用

    安装

    Vue.js 不支持IE8及以下版本,因为他使用了IE8不支持的 ECMAScript5 的特性。

    引入核心库

    <!-- 开发环境下引入完成包,生产环境引 min.js 包 -->
    <script src="./vue.js"></script>
    
    

    指令

    以 v- 作为前缀,vue指令会在渲染的DOM上应用特殊的响应行为。

    v-text

    绑定DOM标签内的text文本内容。如果内容中存在HTML标签,会被原样展示

    v-html

    绑定DOM标签内HTML内容

    v-on:click = "functionName"

    • 绑定单击事件。注意:单击调用的方法只写方法名,不写小括号
    • 在实例中定义 methods 对象,对象内部可以定义方法
    • 另外, v-on:click 也可以简写成: @click
    var app = new Vue({
        el:'#app',
        data:{
            text:"Hello"
        },
        methods:{ # 这个属性用来定义实例中的方法
            changeText : function () {
                app.text = "World"
            }
        }
    });
    // 或者可以采用 this.text 的方式来更改 text
    changeText : function () {
        this.text = "World"
    }
    
    

    属性绑定

    v-bind:title="title"

    为 title 属性后面的内容赋予了特殊的意义。例如此例中 “” 内的 title 表示Vue实例中的title变量的值

    v-bind: 可以简写为 :

    计算属性

    computed

    用来对变量进行一些运算操作。

    优点:当参与运算的变量没有改变时,结果会采用上一次的缓存值

    <div id="app">
        姓:<input v-model="firstName"/>
        名:<input v-model="lastName"/>
        <div>{{fullName}}</div>
    </div>
    
    

    使用 computed 属性来定义参计算结果的函数

    new Vue({
        el:'#app',
        data:{
            firstName:"", # 必须提前定义为 “” 否则页面会显示fullName为 undefined
            lastName:""
        },
        computed:{ # 定义计算属性
            fullName : function () {
                return this.firstName + " " + this.lastName; # 返回字符串拼接结果
            }
        }
    });
    
    

    侦听器

    watch

    监听某个数据的变化,当它产生变化时,执行回调函数

    watch: { # 定义侦听器
        fullName : function () { # 侦听的变量为 fullName 
            this.count ++ ; # 回调函数方法体
        }
    }
    
    

    练习1

    vue1

    需求:如上面的动图,当输入框输入内容后,点击提交就会在下面的列表展示新添加的数据,如果用户没有写任何数据点击提交,提示他应该输入之后才能点击

    <div id="app">
        <input v-model="num" ref="id"/>  <!-- 添加ref属性,以便使用Vue选择器来获取该输入框的 -->
        <button @click="add">提交</button>
    
        <ul>  <!-- 添加key属性,提高遍历速度 -->
            <li v-for="(entity, index) in list":key="index">{{entity.num}}</li>
        </ul>
    </div>
    
    
    <script>
        var app = new Vue({
            el: '#app',
            data:{
                num:"",
                list:[
                    {num:1},
                    {num:2},
                    {num:3},
                    {num:4}
                ]
            },
            methods:{
                add : function () {
                    if(this.num){
                        this.list.push({num:this.num});
                        this.num = ""; # 添加完成后,删除原来的数据
                    }else {
                        alert("请输入要添加的内容后重试!");
                        this.$refs.id.focus(); # vue语法,让输入框获得焦点,提高用户体验
                    }
                }
            }
        });
    </script>
    
    

    练习2

    完成 TodoList 中点击某个 li 删除它的功能

    <div id="app">
        <input v-model="num" ref="id"/>
        <button @click="add">提交</button>
    
    <ul>
        <todo-item
                v-for="(content, index) in list"
                :key="index"  
                :content="content"   父组件向子组件传递数据
                :index="index"
                @delete = "handleDelete" 父组件的订阅方法
        ></todo-item>
    </ul>
    </div>
    
    
    <script>
        // 全局组件
        Vue.component('todo-item', {
            props : ['content', 'index'], # 子组件接收数据
            template: '<li @click="deleteItem">{{content}}</li>', # 绑定点击事件
            methods:{
                deleteItem:function () {
                    this.$emit("delete", this.index); # 子组件向父组件发送消息,携带该 li 的index 数据
                }
            }
        });
    
        new Vue({
            el: '#app',
            data: {
                num: "",
                list: []
            },
            methods: {
                add: function () {
                    if (this.num) {
                        this.list.push(this.num);
                        this.num = "";
                    } else {
                        alert("请输入要添加的内容后重试!");
                        this.$refs.id.focus();
                    }
                },
                handleDelete : function (index) { # 父组件收到消息后执行删除方法,删除对应 index 的 li 标签
                    // alert(index);
                    this.list.splice(index, 1);
                }
            }
        });
    </script>
    
    

    Vue 脚手架工具 vue-cli

    首先安装 node.js

    1564726440925

    下载地址:

    https://nodejs.org/en/download/

    下载对应系统的版本,双击安装即可。安装完成后会自动添加全局变量。使用 node -v 来确认是否安装成功

    安装 NPM

    (Node Package Manager)他是node包管理和分发的工具,使用NPM可以对应用的依赖进行管理,NPM的功能和服务端项目构建工具maven差不多,我们通过npm 可以很方便地下载js库,打包js文件。
    node.js已经集成了npm工具,在命令提示符输入 npm -v 可查看当前npm版本

    设置包路径,

    包路径就是npm从远程下载的js包所存放的路径。使用 npm config ls 查询NPM管理包路径(NPM下载的依赖包所存放的路径)

    使用下面的命令来设置:

    npm config set prefix "C:develop
    odeJS
    pm_modules"
    npm config set cache "c:develop
    odeJS
    pm_cache"
    
    
    1. 安装淘宝的镜像。镜像默认是使用国外的网络来下载的。网速很慢,因此我们配置一个国内的镜像
    npm install -g cnpm --registry=https://registry.npm.taobao.org
    
    

    安装完成后使用:cnpm -v 来查看

    注意:如果安装后,出现 cnpm 不是内部或外部命令,也不是可运行的程序。就需要检查cnpm 的路径是否正确。将 cnpm包的所有文件复制和 npm.cmd 文件在同一级目录下即可。

    究其原因:是因为环境变量中仅仅配置了 npm.cmd 所在文件夹路径,我们也可以将 npm_modules 目录添加到环境变量中,这样也不会出现这个问题。推荐使用该方法

    添加环境变量:

    1564731885562

    在 PATH 中添加:

    1564731919317

    安装 nrm

    cnpm install -g nrm

    切换镜像

    查看已安装的镜像 : nrm ls 切换镜像 nrm use XXX

    最后,安装 vue-cli 客户端

    npm install --global vue-cli

    创建新的Vue项目

    1. 创建一个文件夹,用于存放和维护 Vue 项目,这里我创建的是 c:developVueProjects
    2. 切换到该文件夹,打开cmd。然后输入: vue init webpack 项目名
    3. 配置按照下图设置
      1564734104979

    最后一行选项选择的是包/依赖安装方式

    1. 创建完成后,切换到项目路径。使用 npm run dev 命令启动项目

    将项目导入IDEA

    这里因为我电脑上只有IDEA并且懒得安装前端编程IDE,所以就使用IDEA来编程

    安装后会存在一个问题,IDEA 并不能正确识别 .vue 文件(我是2018.2版本,不知新版解决没有),因此会将.vue文件识别成普通文本文件,给我们编码带来很大的不便,解决办法如图:

    1564735407072

    另外,IDEA也不能识别ES6语法,我们也需要进行一些配置:

    1564735699406

    通过上面的两个设置,就可以愉快的使用 IDEA 进行 Vue 项目编程啦!

    Vue-Cli 中编辑的项目是支持热部署的,耶!

    Vue项目结构

    项目根目录下有一个 index.html

    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width,initial-scale=1.0">
        <title>todolist</title>
      </head>
      <body>
        <div id="app"></div> <!-- 这里定义了一个 app 的挂载点 -->
        <!-- built files will be auto injected -->
      </body>
    </html>
    
    

    src 目录下有 main.js 是 Vue 项目的入口js

    // The Vue build version to load with the `import` command
    // (runtime-only or standalone) has been set in webpack.base.conf with an alias.
    import Vue from 'vue'
    import App from './App'
    
    Vue.config.productionTip = false
    
    /* eslint-disable no-new */
    new Vue({
      el: '#app',
      components: { App }, # 这里采用 ES6 的语法,如果某 key 和 value 是一样的,可以简写成 key
      template: '<App/>'
    })
    
    

    可以看出,入口文件引入了同目录下的 App.vue 文件,那么这个文件里面有什么内容呢?

    <template>
      <div id="app">
        <img src="./assets/logo.png">
        <HelloWorld/>
      </div>
    </template>
    
    <script>
    import HelloWorld from './components/HelloWorld'
    
    export default {
      name: 'App',
      components: {
        HelloWorld
      }
    }
    </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: 60px;
    }
    </style>
    
    

    由此可见,Vue 项目对各个模块进行了拆分,以达到解耦的目的。具体的好处且往下看

    练习3

    使用 vue-cli 实现 TodoList

    1. 打开上面创建的 TodoList 项目,修改 App.vue 文件名称为 TodoList.vue , 并修改其他文件中的引用名
    2. 编辑 TodoList.vue 的模板文件,代码如下:
    <template>
      <div>
        <input>
        <button>提交</button>
      </div>
      <ul>
        <li>1</li>
        <li>2</li>
        <li>3</li>
      </ul>
    </template>
    
    

    这时打开浏览器会发现报错了

    1565001521769

    因此我们对模板文件进行修改,使用一个 div 包裹上面的两个标签,发现浏览器可以正常显示了

    数据绑定

    在 vue-cli 中,数据绑定采用另外一种语法:此时数据不是直接绑定,而是间接通过函数来返回

    <script>
        export default {
          <!-- 以下是 data : function(){} 的缩写 -->  
          data(){
            return {
              inputValue : ""
            }
          }
        }
    </script>
    
    

    单击事件

    给提交按钮添加单击事件:

    <button @click="handleClick">提交</button>
    
    

    定义函数:依然可以采用 ES6 的语法,简略的写成 handleClick(){}

    <script>
        export default {
          methods:{
            handleClick (){
              alert(123)
            }
          }
        }
    </script>
    
    

    建立子组件

    vue-cli 的子组件放在 compontents 目录下:

    1565002961390

    1. 复制一份干净的 .vue 代码,起名 TodoItem.vue
    <template>
    
    </template>
    
    <script>
    export default {
    
    }
    </script>
    
    <style>
    
    </style>
    
    
    1. 添加模板数据,在 TodoList.vue 实例中引入 TodoItem.vue 组件,并注册
    <script>
    // 引入组件, import 组件名 from 组件路径
    import TodoItem from './components/TodoItem'
    
    export default {
      // 注册组件, ‘组件标签名’:组件名 
      components:{
        'todo-item' : TodoItem
      },
    ......
    
    
    1. 找到合适的位置,添加组件标签
    <ul>
        <todo-item></todo-item>
    </ul>
    
    

    父组件向子组件传值

    通过定义属性的方式来给子组件传值

    定义 content 属性,index 属性传给子组件

    <ul>
        <todo-item
        v-for="(item, index) of list"
        	:key="index"
        	:content="item"
        	:index="index"
        ></todo-item>
    </ul>
    
    

    子组件声明接收的值:

    <script>
        export default {
          props:['content']
        }
    </script>
    
    

    通过插值表达式来显示值:

    <template>
    	<li>{{content}}</li>
    </template>
    
    

    子组件向父组件传值

    通过发布/订阅的方式来实现子组件向父组件传值

    在子组件的单击方法中定义发布消息的事件,事件名 delete, 参数:当前 li 元素的 index

    handleDelete(){
    	this.$emit('delete', this.index)
    }
    
    

    父组件接收消息:并触发函数的执行

    <ul>
          <todo-item
            v-for="(item, index) of list"
            :key="index"
            :content="item"
            :index="index"
            @delete="handleDelete" // 接收消息
          ></todo-item>
    </ul>
    
    handleDelete (index){
    	this.list.splice(index, 1) // 删除对应的元素
    }
    
    

    全局样式与局部样式

    对于每一个 vue 文件都包含 style 标签,这个 style 标签有一个属性 scoped 如果添加此属性则该标签内所有的样式仅对当前文件有效。开发中尽量都添加上使得文件间的耦合性更低

    结语

    这个笔记仅涵盖了 Vue 的一点点基础知识,如果读者想要深入学习,可以前往官网参考文档继续学习:https://cn.vuejs.org/v2/guide/

  • 相关阅读:
    Time Zone 【模拟时区转换】(HDU暑假2018多校第一场)
    HDU 1281 棋盘游戏 【二分图最大匹配】
    Codeforces Round #527 (Div. 3) F. Tree with Maximum Cost 【DFS换根 || 树形dp】
    Codeforces Round #527 (Div. 3) D2. Great Vova Wall (Version 2) 【思维】
    Codeforces Round #527 (Div. 3) D1. Great Vova Wall (Version 1) 【思维】
    Codeforces Round #528 (Div. 2, based on Technocup 2019 Elimination Round 4) C. Connect Three 【模拟】
    Avito Cool Challenge 2018 E. Missing Numbers 【枚举】
    Avito Cool Challenge 2018 C. Colorful Bricks 【排列组合】
    005 如何分析问题框架
    004 如何定义和澄清问题
  • 原文地址:https://www.cnblogs.com/keatsCoder/p/11305110.html
Copyright © 2011-2022 走看看