vue框架的学习-基础部分

早过忘川 提交于 2020-01-29 06:08:33

1:vue的安装

使用一个框架,我们第一步要做什么呢?安装下载它

安装Vue的方式有很多:
方式一:直接CDN引入
你可以选择引入开发环境版本还是生产环境版本

<!-- 开发环境版本,包含了有帮助的命令行警告 --> 
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<!-- 生产环境版本,优化了尺寸和速度 -->
<script src="https://cdn.jsdelivr.net/npm/vue"></script>

方式二:下载和引入
开发环境 https://vuejs.org/js/vue.js
生产环境 https://vuejs.org/js/vue.min.js
方式三:NPM安装
通过webpack和CLI的安装使用

我的公司开发时使用webpack安装了vue即方式三
注:本文是本人vue学习笔记,本文多数内容属于Vue2.6之前的内容,只有较为重要的地方才会补充2.6版本之后的内容,望周知。

2:Vue中的MVVM

在这里插入图片描述个人理解:
v-view就是页面
m-model就是数据
vm-viewModel是Vue
DOM Listeners就像计数那个例子一样,事件发生了他会监听到反应到页面上
Data Bindings 数据绑定,就是data里的数据,不用像js一样一大堆代码反应到页面上

视频中的讲解
View层:
视图层
在我们前端开发中,通常就是DOM层。
主要的作用是给用户展示各种信息。
Model层:
数据层
数据可能是我们固定的死数据,更多的是来自我们服务器,从网络上请求下来的数据。
在我们计数器的案例中,就是后面抽取出来的obj,当然,里面的数据可能没有这么简单。
VueModel层:
视图模型层
视图模型层是View和Model沟通的桥梁。
一方面它实现了Data Binding,也就是数据绑定,将Model的改变实时的反应到View中
另一方面它实现了DOM Listener,也就是DOM监听,当DOM发生一些事件(点击、滚动、touch等)时,可以监听到,并在需要的情况下改变对应的Data。

3:Vue的生命周期

在这里插入图片描述
在这里插入图片描述
根据生命周期实际中用到的应该是那些方法吧
上图方法
created()创建时执行(比如组件创建出来)
mounted() template挂载到dom上时执行
updated()发生刷新时执行

4:基础语法(插值语法)

mustache语法(双括号语法)

<h2>{{first + last}}</h2>
<h2>{{first + '' + last}}</h2>
<h2>{{first}} {{last}}</h2>和上面的结果一样的
<h2>{{count * 2}}</h2>

v-once指令
在我们不希望一个元素随界面随意的改变而改变时可以使用这个
该指令后面不需要跟任何表达式(比如之前的v-for后面是由跟表达式的)
该指令表示元素和组件(组件后面才会学习)只渲染一次,不会随着数据的改变而改变。

<h2 v-once>{{message}}</h2>
不会变,只会保持最开始的值

v-html指令
某些情况下,我们从服务器请求到的数据本身就是一个HTML代码
如果我们直接通过{{}}来输出,会将HTML代码也一起输出。
但是我们可能希望的是按照HTML格式进行解析,并且显示对应的内容。
如果我们希望解析出HTML展示,可以使用v-html指令,该指令后面往往会跟上一个string类型,会将string的html解析出来并且进行渲染

<h2 v-html="url"></h2>
后端传过来的是一个<a href/>的html语言字符串url,可以让vue自动解析

在这里插入图片描述
v-text指令

<h2 v-text="message"></h2><h2>{{message}}</h2>相同
但它不够灵活。建议使用mastache语法

v-pre指令

<h2 v-pre>{{message}}</h2>显示出来的就是{{message}}

v-cloak指令

<div id="app" v-cloak>{{message}}</div>
当vue还没初始化完成时先显示v-cloak的样式,初始化好vue自己就删了这个
属性,防止网络卡时没加载完vue显示{{message}}

v-bind指令
可以动态绑定a元素的href属性
可以动态绑定img元素的src属性

