vue基础知识总结

github github.com/guxiansheng…javascript

1、web前端技术基础

1. 最基础的html, css, javascript

html, css, javascript关系 相似于人体: html为骨架 css为血肉和外貌 javascript是人的行为css

html搭建起整个页面的文档结构,css为文档结构设置样式,javascript作交互行为.html

<!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>demo</title>
  <style>
    .box {
      width: 200px;
      height: 200px;
      border: 1px solid #ccc;
    }
    .box1 {
      font-size: 12px;
      color: red;
    }
    .box2 .p1 {
      font-size: 20px;
      color: blue;
    }
  </style>
</head>
<body>
  <div class="box box1">
    <h1>一念起天涯咫尺</h1>
    <h1>一念灭咫尺天涯</h1>
  </div>
  <div class="box box2">
    <button onclick="changeText(event)">点击修改dom元素</button>
    <p class="p1" id="p1"></p>
  </div>
</body>
<script>
  function changeText(e) {
    var p1 = document.getElementById('p1');
    p1.innerText = Math.random();
  }
</script>
</html>
复制代码

2. 框架介绍

前端目前主要存在如下几个方向,每一个方向存在着不一样的框架前端

  • web:

(1) Vue.jsvue

(2) React.jsjava

(3) Angularnode

  • PWA:

PWA(Progressive Web Apps),谷歌提出的一种基于浏览器的技术,使用web前端技术开发的,可是能够将应用添加到桌面,能够离线使用,能够有推送通知等更加相似于APP的功能.webpack

  • 小程序

微信小程序,QQ小程序,百度小程序等等ios

  • 混合APP开发

(1) React Native(Facebook)git

(2) Flutter(谷歌)

(3) Hbuilder(国内企业作的)

  • 桌面应用开发

Electron

  • 服务端开发

Node.js

Any application that can be written in JavaScript, will eventually be written in JavaScript.

任何可以用 JavaScript 实现的应用,最终都必将用 JavaScript 实现。

3. node.js介绍

Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境。Node.js 使用了一个事件驱动、非阻塞式 I/O 的模型,使其轻量又高效。 官网: nodejs.cn

Node.js主要应用场景以下:

  1. 作服务端开发
  2. 制做先后端分离开发中web前端的开发工具,如webpack等
  3. 作命令行工具
  4. 开发桌面应用,如 Visual Studio Code

4. web前端开发环境

先后端分离开发:

  1. Node.js提供开发工具
    (1)Node.js开发工具能够直接下载 nodejs.cn/download/, 目前使用v10.16.0
    (2)可使用NVM版本管理工具,能够下载多个版本,各个版本之间自由切换(www.jianshu.com/p/d0e0935b1…)
  2. npm包依赖工具 npm会随着Node.js一块儿安装,因此不用单独安装,连接中有详细的使用教程(www.jianshu.com/p/dee4a84e5…).
  3. webpack打包工具 能够通过打包,将各类web前端资源打包成一个个js文件,css文件,html文件,图片等 先后端分离项目通常运行步骤:
  4. npm install (安装项目全部的依赖包)
  5. npm run dev (本地运行开发环境代码,同时Node.js启动一个本地web服务器)
  6. npm run build (本地打包线上环境代码,能够部署)

以上打包命令都会被定义在项目根目录下的package.json中的scripts中,不然没法使用

2、Vue.js基础

1. Vue.js基础

(1) 模板语法

  • 文本
  • v-bind(能够缩写为符号: ':' )
  • v-on(能够缩写为符号: '@')

Demo1.vue中 data中定义的 text属性被绑定到h1标签的内容上了.
srcText是一个图片连接,被绑定到img标签的src属性中
v-on指令绑定了methods中的点击事件clickMethod

(2) 条件

  • v-if
  • v-else
  • v-show

