Vue2.X_基础

了解Vue

vue.js是一个JavaScriipt MVVM库,是一套构建用户界面的渐进式框架,vue.js兼具了angular.js和react.js的优点,并删除了它们的缺点,作者是尤雨溪(Evan You)。

前端框架

  • jquery
    节点操作简单,浏览器兼容
  • angular
    MVC模式,双向数据绑定,依赖注入
  • react
    virtual DOM(虚拟DOM,即为与DOM一样的对象,操作对象避免DOM的直接操作从而提高性能),性能上辗轧angular
  • vue
    结合angular和react的优点,MVVM模式,高性能高效率框架

架构模式(了解)

复杂软件必须有清晰合理的架构,否则无法开发维护

  • MVC模式
    M: Model (数据) => 数据保存
    V: View (视图) => 用户界面
    C: Controller (控制器) => 业务逻辑
    Vue2.X_基础_第1张图片
  • MVP
    MVP架构模式是MVC的一个变种
    M: Model
    V: View
    P: Presenter,可以理解为松散的控制器,其中包含了视图的UI业务逻辑,所有从视图出发的事件都会通过代理给Presenter进行处理;同时,Presenter也通过视图暴露的接口与其进行通信。
    Vue2.X_基础_第2张图片
  • MVVM
    MVVM架构模式是MVP的演变
    Model
    View
    ViewModel 类似于MVP中的Presenter,唯一区别是它为双向绑定,View的变动自动反映在ViewModel,反之亦然。
    Vue2.X_基础_第3张图片
    核心:关注Model的变化,让MVVM框架利用自己的机制去更新DOM,让开发者从操作DOM的繁琐解脱。

安装引入

vue.js官网下载vue.js文件
script标签

<script src="vue.js">script>

cdn

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

npm

npm install vue

Vue实例化过程

vue是一个构造函数,使用必须先实例化

<script src="libs/vue.js">script>
<body>
   
    <div id="app">
		
		插值表达式(得到一个值的式,如三元运算、字符串split()等)
        {{username}} - {{age}} = {{gender=='女'? 'female':'male'}}
        页面中显示
        katsuki - 18 = female 
	div>
    <script>
        // model层
        let model = {
            username : "katsuki",
            age : 18,
            gender : '女'
        }
        // ViewModel层
        // 是一个view的实例,在实例化过程中,vue会遍历data参数中的数据,写入实例的属性
        let vm = new Vue({
        	// 利用Vue来管理#app这个标签,把div#app这个标签作用根节点
        	// Vue会重新生成这个元素的所有内容
            el : "#app",
            data : model
        })
    script>
body>

在浏览器中打开,F12或右击检查打开控制台输入

两种方式
model.username = 'kasami'
vm.username = 'kasami'

页面中的katsuki会变成kasami,修改实例的属性,model数据与视图都做出响应;修改model另两个也会变。下面描述其原理。

Vue响应式属性原理

存储器属性补充,这里只关心存储器属性使用,结合了oop博文中对象的属性特性(ES5)使用。

let person1 = {
	name : 'katsuki',
	age : 18
}
let person2 = {
	username : 'katsuki_chan',
	age : 17
}
1------------------------------------------------
Object.defineProperty(person2,'skill',{
	enumberable : true,
	get : function(){
		console.log('getter');
	} ,
	set : function(){
		console.log('setter');
	}
});

浏览器控制台输入
person2.skill; // 获取值 执行get内容 打印getter
person2.skill = 'js'; // 设置值 执行set内容 打印setter
2------------------------------------------------
Object.defineProperty(person2,'skill',{
	enumberable : true,
	get : function(){
		let res = person1.age - 1;
		return res;
	} ,
	set : function(val){
		 person1.age = val;
	}
});

浏览器控制台输入
person2.skill; // 操作了person1的age属性 现 age为17
person2.skill = 20; // 操作了person1的age属性 现 age为val(20)

这样就能够通过操作一个对象的属性去改变其他对象的属性
Vue就是通过这样的方法进行系列操作实现响应,就如操作了ViewModel同时改变View和Model的值
<script src="libs/vue.js">script>
<body>
    <div id="app">
        {{username}}
	div>
    <script>
    // Vue在实例化时会遍历data中所有属性,并把他们设置成存储器属性
        let model = {
            username : "katsuki",
            age : 18,
            gender : '女'
        }
        let vm = new Vue({
            el : "#app",
            data : model
        })
        // 实例化后model中的属性被Vue转成存储器属性
        console.log(model);
        // 并把属性写入vm实例,所以操作model和vm都能有响应
        console.log(vm);
        // vm.$data即为model
        console.log(vm.$data);
        // vm.$el即为绑定的节点div#app
        console.log(vm.$el);
    script>
body>

Vue指令

导入vue.js文件使用

<script src="vue.js">script>

指令的解析

<script>
new Vue({
	el : ".katsuki"
    data : {
        name : "katsuki"
    }
})
script>
前半部分如这里的v-text会在vue.js文件中找到解析
后半部分如这里的name会在对应的vue实例中data找到解析
<div class="katsuki" v-text="name">div>

v-text