<img v-bind:src="imgUrl">
后端传回来的图片地址放在imgUrl中通过v-bind反应到页面上
语法糖写法:<img :src="imgUrl">

v-bind绑定class

<!--如果嫌太长可以把这个写到下面的方法里-->true还是false保留不保留class
<!--<h2 :class="{active: isActive, line: isLine}">{{message}}</h2>-->
<h2 :class="getClass()">{{message}}</h2>
:class="{isActive: index === currentIndex}
v-bind绑定style(对象语法)<h2 :style="{key(属性) :value(属性值)}"></h2>//value要加单引号,防止被vue解析成变量
<h2 :style="{fontSize :'50px'}">{{message}}</h2>支持驼峰也支持原来的

用法一:直接通过{}绑定一个类
<h2 :class="{'active': isActive}">Hello World</h2>
用法二:也可以通过判断,传入多个值
<h2 :class="{'active': isActive, 'line': isLine}">Hello World</h2>
用法三:和普通的类同时存在,并不冲突
注:如果isActive和isLine都为true,那么会有title/active/line三个类
<h2 class="title" :class="{'active': isActive, 'line': isLine}">Hello World</h2>
用法四:如果过于复杂,可以放在一个methods或者computed中
注:classes是一个计算属性
<h2 class="title" :class="classes">Hello World</h2>

在这里插入图片描述

v-bind绑定style(数组语法)
<h2 :style="[baseStyle,baseStyle1]">{{message}}</h2>
baseStyle: {background : "blue"},这个在data里
baseStyle1: {fontsize : "30px"}

用法一:直接通过{}绑定一个类
<h2 :class="['active']">Hello World</h2>
用法二:也可以传入多个值
<h2 :class=[‘active’, 'line']">Hello World</h2>
用法三:和普通的类同时存在,并不冲突
注:会有title/active/line三个类
<h2 class="title" :class=[‘active’, 'line']">Hello World</h2>
用法四:如果过于复杂,可以放在一个methods或者computed中
注:classes是一个计算属性
<h2 class="title" :class="classes">Hello World</h2>

在这里插入图片描述
案例:vue v-for出来的列表,点击当前,当前被点击的字体变颜色

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        .active {
            color: red;
        }
    </style>
    <script src="../js/vue.js"></script>
</head>

<body>
    <div id="app">
        <ul>
            <li v-for="(m,item) in movies">
                <a @click="btnClick(item)" :key="item" :class="{active:i===item}">{{item}}--{{m}}</a></li>
        </ul>
    </div>

    <script>
        //创建Vue实例,得到 ViewModel
        var vm = new Vue({
            el: '#app',
            data: {
                movies: ['海王', '星际穿越', '大话西游', '少年派', '盗梦空间'],
                i: 0,
            },
            methods: {
                btnClick: function (index) {
                    this.i = index;
                },
            }
        });
    </script>
</body>

</html>

v-bind也用于向另一个组件传递props值

v-for指令
v-for遍历数组中的对象属性

<tr v-for="(item, index) in books">
  <td>{{item.id}}</td>
  <td>{{item.name}}</td>
  <td>{{item.date}}</td>
  <td>{{item.price | showPrice}}</td>
  <td>
    <button @click="add(index)">+</button>
    {{item.count}}
    <button @click="sub(index)" :disabled="item.count <= 1">-</button>
  </td>
  <td>
    <button @click="removeBook(index)">移除</button>
  </td>
</tr>

v-for遍历数组

<ul>
    <li v-for="(item ,index) in people" @click="change(index)" :class="{isActive: index === currentIndex}">{{index}}-{{item}}</li>
  </ul>
</div>
<script>
  const app = new Vue({
    el : '#app',
    data : {
      message : "hello",
      people: ["爷爷","奶奶","爸爸"],
      currentIndex: 0
    },
    methods : {
      change : function (index) {
        this.currentIndex = index
      },
    }
  })

v-for遍历对象

