心想着虽然自己不搞前端,但是一般的前端代码自己总得看得懂吧,那国内目前比较火的前端框架,那肯定是vue了,就花一天时间来学习一下吧,就当入个门,至少以后看到代码至少懂一些基础的东西。

一、环境安装

坑还是比较多的,安装了很久,各种问题,参考这个博客,少走弯路:
目录参考:

二、快速上手

1. 定义属性

首先通过new Vue()来创建Vue实例,然后构造函数接收一个对象,对象中有一些属性:

  • el:是element的缩写,通过id选中要渲染的页面元素,本例中是一个div
  • data:数据,数据是一个对象,里面有很多属性,都可以渲染到视图中
  • name:这里我们指定了一个name属性
  • 页面中的h2元素中,我们通过{{name)}的方式,来渲染刚刚定义的name属性。
<template>
  <div class="hello">
    <h3>Vue基础</h3>
    <p>{{ message }}</p>
    <div>{{rawHtml}}</div>
    <div v-html="rawHtml"></div>
    <div v-bind:id="dynamicId"></div>
    <p>{{num+10}}</p>
    <p>{{flag?"孙猴子":"傻猴子"}}</p>
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  data(){
    return {
      message:"测试Vue学习",
      rawHtml:"<a href='https://www.itbaizhan.com/'>百战</a>",
      dynamicId:10001,
      num:10,
      flag:true
    }
  }
}
</script>

2. Vue生命周期(钩子)

每个Vue实例在被创建时都要经过一系列的初始化过程︰

创建实例,装载模板,渲染模板等等。Vue为生命周期中的每个状态都设置了钩子函数(监听函数)。

每当Vue实例处于不同的生命周期时,对应的函数就会被触发调用。

1、生命周期:

vue 前端架构设计图 基于vue前端框架设计_axios

2、渲染数据:钩子函数

例如: created代表在vue实例创建后;
我们可以在Vue中定义一个created函数,代表这个时期的构造函数;

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <div id="app">
        <button @click="handleClick">点我</button><br>
        <input type="text" v-model="num" /><button @click="num++">+</button>
        <h1>
           {{name}} xxx非常美丽!<br>
            {{num}} 位其着迷!
        </h1>
    </div>
<script src="node_modules/vue/dist/vue.js"></script>
<script>
    const app = new Vue({
        el:"#app",//elemnet,vue 作用的标签
        data:{
            name:"",
            num: 1,
        },
        methods : {
            handleClick(){
                console.log(this)
                console.log("hello");
            }
        },
        created(){
            //向后台发起Ajax请求,完成对data数据初始化
            this.name = "虎哥";
        }
    });
</script>
</body>
</html>

模拟实际渲染数据:this 我们可以看下在vue内部的this变量是谁,我们在created的时候,打印this

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <div id="app">
        <button @click="handleClick">点我</button><br>
        <input type="text" v-model="num" /><button @click="num++">+</button>
        <h1>
           {{name}} xxx非常美丽!<br>
            {{num}} 位其着迷!
        </h1>
    </div>
<script src="node_modules/vue/dist/vue.js"></script>
<script>
    const app = new Vue({
        el:"#app",//elemnet,vue 作用的标签
        data:{
            name:"",
            num: 1,
        },
        methods : {
            handleClick(){
                console.log(this)
                console.log("hello");
            }
        },
        created(){
            //向后台发起Ajax请求,完成对data数据初始化
            setTimeout(() => this.name = "虎哥 真的",1000)
        }
    });
</script>
</body>
</html>

总结: this就是当前的Vue实例,在Vue对象内部,必须使用this才能访问到Vue中定义的data内属性、方法等。

3. 指令

什么是指令?
指令(Directives)是带有 v-前缀的特殊属性。

例如我们在入门案例中的v-model,代表双向绑定。

1、插值表达式
(1)花括号

格式:{{表达式}}

说明;

  • 该表达式支持JS语法,可以调用js内置函数(必须有返回值)
  • 表达式必须有返回结果。例如1+1,没有结果的表达式不允许使用,如: var a = 1+1;
  • 可以直接获取Vue实例中定义的数据或函数

示例
HTML:<div id= " app">i{name ) )</div>