<div id="show">
	两者效果一致,但{{}}形式会先加载{{}}再加载里面的的内容
	网络差时,会出现大量的{{}},视图体验不好,建议使用v-text指令
	<p v-text="name">p>
	<p>{{name}}p>
div>
<script>
   let katsuki = new Vue({
       el : "#show",
       data : {
           name : "katsuki"
       }
   })
script>

v-html

<div id="show">
	v-html 若内容包含标签结构,会进行标签解析
	v-text 会直接将内容当作字符串显示
	<p v-html="name">p>
	<p v-text="name">p>
div>
<script>
   let katsuki = new Vue({
       el : "#show",
       data : {
           name : `katsuki desu`
       }
   })
script>

v-show & v-if

<div id="show">
	v-show 里面值或表达式为true时显示,为false隐藏,标签结构仍在
    <p v-text="name" v-show="bool">p>
    <p v-html="name" v-show="false">p>
div>
<script>
    let katsuki = new Vue({
        el : "#show",
        data : {
            name : `katsuki`,
            bool : true
        }
    })
script>
<div id="show">
	v-if 里面值或表达式为true时显示,为false移除节点,标签结构删除
    <p v-text="name" v-if="bool">p>
    <p v-text="name" v-if="num>3">p>
div>
<script>
    let katsuki = new Vue({
        el : "#show",
        data : {
            name : `katsuki`,
            bool : true,
            num : 1 
        }
    })
script>

那么什么时候用v-show,什么时候用v-if?
状态经常不断变化用show,反之用if,因为if操作节点性能消耗高,而且if删除节点会把节点的绑定事件一并删除

v-if & v-else & v-else-if

<div id="show">
	v-else 和 v-else-if 前一兄弟元素必须有 v-if 或 v-else-if
	也就是说if、else if、else要连用,不能中断。
    <p v-html="name" v-if="type === 'A'">p>
    <div v-else-if="type === 'B'">
        kasami
    div>
    <div v-else>
        Grisaia
    div>
div>
<script>
    let katsuki = new Vue({
        el : "#show",
        data : {
            name : `katsuki`,
            type : 'A'
        }
    })
script>

v-for

<div id="show">
   v-for 循环生成标签,for in可遍历数组对象
   遍历数组时,con拿到数组内容,idx拿到数组下标
   遍历对象时,con拿到对象的值, idx拿到对象的键
   <div v-for="(con,idx) in contents" v-text="con" :data-idx="idx">
    div>
div>
<script>
    let katsuki = new Vue({
        el : "#show",
        数组
        data : {
            contents : ['katsuki','kasami']
        }
        对象
        data : {
            contents : {
				name : 'katsuki',
				age : 18
			}
        }
    })
script>

v-on

<div id="show">
	v-on事件绑定,v-on:简写为@
    <div v-text="name" v-on:click="testclick">
    <div v-text="name" @click="testclick">
    div>
div>
<script>
    let katsuki = new Vue({
        el: "#show",
        data: {
            name: 'katsuki',
        },
        methods: {
            testclick(){
                console.log(this.name);
            }
        }
    })
script>

v-bind

<div id="show">
	v-bind用于绑定 DOM 属性,v-bind简写为:
    <div v-text="name" v-bind:data-name="name">div>
    <div v-text="age" :data-age="age">div>
    在绑定 class 或 style 特性时,支持其它类型的值,如数组或对象。
    为true写入该类名,为false不写入该类名
    <div :class="{
		'katsuki' : true,
		'kasami' : false
	}">div>
	<div :style="{ fontSize: 18 + 'px' }">div>
div>
<script>
    let katsuki = new Vue({
        el: "#show",
        data: {
            name: 'katsuki',
            age: 18
        }
    })
script>

v-model

<div id="show">
	用 v-model 指令在表单 <input><textarea><select> 
	元素上创建双向数据绑定,会改变view和model层数据
    <div v-text="name">div>
    <input v-model="name" />
div>
<script>
    let katsuki = new Vue({
        el: "#show",
        data: {
            name: 'katsuki'
        }
    })
script>

指令小结

更改一方改变另一方的指令图示
Vue2.X_基础_第4张图片

Vue实现tab切换

使用bootstrap.css


<html lang="en">
<head>
    <meta charset="UTF-8">
    <link rel="stylesheet" href="./libs/bootstrap.css">
    <style>
        .collapse{
            display: block;
        }
    style>
head>
<body>
    <div id="app" class="container">
        <ul class="nav nav-tabs">
            <li class="nav-item" v-for="(tab,idx) in tabs">
                
                <a class="nav-link" href="#" v-bind:class="{active:idx===currentIdx}" 
                @click="change(idx)">{{tab}}a>
            li>
        ul>
        <div class="collapse">
            
            <div class="card card-body" v-for="(con,idx) in contents" v-show="idx===currentIdx">
               {{con}}
            div>
        div>
    div>
    
    <script src="libs/vue.js">script>
    <script>
        // Vue开发,不需要我们过多关注DOM节点操作,而是把精力放大数据和业务结构
        /*
            指令
                v-for  遍历
                v-bind 可以绑定任意属性
                    简写 :
                v-show 显示,隐藏        建议操作节点频繁用
                v-if   显示,移除节点    建议操作节点不频繁用

                v-on 事件绑定
                    简写 @click
        */
        let vm = new Vue({
            el : '#app',
            //数据
            data : {
                tabs : ['Grisaia','kasami','katsuki'],
                contents : ['Grisaia desu','Kasami desu','Katsuki desu'],
                currentIdx : 0
            },
            //方法
            methods : {
                change(idx){
                    this.currentIdx = idx;
                }
            }
        })
    script>