如果遍历的people是对象则显示的是value
<li v-for="(key, value) in people">{{key}}.{{value}}</li>对象key value都要可以这样
<li v-for="(key, value, index) in people">{{key}}.{{value}}-{{index}}</li>加上索引值(对象值)
<li v-for="item in people" :key="item">{{item}}</li>
最好绑定一个key,插入数据更有效率,key要唯一不变,所以不能用index

官方推荐我们在使用v-for时,给对应的元素或组件添加上一个:key属性。
为什么需要这个key属性呢(了解)?
是为了高效的更新虚拟DOM(设计到Vue的虚拟DOM的Diff算法)

条件判断 v-if、v-else-if、v-else、及条件渲染 v-show指令

<h2 v-if="score>90">优秀</h2>这些写太长,实际可以弄个函数再直接用那个语法
<h2 v-else-if="score>80">良好</h2>
<h2 v-else-if="score>60">及格</h2>
<h2 v-else>不及格</h2>根据条件满足显示那个

<h2 v-show="score>90">优秀</h2>
v-if条件为false时是整个元素都没有,不在dom中,
而v-show条件为false,是因为有个行内样式display: none
导致不显示的当显示与隐藏切换频繁时用v-show,效率高,
只有不频繁时用v-if

事件监听 v-on指令

<button v-on:click="change">按钮</button>
语法糖写法:<button @click="change">click</button>
<button @click="btnClick">click</button>
当btnClick方法要传参数却这样写时,会自动将游览器产生的event事件对象
当做参数传过去
<button @click="btnClick(3,$event)">click</button>
如果传入多个参数时也要获得游览器产生的event事件对象可以用$event传

在某些情况下,我们拿到event的目的可能是进行一些事件处理。

Vue提供了修饰符来帮助我们方便的处理一些事件:

.stop - 调用 event.stopPropagation()。
.prevent - 调用 event.preventDefault()。
.{keyCode | keyAlias} - 只当事件是从特定键触发时才触发回调。
.native - 监听组件根元素的原生事件。
.once - 只触发一次回调。
在这里插入图片描述

<div @click="dClick">
    <button @click.stop="bClick">按钮</button>
</div>加上.stop防止也执行div上的事件(前端将这种称为冒泡)
<input type="submit" value="提交" @click.prevent="sClick">
加上.prevent防止默认的事件执行
<input type="text" @keyup.enter="keyup">
当敲回车键才会执行这个方法
.once这个事件只会执行一次

v-model指令

v-model表单元素和数据的双向绑定
v-model原理
v-model其实是一个语法糖,它的背后本质上是包含两个操作:
1.v-bind绑定一个value属性
2.v-on指令给当前元素绑定input事件
也就是说下面的代码:等同于下面的代码:

<input type="text" v-model="message">
等同于
<input type="text" v-bind:value="message" 
v-on:input="message = $event.target.value">

在这里插入图片描述
v-model 单选框 复选框结合使用
v-model:radio
在这里插入图片描述
v-model:checkbox
复选框分为两种情况:单个勾选框和多个勾选框
单个勾选框:
v-model即为布尔值。
此时input的value并不影响v-model的值。
多个复选框:
当是多个复选框时,因为可以选中多个,所以对应的data中属性是一个数组。
当选中某一个时,就会将input的value添加到数组中。
在这里插入图片描述lable好处就是用户可以点击文字也会选中,一般一个label绑定一个input

v-model:select
单选:只能选中一个值。
v-model绑定的是一个值。
当我们选中option中的一个时,会将它对应的value赋值到mySelect中
多选:可以选中多个值。
v-model绑定的是一个数组。
当选中多个值时,就会将选中的option对应的value添加到数组mySelects中,加入数组好返回给服务器
在这里插入图片描述
修饰符