JS:

var app =new vue({
	el:"#app",
	data:{
		name:"Jack""
	}
})
2、差值闪烁

使用0方式在网速较慢时会出现问题。在数据未加载完成时,页面会显示出原始的

加载完毕后才显示正确数据,我们称为插值闪烁。

我们将网速调慢一些,然后试试看刚才的案例:发现刷新页面有延迟

3、使用v-text和v-html

使用v-textv-html指令来替代{{}}说明:

v-text∶将数据输出到元素内部,如果输出的数据有代码,会作为普通文本输出

v-html:将数据输出到元素内部,如果输出的数据有HTML代码,会被渲染

4、v-model

刚才的v-text和v-html可以看做是单向绑定,数据影响了视图渲染,但是反过来就不行。

接下来学习的v-model是双向绑定,视图(view)和模型(Model)之间会互相影响。

既然是双向绑定,一定是在视图中可以修改数据,这样就限定了视图的元素类型。

目前v-model的可使用元素有:input、select、textarea、checkbox、radio、components(Vue中的自定义组件)

5、v-on
(1)基本用法

v-on指令用于给页面元素绑定事件。

语法:v-on:事件名="js片段或函数名"

简写语法:例如v-on:click='add'可以简写为@click='add'

<template>
  <div class="hello">
    <!-- <button v-on:click="counter += 1">点击:counter = {{counter}}</button> -->
    <button @:click="counter += 1">点击:counter = {{counter}}</button>
    <button @:click="clickHandle">按钮</button>
    <p>{{ message }}</p>
    <button @click="say('hi')">say hi</button>
    <button @click="say('what')">say what</button>
    <ul>
      <li @click="clickItemHandle(item)" v-for="(item,index) in names" :key="index">
      {{item}}
      </li>
    </ul>
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  data(){
    return {
      counter:1,
      message:"消息通知",
      names:["iwen","ime","frank"]
    }
  },
  methods:{
    clickHandle(event){
      // console.log("哈哈哈");
      //在事件中,读取data中的属性,是需要通过this.属性来实现的
      this.message = "消息被撤回了";
      //event是原生DOM event
      console.log(event);
      event.target.innerHTML = "点击之后"
    },
    say(data){
      console.log(data);
    },
    clickItemHandle(item){
      console.log(item);
    }
  }
}
</script>
(2)点击事件(包含关系(冒泡))
(3)点击事件(设置不自动包含关系(停止冒泡))
(4)事件修饰符

在事件处理程序中调用event.preventDefault()或event.stopPropagation())是非常常见的需求。

尽管我们可以在方法中轻松实现这点,但更好的方式是:方法只有纯粹的数据逻辑,而不是去处理DOM事件细节。

为了解决这个问题,Vue.js 为v-on提供了事件修饰符。

之前提过,修饰符是由点开头的指令后缀来表示的

  • stop ︰阻止事件冒泡
  • prevent :阻止默认事件发生
  • capture :使用事件捕获模式
  • self∶只有元素自身触发事件才执行。(冒泡或捕获的都不执行)
  • once:只执行一次
(5) 阻止默认事件发生 阻止a标签跳转
6、v-for

遍历数据渲染页面是非常常用的需求,Vue中通过v-for指令来实现。

(1)遍历数组

语法:v-for="item in items ""

  • items:要遍历的数组,需要在vue的data中定义好。
  • item:迭代得到的数组元素的别名
<template>
  <div class="hello">
    <h3>列表渲染</h3>
    <ul>
      <li v-for="item in newsList">
      {{ item.title }}
      </li>
    </ul>
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  data(){
    return {
      newsList:[
        {
          id:1001,
          title:"今日新闻1"
        },
        {
          id:1002,
          title:"今日新闻2"
        },
        {
          id:1003,
          title:"今日新闻3"
        }
      ]
    }
  }
}
</script>
(2)遍历数组:多个参数(数组角标)

在遍历的过程中,如果我们需要知道数组角标,可以指定第二个参数:
语法:v-for=" (item, index) in items "

  • items:要迭代的数组
  • item:迭代得到的数组元素别名
  • index:迭代到的当前元素索引,从0开始
7、key