Demo1.vue中根据data中show属性是true/false,显示或者隐藏标签
经过toggle方法切换show的值,从而完成标签的显示和隐藏
v-show只会隐藏元素(修改元素的display属性),可是不会从html文档中删除标签,只是切换显示或者隐藏,因此性能高,适合频繁切换的场景
v-if false时会从html文档中删除标签, 因此性能消耗大,不适合频繁切换的场景

(3) 循环

  • v-for

Demo1.vue中 data里面的arr数组,经过v-for指令完成循环

(4) 事件处理

  • 原生实践绑定

Demo1.vue中 经过v-on绑定html标签原生的相关事件,好比click,mouseover等等, 绑定的方法声明在methods中.

(5) 组件

  • 组件新建

component1.vue组件代码段是一个.vue文件,跟一个普通组件同样的.

  • 组件使用

Demo1.vue中, (1)引入component1.vue, (2)components中引用组件, (3)页面中使用小写使用组件,两个大写则小写后用短横杠分开

  • 组件间传值

父组件向子组件传递数据, Demo1.vue中, text是传入子组件的属性,在子组件component1.vue中经过props接收.

子组件向父组件传递数据, component1.vue组件代码段中经过emitMethod方法emit出去一个data1事件,并传值为 '嘿嘿嘿'; Demo1.vue中,在组件使用的地方接收 v-on:data1="accept",在accept的参数中就是接收到的 '嘿嘿嘿'.

Demo1.vue

<template>
// Demo1.vue
  <div>
    <h1>{{text}}</h1>
    <img class="image1" v-bind:src="srcText" alt="">
    <button v-on:click="clickMethod">点击</button>
    <!-- computed -->
    <hr>
    <button @click="changeRandowNumber">点击生成随机数</button>
    <p>randomNumber:{{randomNumber}}</p>
    <p>test1:{{test1}}</p>
    <!-- watch -->
    <hr>
    <button @click="changeWatchParam">点击生成watchParam</button>
    <!-- 条件 -->
    <hr>
    <button @click="toggle">切换隐藏和显示</button>
    <p v-if="show">显示{{show}}</p>
    <p v-else>隐藏{{show}}</p>
    <p v-show="show">v-show切换{{show}}</p>

    <!-- 循环 -->
    <hr>
    <div v-for="(item, index) in arr" :key="index">{{item}}</div>

    <!-- 组件 -->
    <component1 :text="component1Text" v-on:data1="accept"></component1>
    
    <!-- 子路由 -->
    <router-view></router-view>
  </div>
</template>

<script>
import Component1 from './component1'

export default {
  data () {
    return {
      text: '驴妈妈',
      srcText: 'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1561442417122&di=e6fa319459f0ea95645b2bde6d2591a3&imgtype=0&src=http%3A%2F%2Ff.hiphotos.baidu.com%2Fimage%2Fpic%2Fitem%2F8d5494eef01f3a29f863534d9725bc315d607c8e.jpg',
      randomNumber: 0,
      watchParam: 0,
      show: false,
      arr: [1, 2, 3, 4, 5, 6],
      component1Text: 234
    }
  },
  components: {
    Component1
  },
  // 计算属性
  computed: {
    test1 () {
      let res = 0
      res = this.randomNumber * 1000
      return res
    }
  },
  //
  watch: {
    watchParam (newVal, oldVal) {
      console.log('newVal', newVal)
      console.log('oldVal', oldVal)
    }
  },
  // 组件内路由守卫
  beforeRouteEnter (to, from, next) {
    next(vm => {
      console.log('beforeRouteEnter');
    });
  },
  // 此处不能获取dom,还没有挂载dom
  created () {

  },
  // 此处自由使用
  mounted () {
    this.init();
    console.log('demo1 this.$route', this.$route);
  },
  methods: {
    clickMethod () {
      alert('点击事件')
    },
    init () {
      console.log('init method run')
    },
    changeRandowNumber () {
      this.randomNumber = Math.random()
    },
    changeWatchParam () {
      this.watchParam = Math.random()
    },
    toggle () {
      this.show = !this.show
    },
    accept (data1) {
      console.log('data1', data1)
    }
  }
}
</script>