lazy修饰符:
默认情况下,v-model默认是在input事件中同步输入框的数据的。
也就是说,一旦有数据发生改变对应的data中的数据就会自动发生改变。
lazy修饰符可以让数据在失去焦点或者回车时才会更新:
number修饰符:
默认情况下,在输入框中无论我们输入的是字母还是数字,都会被当做字符串类型进行处理。
但是如果我们希望处理的是数字类型,那么最好直接将内容当做数字处理。
number修饰符可以让在输入框中输入的内容自动转成数字类型:
trim修饰符:
如果输入的内容首尾有很多空格,通常我们希望将其去除
trim修饰符可以过滤内容左右两边的空格

5:创建vue实例中传入的options对象中的选项

在这里插入图片描述
computed:

 computed: {//计算属性,里面写的是方法,但方法名多起属性名,前面不加get
      fullname : function () {
        return this.message+','+this.name
      }
<h2>{{fullname}}</h2>
 computed只会调用一次保存缓存,methods调用几次执行几次没有缓存
本质是get方法,没有set方法,但也可以加进去set方法

computed定义的方法我们是以属性访问的形式调用的,{{computedTest}}
但是methods定义的方法,我们必须要加上()来调用,如{{methodTest()}
对于任何复杂逻辑,你都应当使用计算属性
computed依赖于data中的数据,只有在它的相关依赖数据发生改变时才会重新求值

6:组件化

组件的使用分成三个步骤
创建组件构造器
注册组件
使用组件。
但感觉我的公司实际开发中要么已经直接生成好了,要么写不到这些
在这里插入图片描述
这里的步骤都代表什么含义呢?

1.Vue.extend():
调用Vue.extend()创建的是一个组件构造器。
通常在创建组件构造器时,传入template代表我们自定义组件的模板。
该模板就是在使用到组件的地方,要显示的HTML代码。
事实上,这种写法在Vue2.x的文档中几乎已经看不到了,它会直接使用下面我们会讲到的语法糖,但是在很多资料还是会提到这种方式,而且这种方式是学习后面方式的基础。

2.Vue.component():
调用Vue.component()是将刚才的组件构造器注册为一个组件,并且给它起一个组件的标签名称。
所以需要传递两个参数:1、注册组件的标签名 2、组件构造器

3.组件必须挂载在某个Vue实例下,否则它不会生效
注册组件语法糖
在这里插入图片描述组件自己的数据存放在组件对象的data属性中,这个data属性必须是一个函数,而且这个函数返回一个对象,对象内部保存着数据在这里插入图片描述为什么data在组件中必须是一个函数呢?
首先,如果不是一个函数,Vue直接就会报错。
其次,原因是在于Vue让每个组件对象都返回一个新的对象,因为如果是同一个对象的,组件在多次使用后会相互影响。

全局组件和局部组件
当我们通过调用Vue.component()注册组件时,组件的注册是全局的
这意味着该组件可以在任意Vue示例下使用。
如果我们注册的组件是挂载在某个实例中, 那么就是一个局部组件

父组件和子组件

父子互相调用方法或者属性
父调用子(父函数中)
<cpn ref="aaa"></cpn>
this.$children[0].showMessage()所有子
this.$refs.aaa.showMessage()能找到ref=aaa的子,用的多
子访问父(开发基本用不到)$parent(耦合度太高)$root(根目录一般不放东西)
$children的缺陷:
通过$children访问子组件时,是一个数组类型,访问其中的子组件必须通过索引值。
但是当子组件过多,我们需要拿到其中一个时,往往不能确定它的索引值,甚至还可能会发生变化。
有时候,我们想明确获取其中一个特定的组件,这个时候就可以使用$refs
$refs的使用:
$refs和ref指令通常是一起使用的。
首先,我们通过ref给某一个子组件绑定一个特定的ID。
其次,通过this.$refs.ID就可以访问到该组件了。

父子组件之间通信
父传子通过props属性以及绑定
子传父以子通过$emit方法发送数据

父传子
<div id="app">//这边不支持驼峰,用了驼峰要用c-message="message"
<cpn :cmessage="message" :cpeople="people" :cpokemon="pokemon"></cpn>
</div>
<template id="cpnt">
  <div>//这边可以驼峰
    <h2>{{count}}</h2>
    <h2>{{cmessage}}</h2>
    <h2>{{cpokemon.moves}}</h2>
    <ul>
      <li v-for="item in cpeople">{{item}}</li>
    </ul>
</template>
<script>

const cpn= Vue.component('cpn', {
    template: '#cpnt',
    data() {//数据是方法不能属性防止组件复用时属性交叉更改
      return {
        count: 0
      }
    },
    //props: ['cmessage','cpeople']
    props: {
      cmessage: {
        type: String,
        required: true,
        default: 'sdsdsd'
      },
      cpeople: {
        type: Array,
        required: true,
        default: []
      },
      cpokemon: {
        type: Object,
        default: function () {
          return {message: 'error'}
        }
      }
    }
  })
  const app = new Vue({
    el: '#app',
    data: {
      message: 'hello',
      people: [123,321,12345],
      pokemon: {
        id: 1,
        name: 'pikaque',
        moves: 'quik stast'
      }
    },
    components: {
      cpn
    }
  })
子传父
<cpn @item-click="cpnClick"></cpn>
</div>
<template id="cpnt">
  <div>
    <button v-for="item in cata" @click="btnClick(item)">{{item.name}}</button>
  </div>
</template>
const cpn= Vue.component('cpn', {
    template: '#cpnt',
    data() {
      return {
        cata: [
          {id:1,name:"qwqwqwqw"},
          {id:2,name:"asasasas"},
          {id:3,name:"zxzxzxzx"},
          {id:4,name:"cvcvcvcv"}
        ]
      }
    },
    methods: {
      btnClick(item) {
        this.$emit('item-click',item)
      }
    }
const app = new Vue({
    el: '#app',
    data: {
      message: 'hello'
    },
    components: {
      cpn
    },
    methods: {
      cpnClick(item){
        console.log('cpnClick',item)
      }
    }
  })

7:插槽slot

编译作用域

<div id="app">
  <cpn ref="aaa" v-show="isshow"></cpn>
</div> isshow看vue实例的属性
<template id="cpnt">
  <div>
    <h2 v-show="isShow">weq</h2>
  </div>
</template>看组件里的isShow
父组件模板的所有东西都会在父级作用域内编译;
子组件模板的所有东西都会在子级作用域内编译
即父组件的属性由父组件中的变量决定,子由子决定

作用域插槽:使用
在父组件使用我们的子组件时,从子组件中拿到数据:
我们通过获取到slotProps属性
在通过slotProps.data就可以获取到刚才我们传入的data了

  <cpn>
    <div slot-scope="slot">
      <span>{{slot.data.join(' * ')}}</span>
    </div>
  </cpn>
</div>
<template id="cpnt">
  <slot :data="people">
    <ul>
      <li v-for="item in people">{{item}}</li>
    </ul>
  </slot>
</template>

slot基本使用
在这里插入图片描述

cpn >
    <h2 slot="center">dsfsfdsfds</h2>指定替代那个slot
</cpn>
<slot name="center"><span>222</span></slot>

<div v-if="!isActive"><slot name="item-icon"></slot></div>
    <div v-else><slot name="item-icon-active"></slot></div>
    <div :class="{active: isActive}"><slot name="item-text"></slot></div>
插槽最好外面都包装个div,防止直接替换的时候将指令也替换了,比如这里的:class="{active: isActive}直接写在slot中就会被替换

slot有三种类型
默认插槽 default
具名插槽 name
作用域插槽 v-slot
在子组件中:
插槽用标签来确定渲染的位置,里面放如果父组件没传内容时的后备内容。一个不带 name的 出口会带有隐含的名字“default”。
具名插槽用name属性来表示插槽的名字
作用域插槽在作用域上绑定属性来将子组件的信息传给父组件使用

8:其他

一:过滤器

<td>{{item.price | showPrice}}</td>
filters: {
    showPrice(price){
      return '$' + price.toFixed(2)
    }
  }

二:编译作用域
例子
在这里插入图片描述

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!