当Vue.js用v-for 正在更新已渲染过的元素列表时,它默认用"就地复用"策略。

如果数据项的顺序被改变,Vue将不会移动DOM元素来匹配数据项的顺序,而是简单复用此处每个元素,并且确保它在特定索引下显示已被渲染过的每个元素。

这个功能可以有效的提高渲染的效率。

但是要实现这个功能,你需要给Vue一些提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素

需要为每项提供一个唯一 key属性。理想的key值是每项都有的且唯一的id。

提升加载数据的速度

8、v-if和v-show

v-if,顾名思义,条件判断。当得到结果为true时,所在的元素才会被渲染。
语法:v-if”布尔表达式”

9、v-if与v-for结合以及v-else
(1)v-if

当v-if和v-for出现在一起时,v-for优先级更高。也就是说,会先遍历,再判断条件。

<template>
  <div class="hello">
    <p v-if="flag"> 我是程哥哥 </p>
    <p v-else> 我不是程哥哥 </p>
    <p v-show="flag"> 真的是程哥哥呀 </p>
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  data(){
    return {
      flag:false
    }
  }
}
</script>
(2)v-else
(3)v-if和v-show的区别(面试常问)
10、v-bind
(1)创建新的HTML页面
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <div id="app">



    </div>
<script src="node_modules/vue/dist/vue.js"></script>
<script>
    const app = new Vue({
        el:"#app",//elemnet,vue 作用的标签
        data:{

        }
    });
</script>
</body>
</html>
(2)编写CSS样式和HTML
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style type="text/css">
        div #box{
            width:100px;
            height: 100px;
            color: darkgray;
        }
        .red{
            background-color: red;
        }
        .blue{
            background-color: blue;
        }
    </style>
</head>
<body>
    <div id="app">
        <button>红色</button>
        <button>蓝色</button>
        <div id="box" class="red">
            我是盒子
            我是盒子
        </div>
    </div>
<script src="node_modules/vue/dist/vue.js"></script>
<script>
    const app = new Vue({
        el:"#app",//elemnet,vue 作用的标签
        data:{

        }
    });
</script>
</body>
</html>
(3)添加点击切换图片的事件
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style type="text/css">
        div #box{
            width:100px;
            height: 100px;
            color: darkgray;
        }
        .red{
            background-color: red;
        }
        .blue{
            background-color: blue;
        }
    </style>
</head>
<body>
    <div id="app">
        <button @click="color='red'">红色</button>
        <button @click="color='blue'">蓝色</button>
        <div id="box" class="{{color}}">
            我是盒子
            我是盒子
        </div>
    </div>
<script src="node_modules/vue/dist/vue.js"></script>
<script>
    const app = new Vue({
        el:"#app",//elemnet,vue 作用的标签
        data:{
            color:"red",
        }
    });
</script>
</body>
</html>
11、计算属性

在插值表达式中使用js表达式是非常方便的,而且也经常被用到。

但是如果表达式的内容很长,就会显得不够优雅,而且后期维护起来也不方便

12、单表输入绑定

form表单输入值获取

<template>
  <div class="hello">
    <input type="text" v-model="username">
    <p>{{username}}</p>
    <button @click="clickGetUserName">获取用户名</button>
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  data(){
    return {
      username:""
    }
  },
  methods:{
    clickGetUserName(){
      console.log(this.username);
    }
  }
}
</script>
13、watch
(1)监控

watch可以让我们监控一个值的变化,从而做出相应的反应。

(2)浅监控
(3)深监控,监控对象

4. 组件化

在大型应用开发的时候,页面可以划分成很多部分。

往往不同的页面,也会有相同的部分。例如可能会有相同的头部导航。

但是如果每个页面都独白开发,这无骚增加了我们开发的成本。

所以我们会把页面的不同部分拆分成独立的组件,然后在不同页面就可以共享这些组件,避免重复开发。

1、定义安全组件

我们通过Vue的component方法来定义一个全局组件。

2、组件的复用

定义好的组件,可以任意复用多次:

3、局部注册

一旦局部注册,就意味着即便以后你不再使用这个组件,它依然会随着Vue的加载而加载。

因此,对于一些并不频繁使用的组件,我们会采用局部注册。