<style scoped>
.image1 {
  width: 100px;
  height: 100px;
}
</style>
复制代码

component1.vue

// component1.vue组件
<template>
  <div>
    <h1>{{text}}</h1>
    <button @click="emitMethod">子组件传递数据到父组件</button>
  </div>
</template>

<script>
export default {
  data () {
    return {
    }
  },
  props: {
    text: {
      type: Number,
      default: 1
    }
  },
  methods: {
    emitMethod () {
      this.$emit('data1', '嘿嘿嘿')
    }
  }
}
</script>

<style scoped>
</style>
复制代码

2. vue-router

router.vuejs.org/zh/installa…

(1) 单页面开发

单页面开发依赖前端路由,分如下2种实现方式:

  • 哈希模式(默认)
  • history模式

(2) 路由基本使用

  • 路由和子路由

首先, Demo1.vue的template中,应该声明用来匹配子路由
青葱,router/index.js, /Demo1匹配Demo1组件; /Demo1/Demo1Child匹配到Demo1Child组件,此时Demo1Child会显示在Demo1.vue的router-view中

router/index.js

import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'
import Demo1 from '@/views/demo1/Demo1'
import Demo1Child from '@/views/demo1/Demo1Child'
import Demo2 from '@/views/demo2/Demo2'

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/',
      name: 'HelloWorld',
      component: HelloWorld
    },
    {
      path: '/Demo1',
      name: 'Demo1',
      component: Demo1,
      children: [
        {
          path: 'Demo1Child',
          name: 'Demo1Child',
          component: Demo1Child
        }
      ]
    },
    {
      path: '/Demo2/:id',
      name: 'Demo2',
      component: Demo2
    }
  ]
})
复制代码
  • 路由钩子

路由钩子存在如下三种:

  1. 全局路由钩子
  2. 组件内部路由钩子
  3. 路由中的钩子

Demo1.vue中beforeRouteEnter为组件内部路由守卫,即进入路由以前触发的钩子函数

  • 路由传参

路由传参数通常采用如下两种(HelloWorld.vue中turn1和turn2方法分别对应2中不一样的方式):

  1. query,即查询字符串
  2. params, 即路由参数

HelloWorld.vue

<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
    <h2>Essential Links</h2>
    <button @click="turn1">页面跳转query</button>
    <button @click="turn2">页面跳转params</button>
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  data () {
    return {
      msg: 'Welcome to Your Vue.js App'
    }
  },
  methods: {
    turn1 () {
      // 能够到Demo1Child.vue的mounted中打印查看this.$route中接收到的参数
      this.$router.push({path: '/Demo1/Demo1Child', query: {param1: 123, param2: '哈哈哈'}});
    },
    turn2 () {
      // 能够到Demo2.vue的mounted中打印查看this.$route中接收到的参数
      this.$router.push({path: '/Demo2/123'});
    }
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
</style>

复制代码

3. vuex

vuex.vuejs.org/zh/

vuex是vue提供的状态管理工具.主要包含如下几项:
(1) state (状态)
(2) getters (暴露状态的访问)
(3) mutations (提交同步修改state)
(4) actions (异步行为)

模块化使用方式

能够将一个项目的状态树,根据项目功能模块,分模块管理状态树,使得状态管理结构清晰,使用方便. 具体使用能够看项目代码.

vuex目录以下:

(1) src/store/index.js将store下的modules模块和root模块合并管理并导出
(2) src/main.js须要将src/store/index.js引入,并挂载到vue实例上 (3) Demo2.vue中使用如代码所示,mapGetters应写在computed下,并声明模块home,便可在页面使用isLogin了; mapMutations和mapActions则应该在methods中声明,使用如代码所示,便可在组件内部使用.

src/store/index.js

import Vue from 'vue';
import Vuex from 'vuex';
import root from './root';
import home from './modules/home';

Vue.use(Vuex);

const store = new Vuex.Store({
  modules: {
    root,
    home
  }
});

export default store;
复制代码

src/store/root.js

const state = {};
const getters = {};
const mutations = {};
const actions = {};

export default {
  namespaced: true,
  state,
  getters,
  mutations,
  actions
}
复制代码

src/modules/home.js

import api from '../../api/index';

const state = {
  isLogin: false
};
const getters = {
  isLogin: state => state.isLogin
};
const mutations = {
  changeLoginState (state, data) {
    state.isLogin = data;
  }
};
const actions = {
  login (context, params) {
    // 可作异步请求
    // setTimeout(() => {
    //   // context.state.isLogin = true;
    //   context.commit('changeLoginState', true);
    // }, 2000);

    return new Promise((resolve, reject) => {
      api.ajaxGetMethod(params).then(res => {
        if (true) {
          resolve(res);
        } else {
          reject(res);
        }
      });
    });
  }
};

export default {
  namespaced: true,
  state,
  getters,
  mutations,
  actions
}
复制代码

src/main.js

import store from './store'
/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  store,
  components: { App },
  template: '<App/>'
})
复制代码