body>
html>

axios

安装

npm安装
npm install axios
cdn安装
<script src="https://unpkg.com/axios/dist/axios.js">script>

第三方js库axois,使用ajax技术封装的接口,npm官方文档中axois的post请求会出问题,下面是解决说明链接

axois POST请求问题
https://github.com/Wscats/vue-tutorial/issues/16

在博文Vue-cli中,结合脚手架描述axios的相关配置

配合vue使用

这里配合第三方模块axios、request使用
npm axois文档
文档中axois请求方法有then和catch,说明返回的是一个Promise
npm request文档

express脚手架中routes的index.js
var express = require('express');
var request = require('request');
var router = express.Router();

/* GET home page. */
router.get('/', function (req, res, next) {
  res.render('index', {
    title: 'Express'
  });
});

router.get('/katsuki', async (req, res, next) => {
  let getData = () => {
    return new Promise((resolve, reject) => {
      //利用request模块请求数据,是服务器代理解决跨域方式,是下下策
      //开发时可以这么做,若上线时前后端继续分离,则要上线前端nodejs服务器和后端服务器
      request('https://katsuki.com?xxx json数据链接', (err, response, body) => {
        resolve(body)
      })
    })
  }
  let data = await getData();
  res.send({
    status: 1,
    data:JSON.parse(data)
  });
});

module.exports = router;
express脚手架中javascripts的一个js文件
new Vue({
	//拿到数据在#katsuki元素中以v-for方式拿到data渲染
    el: "#katsuki",
    data: {
        dataArr: []
    },
    methods: {
        async loadMore() {
            let data = await axios.get('http://localhost:3000/katsuki', {
                params: {
                    ID: 18 //此处传参无意义
                }
            })
            console.log(data);
            //把得到的对象拿到对象中数据位置属性名的对应内容存入数组
            //concat() 方法用于连接两个或多个数组
            //将原本的数组接上添加内容,返回合并后的数组:arr.concat(addcontent)
            this.dataArr = this.dataArr.concat(data.data)
        }
    },
	//生命周期函数,创建后执行created()函数
    created() {
        this.loadMore();
    }
}

计算属性和侦听器

计算属性

<div id="katsuki">
	data和computed的name同样这样调用,因此不能重名
	<p v-text="dname">p>
	<p v-text="cname">p>
div>
<script>
   new Vue({
       el : "#katsuki",
       //data存放默认固定的数据
       data : {
           dname : 'katsuki'
       },
       //computed计算属性,用于需要经过处理或计算等逻辑得到数据
       //计算属性是特殊的data computed强于data
       computed : {
           cname(){
           let str = 'chan';
           return `katsuki` + str;
           }
       }
   })
script>

侦听器

<div id="katsuki">
    <input v-model="name" />
    <p v-text="name">p>
div>
<script src="../../js/vue.js">script>
<script>
    new Vue({
        el: "#katsuki",
        data: {
            name: "katsuki"
        },
        // 监听name的变化,如果有变化,执行对应的函数
        watch: {
            name() {
                console.log(this.name)
            }
        }
    })
script>

组件

没有见过的标签 就是 自定义标签 就是 组件
优势在于分开管理和重复利用
甩锅和偷懒

component

<div id="katsuki">div>
<script>
	// Vue.component其实等价于new Vue
	
	// new Vue里所有的参数都能写在component里
	// 如 el methods watch等,但el在这里无意义,el是根据标签定位,而component本身就是标签
	
	// component中data是函数写法,避免组件复用会互相影响,从而高度独立化
	
    // 子组件
    // 定义一个组件 特殊标签
    // 若Xkatsuki处写div、等已存在标签会生效改写
    // Xkatsuki组件
    Vue.component("Xkatsuki",{
        data(){
            return {
                title : "katsuki组件"
            }
        },
        // template中只能有一个最外层父节点
        template : `
            

`
}) // new Vue是最大的父组件 // Root组件 new Vue({ el : "#katsuki", data : { name : 'katsuki' }, //这里的结构会把原本的#katsuki覆盖 template : `

`
})
script>

extend

<div id="katsuki">div>
<script>
	//先extend定义后,再component注册才能使用
	//代码顺序也必须先定义再实例化
    const Xkatsuki = Vue.extend({
        data(){
            return {
                title : "katsuki组件"
            }
        },
        template : `
            

`
}) //全局注册,会全局污染,一般局部注册 //Vue.component("Xkatsuki",Xkatsuki); new Vue({ el : "#katsuki", data : { name : 'katsuki' }, template : `

`
, //局部注册 components : { Xkatsuki } })
script>

你可能感兴趣的:(Vue)