我们先在外部定义一个对象,结构与创建组件时传递的第二个参数一致:

<template>
    <h3>我是单文件组件</h3>
</template>
<script>
    export default{
        name:"MyComponent"
    }
</script>
<style>
h3{
    color: red;
}
</style>
4、组件通信

通常一个单页应用会以一棵嵌套的组件树的形式来组织:

vue 前端架构设计图 基于vue前端框架设计_axios_02

  • 页面首先分成了顶部导航,左侧内容区,
  • 左侧内容区又分为上下两个组件
  • 右侧边栏中又包含了3个子组件

各个组件之间以嵌套的关系组合在一起,那么这个时候不可避免的会有组件间通信的需求。

(1)父向子传递:props

比如我们有一个子组件:

Vue.component("introduce",{
    // 直接使用props接收到的属性来渲染页面
    template:'<h3>{{title}}</h3>',
    props:[title] // 通过props来接收一个父组件传递的属性
})
  • 这个子组件中要使用title属性渲染页面,但是自己并没有title属性
  • 通过props来接收父组件属性,名为title
<template>
    <h3>prop传递数据</h3>
    <p>{{title}}</p>
    <p>age={{age}}</p>
    <p>{{names}}</p>
    <ul>
        <li v-for="(item,index) in names" :key="index">{{item}}</li>
    </ul>
</template>
<script>


    export default{
        name:"PropComponent",
        props:{
            title:{
                type:String,
                default:""
            },
            age:{
                type:Number,
                default:0
            },
            names:{
                type:Array,
                //数组和对象必须使用函数来返回
                default:function(){
                    return []
                }
            }
        }
    }
</script>
<style scoped>

</style>
(2)子向父通信
  • 子组件接收父组件的num属性
  • 子组件定义点击按钮,点击后对num进行加或减操作
  • vue提供了一个内置的this.$emit函数,用来调用父组件绑定的函数
<template>
    <h3>自定义事件传递数据</h3>
    <button @click="sendClickHandle">点击传递</button>
</template>
<script>

    export default{
        name:"ZidingyiComponent",
        data(){
        return{
            message:"我是ZidingyiComponent"
        }
    },
    methods:{
        sendClickHandle(){
            //参数一:字符串
            //参数二:传递的数据
            this.$emit("onEvent",this.message);
        }
    }
    }
    
</script>
<style scoped>

</style>
<template>
  <img alt="Vue logo" src="./assets/logo.png">
  <ZidingyiComponent @onEvent="getDataHandle"/>
  <p>{{message}}</p>
</template>

<script>
  
import ZidingyiComponent from './components/ZidingyiComponent.vue';
export default {
  name: 'App',
  data(){
    return {
      message:""
    }
  },
  components: {
    ZidingyiComponent
},
methods:{
  getDataHandle(data){
    console.log(data);
    this.message=data;
  }
}
}
</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>

5. Axios请求

1. axios发送网络请求
<template>
  <div class="hello">
    <p>{{chengping}}</p>
  </div>
</template>

<script>
import axios from "axios"


export default {
  name: 'HelloWorld',
  data(){
    return{
      chengping:{}
    }
  },
  mounted(){
    axios({
      method:"get",//or post
      url:"www.baidu.com"
    }).then(res=>{
      console.log(res.data);
      this.chengping=res.data;
    })
  }
}
</script>
2. axios网络请求封装
import axios from "axios"
import { config } from "process";
import querystring from "querystring"

const instance = axios.create({
    //网络请求公共配置
    timeout:5000

})
//拦截器最常用
//发送数据
instance.interceptors.request.use(
    config=>{
        if(config.methods==="post"){
            config.data = querystring.stringify(config.data)
        }
        //config:包含网络请求的所有信息
        return config;
    },
    error=>{
        return Promise.reject(error)
    }
)
//获取数据之前
instance.interceptors.response.use(
    response=>{
        return response.status === 200?Promise.resolve(response):Promise.reject(error);
    },
    error=>{
        const { response } = error;
        //错误的处理才是我们最应该关注的
        errprHandle(response.status,response.info);
    }
)
export default instance;

6. 路由配置

https://router.vuejs.org/zh/