src/views/demo2/Demo2.vue

<template>
  <div>
    <h1>Demo2</h1>
    <p>{{isLogin}}</p>
    <button @click="login()">登录</button>
  </div>
</template>

<script>
import { mapGetters, mapMutations, mapActions } from 'vuex';
export default {
  data () {
    return {}
  },
  computed: {
    ...mapGetters('home', ['isLogin'])
  },
  methods: {
    ...mapMutations('home', ['changeLoginState']),
    ...mapActions('home', ['login']),
    // async, await异步调用
    async loginMethod () {
      try {
        let res = await this.login({});
        console.log('res', res);
      } catch (error) {
        console.error('error', error);
      }
    }
  }
}
</script>

<style scoped>
</style>
复制代码

4. axios

www.kancloud.cn/yunye/axios…

(1) 建议将请求统一管理,避免项目内部散乱的写
(2) 建议结合vuex使用,固然也能够不结合. src/store/modules/home.js中的actions 下的login方法就是结合vuex使用的,能够在获得异步请求结果后直接修改状态
(3) 也能够将src/api/index.js引入任何组件,调用方法便可发送ajax请求
(4) 使用async,await(完全解决回调地狱问题). 首先src/store/modules/home.js中actions下的login方法返回new Primise; 其次在src/views/demo2/Demo2.vue中loginMethod方法前应写标致 async ,调用login前应写await;最后应使用try...catch捕获异常

src/api/index.js

import axios from 'axios';

export default {
  ajaxGetMethod: params => axios.get('/xx', {params: params}).then(res => res.data),
  ajaxPostMethod: body => axios.get('/yy', body).then(res => res.data)
}
复制代码

src/store/modules/home.js

import api from '../../api/index';

const state = {
  isLogin: false
};
const getters = {
  isLogin: state => state.isLogin
};
const mutations = {
  changeLoginState (state, data) {
    state.isLogin = data;
  }
};
const actions = {
  login (context, params) {
    // 可作异步请求
    // setTimeout(() => {
    //   // context.state.isLogin = true;
    //   context.commit('changeLoginState', true);
    // }, 2000);

    return new Promise((resolve, reject) => {
      api.ajaxGetMethod(params).then(res => {
        if (true) {
          resolve(res);
        } else {
          reject(res);
        }
      });
    });
  }
};

export default {
  namespaced: true,
  state,
  getters,
  mutations,
  actions
}
复制代码

src/views/demo2/Demo2.vue

async loginMethod () {
      try {
        let res = await this.login({});
        console.log('res', res);
      } catch (error) {
        console.error('error', error);
      }
}
复制代码

5. vue-cli

2.x 版本: github.com/vuejs/vue-c…
3.x 版本: cli.vuejs.org/zh/

2.x 新建项目: vue init template-name project-name

3.x 新建项目: vue create xxx

相关文章
相关标签/搜索