博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Vue 基础总结(2.x)
阅读量:3968 次
发布时间:2019-05-24

本文共 14474 字,大约阅读时间需要 48 分钟。

GitHub源码 :

vue 环境搭建

一、初始化项目

  1. 生成package.json
yarn init -y
  1. 创建入口js: src/index.js
console.log('Hello Webpack!')document.getElementById('root').innerHTML = '

Hello222

'
  1. 创建页面文件: index.html

二、webpack基本使用

  1. 下载依赖包
yarn add -D webpack webpack-cliyarn add -D html-webpack-plugin
  1. 创建webpack配置: webpack.config.js
const path = require('path')    const HtmlWebpackPlugin = require('html-webpack-plugin')    module.exports = {
// 模式: 生产环境 mode: 'production', // 入口 entry: {
app: path.resolve(__dirname, 'src/index.js') }, // 出口(打包生成js) output: {
filename: 'static/js/[name].bundle.js', path: path.resolve(__dirname, 'dist') }, // 模块加载器 module: {
rules: [ ] }, // 插件 plugins: [ new HtmlWebpackPlugin({
template: 'index.html', filename: 'index.html' }) ] }
  1. 生成环境打包并运行
配置打包命令:  "build": "webpack --mode production"打包项目: yarn build运行打包项目: serve dist

三、开发环境运行

  1. 现在的问题
每次修改项目代码后, 必须重新打包, 重新运行
  1. 下载依赖包
yarn add -D webpack-dev-server
  1. 配置开发服务器
devServer: {
open: true, // 自动打开浏览器 quiet: true, // 不做太多日志输出}
  1. 配置开启source-map调试
devtool: 'cheap-module-eval-source-map'
  1. 开发环境运行
配置命令: "dev": "webpack-dev-server --mode development"执行命令: yarn dev

四、打包处理 ES6/CSS/图片

  1. 处理ES6
a. 下载依赖包	yarn add -D babel-loader @babel/core @babel/preset-envb. 配置{
test: /\.js$/, //exclude: /(node_modules|bower_components)/, include: path.resolve(__dirname, 'src'), use: {
loader: 'babel-loader', options: {
presets: ['@babel/preset-env'] } }}
  1. 处理CSS
a. 下载依赖包    yarn add -D css-loader style-loaderb. 配置{
test: /\.css$/, use: ['style-loader', 'css-loader'], // 多个loader从右到左处理}
  1. 处理图片
a. 下载依赖包        yarn add -D url-loader@2.3.0 file-loader@4.3.0 b. 配置 {
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, loader: 'url-loader', options: {
limit: 1000, name: 'static/img/[name].[hash:7].[ext]' // 相对于output.path } }
  1. 测试
a. 添加图片: src/assets/imgs/logo.pngb. 添加css: src/assets/css/my.cssimg {
width: 200px; height: 200px;}c. index.jsimport logo from './assets/imgs/logo.png'import './assets/css/my.css'const image = new Image()image.src = logodocument.body.appendChild(image)document.getElementById('root').innerHTML = '

Hello222

'

五、搭建vue的环境

1). 文档:    https://vue-loader.vuejs.org/zh/2). 下载依赖包:    yarn add vue    yarn add -D vue-loader vue-template-compiler3). 配置    const VueLoaderPlugin = require('vue-loader/lib/plugin')    {
test: /\.vue$/, include: path.resolve(__dirname, 'src'), loader: 'vue-loader' } {
test: /\.css$/, use: ['vue-style-loader', 'css-loader'], } new VueLoaderPlugin() // 引入模块的解析 resolve: {
extensions: ['.js', '.vue', '.json'], // 可以省略的后缀名 alias: {
// 路径别名(简写方式) 'vue$': 'vue/dist/vue.esm.js', // 表示精准匹配 } }4). 编码: src/App.vue src/index.js

六、解决开发环境ajax请求跨域问题

  1. 利用webpack-dev-server进行请求代理转发
webpack-dev-server内部利用http-proxy-middle包对特定请求进行转发操作
  1. 配置:
devServer: {
proxy: {
// 处理以/api开头路径的请求 // '/api': 'http://localhost:4000' '/api': {
target: 'http://localhost:4000', // 转发的目标地址 pathRewrite: {
'^/api' : '' // 转发请求时去除路径前面的/api }, changeOrigin: true, // 支持跨域 } }}
1). 利用webpack-dev-server进行请求代理转发    webpack-dev-server内部利用http-proxy-middle包对特定请求进行转发操作2). 配置:    devServer: {
proxy: {
// 处理以/api开头路径的请求 // '/api': 'http://localhost:4000' '/api': {
target: 'http://localhost:4000', // 转发的目标地址 pathRewrite: {
'^/api' : '' // 转发请求时去除路径前面的/api }, changeOrigin: true, // 支持跨域 } } }

七、配置async/await的编译环境

  1. 下载包
yarn add @babel/runtime-corejs2
  1. 配置
presets: [   ['@babel/preset-env', {
useBuiltIns: 'usage', 'corejs': 2 // 处理一些新语法的实现 }]]

八、解决mint-ui按需引入配置异常的问题

  1. 文档上的配置
"plugins": [    ["component", [        {
"libraryName": "mint-ui", "style": true } ]]]
  1. 异常信息
Error: .plugins[0][1] must be an object, false, or undefined
  1. 原因
文档编写时, 是根据老的babel版本编写的, 新版本的babel配置有变化以前是数组, 现在只能是对象
  1. 修正
"plugins": [    ["component", {
"libraryName": "mint-ui", "style": true }]]

九、解决history模式路由请求404的问题

devServer: historyApiFallback: true, // 任意的 404 响应都被替代为 index.htmloutput: publicPath: '/', // 引入打包的文件时路径以/开头

vue 组件化

一、vue单文件组件

二、组件化编码的基本流程

  1. 拆分界面, 抽取组件

  2. 编写静态组件

  3. 编写动态组件

    • 初始化数据, 动态显示初始化界面
    • 实现与用户交互功能
  4. 设计data

    类型: [{id: 1, title: ‘xxx’, completed: false}]
    名称: todos
    位置: 如果只是哪个组件用, 交给它, 如果是哪些组件用, 交给共同的父组件

  5. 关于状态数据的更新

    data数据定义在哪个组件, 更新数据的行为就定义在哪个组件
    如果子组件要更新父组件的数据, 调用父组件的更新函数来更新父组件的数据
    一个组件接收属性数据不要直接修改, 只是用来读取显示的

三、组件间通信

  1. 组件通信的5种方式

props

vue的自定义事件
全局事件总线
slot
vuex

  1. props
父子组件间通信的基本方式属性值的2大类型:    一般/非函数: 父组件-->子组件    函数: 子组件-->父组件问题:     隔层组件间传递: 必须逐层传递(麻烦)    兄弟组件间: 必须借助父组件(麻烦)
  1. vue自定义事件
  • 给子组件标签绑定事件监听
  • 子组件向父组件的通信方式
  • 功能类似于function props
  • 不适合隔层组件和兄弟组件间的通信
  1. 全局事件总线
  • 利用vm对象的 o n ( ) / on()/ on()/emit()/$off()
  • 利用vm对象是组件对象的原型对象
  • 创建vm对象作为全局事件总线对象保存到Vue的原型对象上, 所有的组件对象都可以直接可见:
    • Vue.prototype.$bus = new Vue()
    • 任意组件A可以通过this. b u s . bus. bus.on()绑定监听接收数据
    • 任意组件B可以通过this. b u s . bus. bus.emit()分发事件, 传递数据
  1. slot
  • 父组件向子组件通信
  • 通信是带数据的标签

注意: 标签是在父组件中解析

  1. vuex
  • 多组件共享状态(数据的管理)
  • 组件间的关系也没有限制
  • 功能比事件总线强大, 更适用于vue项目

vue单文件组件

vue-ajax

一、vue 项目中常用的2个ajax库

  • vue-resource

    vue 插件,非官方库, vue1.x 使用广泛

    **在线文档:**https://github.com/pagekit/vue-resource/blob/develop/docs/http.md

  • axios

    通用的ajax请求库,官方推荐, vue2.x 使用广泛

    **在线文档:**https://github.com/pagekit/vue-resource/blob/develop/docs/http.md

安装插件:

// yarn 安装yarn add vue-resource axios// nmp 安装npm install vue-resource --savenpm install axios --save

二、vue-resource、axios 的使用

案例效果

ajax_test (4)

vue-resource:

编码:

index.js

import Vue from 'vue'import VueResource from 'vue-resource' import APP from './APP.vue' // 引入自定义组件Vue.config.productionTip = false;// 声明使用Vue插件Vue.use(VueResource); // 内部给所有的组件对象都添加一个属性对象: $httpnew Vue({
el: '#root', render: h => h(APP),});

APP.vue

axios

index.js

import Vue from 'vue'import APP from './APP.vue' // 引入自定义组件Vue.config.productionTip = false;new Vue({
el: '#root', render: h => h(APP),});

APP.vue

三、使用express 快速搭建后台接口

编码:

server.js

/*    后台服务器应用模块: 使用express快速搭建后台路由 */const express = require('express');const axios = require('axios');const app = express();// 注册后台路由(转发请求)app.get('/repositories/:q', (rep, res) =>{
const q = rep.params.q; axios({
method: 'GET', url: 'https://api.github.com/search/repositories', params: {
q, sort: 'stars' } }).then(response =>{
const {
name, html_url} = response.data.items[0]; res.send({
status: 0, data: {
name, html_url} }); });});app.listen('4000', () =>{
console.log("server listen on http://localhost:4000");})

测试:

启动express: node server.js

image-20210113123341827

  • http://localhost:4000/repositories/v

image-20210113123245518

vuex

一、vuex的核心概念

1、state

vuex管理的状态对象它应该是唯一的const state = {  xxx: initValue}

2、mutations

包含多个直接更新state的方法(回调函数)的对象谁来触发: action中的commit('mutation名称')只能包含同步的代码, 不能写异步代码const mutations = {  yyy (state, {data1}) {    // 更新state的某个属性  }}

3、actions

包含多个事件回调函数的对象通过执行: commit()来触发mutation的调用, 间接更新state谁来触发: 组件中: $store.dispatch('action名称', data1)  // 'zzz'可以包含异步代码(定时器, ajax)const actions = {  zzz ({commit, state}, data1) {    commit('yyy', {data1})  }}

4、getters

包含多个计算属性(getter)的对象谁来读取: 组件中: $store.getters.xxxconst getters = {  mmm (state) {    return ...  }}

5、modules

包含多个module的对象一个module是一个包含state/mutations/actions/getters的对象是将一复杂应用的vuex代码进行多模块拆分的第2种方式

6、store

vuex的核心管理对象, 是组件与vuex通信的中间人读取数据的属性    state: 包含最新状态数据的对象    getters: 包含getter计算属性的对象更新数据的方法    dispatch(): 分发调用action    commit(): 提交调用mutation

二、使用vuex

1. 创建并向外暴露store对象

export default new Vuex.Store({  state,  mutations,  actions,  getters,  modules: {    a,    b  }})

2. 注册store: main.js

import store from './store'new Vue({  store})

3. 组件中通过store与vuex通信

import {mapState, mapGetters} from 'vuex'export default {  computed: (    ...mapState(['xxx']),    ...mapGetters(['yyy'])  )  methods: {        test () {            this.$store.dispatch('zzz', data)            this.$store.commit('zzz', data)        }  }}

三、 Vuex结构图

image-20210125001753385

Vue-router

一、vue-router的基本使用

1). 创建路由器: router/index.js    new VueRouter({      mode: 'hash/history'      routes: [        { // 一般路由          path: '/about',          component: About        },        { // 自动跳转路由          path: '/',          redirect: '/about'        }      ]    })2). 注册路由器: main.js    import router from './router'    new Vue({      router    })3). 使用路由组件标签:    
Go to XXX
// 可以不使用
// 必须使用4). 2个对象 $router: 代表路由器对象, 包含一些实现路由跳转/导航的方法: push()/replace()/back() $route: 代表当前路由对象, 包含一些路由相关的属性: path/params/query/meta

二、编写路由的3步

  • 定义路由组件

  • 映射路由

  • 使用显示当前路由组件

三、 嵌套路由

children: [    {      path: '/home/news/:id/:title',      component: news    },    {      path: 'message',      component: message    }]

四、 向路由组件传递数据

params/query: 
将请求参数映射成props: props=true | props: route => ({id: route.params.id})变相props:

五、动态路由与路由别名

注册路由:     {        name: 'news'        path: '/home/news/:id/:title',        component: News    }跳转:     
router.push({name: 'news', params: {id: 1, title: 'abc'}})

六、缓存路由组件

路由组件对象默认的生命周期: 被切换时就会死亡, 切换回来时重新创建

七、 路由的编程式导航

this.$router.push(path): 相当于点击路由链接(可以返回到当前路由界面)this.$router.replace(path): 用新路由替换当前路由(不可以返回到当前路由界面)this.$router.back(): 请求(返回)上一个记录路由

八、 路由的2种模式比较, 解决history模式404问题

hash模式:    路径中带#: http://localhost:8080/#/home/news    发请求的路径: http://localhost:8080  项目根路径    响应: 返回的总是index页面  ==> path部分(/home/news)被解析为前台路由路径history模式:    路径中不带#: http://localhost:8080/home/news    发请求的路径: http://localhost:8080/home/news    响应: 404错误    希望: 如果没有对应的资源, 返回index页面, path部分(/home/news)被解析为前台路由路径    解决: 添加配置        devServer: historyApiFallback: true, // 任意的 404 响应都被替代为 index.html        output: publicPath: '/', // 引入打包的文件时路径以/开头

Vue 源码分析

一、debug调试

  1. 调试的目的

    查找bug: 不断缩小可疑代码的范围

    查看程序的运行流程(用于熟悉新接手项目的代码)

  2. 如何开启调试模式

    添加debugger语句: 程序运行前 此方式用打包后才运行的项目

    添加(打)断点: 程序运行前或者过程中 此方式用运行源码js

  3. 如何进行调试操作

    resume: 恢复程序执行(可能执行完或者进入下一个断点处)

    step over: 单步跳转, 尝试执行完当前语句, 进入下一条(如果内部有断点, 自动进入内部断点处)
    step into: 跳入, 进入当前调用函数内部
    step out: 跳出, 一次性执行完当前函数后面所有语句,并出去
    deactivate breakpoints: 使所有断点暂时失效

    call stack: 显示是程序函数调用的过程

    scope: 当前执行环境对应的作用域中包含的变量数据

    breakpoints: 断点列表

二、准备

  1. [].slice.call(lis): 将伪数组转换为真数组
  2. node.nodeType: 得到节点类型
  3. Object.defineProperty(obj, propertyName, {}): 给对象添加/修改属性(指定描述符)
    1. configurable: true/false 是否可以重新define
    2. enumerable: true/false 是否可以枚举(for…in / keys())
    3. value: 指定初始值
    4. writable: true/false value是否可以修改存取(访问)描述符
    5. get: 函数, 用来得到当前属性值
    6. set: 函数, 用来监视当前属性值的变化
  4. Object.keys(obj): 得到对象自身可枚举的属性名的数组
  5. DocumentFragment: 文档碎片(高效批量更新多个节点)
  6. obj.hasOwnProperty(prop): 判断prop是否是obj自身的属性

三、数据代理(MVVM.js)

  1. 通过一个对象代理对另一个对象中属性的操作(读/写)

  2. 通过vm对象来代理data对象中所有属性的操作

  3. 好处: 更方便的操作data中的数据

  4. 基本实现流程

    1. 通过Object.defineProperty()给vm添加与data对象的属性对应的属性描述符
    2. 所有添加的属性都包含getter/setter
    3. 在getter/setter内部去操作data中对应的属性数据

四、模板解析(compile.js)

1.模板解析的关键对象: compile对象

2.模板解析的基本流程:

  • 将el的所有子节点取出, 添加到一个新建的文档fragment对象中
  • 对fragment中的所有层次子节点递归进行编译解析处理
    • 对插值文本节点进行解析
    • 对元素节点的指令属性进行解析
    • 事件指令解析
    • 一般指令解析
  • 将解析后的fragment添加到el中显示

3.解析插值语法节点: textNode.textContent = value

  • 根据正则对象得到匹配出的表达式字符串: 子匹配/RegExp.$1
  • 从data中取出表达式对应的属性值
  • 将属性值设置为 文本节点的textConten

4.事件指令解析: elementNode.addEventListener(‘eventName’, callback.bind(vm))

  • 从指令名中取出事件名
  • 根据指令属性值(表达式)从methods中得到对应的事件处理函数对象
  • 给当前元素节点绑定指定事件名和回调函数的dom事件监听
  • 指令解析完后, 移除此指令属性

5.一般指令解析: elementNode.xxx = value

  • 得到指令名和指令值(表达式)
  • 从data中根据表达式得到对应的值
  • 根据指令名确定需要操作元素节点的什么属性
    • v-text—textContent属性
    • v-html—innerHTML属性
    • v-class–className属性

五、数据劫持–>数据绑定

  1. 数据绑定(model==>View)

    一旦更新了data中的某个属性数据, 所有界面上直接使用或间接使用了此属性的节点都会更新(更新)

  2. 数据劫持

    • 数据劫持是vue中用来实现数据绑定的一种技术
    • 基本思想: 通过defineProperty()来监视data中所有属性(任意层次)数据的变化, 一旦变化就去更新界面
  3. 四个重要对象

Observer

  • 用来对data所有属性数据进行劫持的构造函数

    • 给data中所有属性重新定义属性描述(get/set)
      • 为data中的每个属性创建对应的dep对象

Dep(Depend)

  • data中的每个属性(所有层次)都对应一个dep对象

    • 创建的时机:

      • 在初始化define data中各个属性时创建对应的dep对象

        在data中的某个属性值被设置为新的对象时对象的结构{	id, // 每个dep都有一个唯一的id	subs //包含n个对应watcher的数组(subscribes的简写)}
    • subs属性说明

      当一个watcher被创建时, 内部会将当前watcher对象添加到对应的dep对象的subs中

      当此data属性的值发生改变时, 所有subs中的watcher都会收到更新的通知, 从而最终更新对应的界面

Compile

  • 用来解析模板页面的对象的构造函数(一个实例)
  • 利用compile对象解析模板页面
  • 每解析一个表达式(非事件指令)都会创建一个对应的watcher对象, 并建立watcher与dep的关系
  • complie与watcher关系: 一对多的关系

Watcher

  • 模板中每个非事件指令或表达式都对应一个watcher对象
  • 监视当前表达式数据的变化
  • 创建的时机: 在初始化编译模板时
  • 对象的组成
{	vm,  //vm对象	exp, //对应指令的表达式	cb, //当表达式所对应的数据发生改变的回调函数	value, //表达式当前的值	depIds //表达式中各级属性所对应的dep对象的集合对象	//属性名为dep的id, 属性值为dep}

总结: dep与watcher的关系: 多对多

  • 一个data中的属性对应对应一个dep, 一个dep中可能包含多个watcher(模板中有几个表达式使用到了属性)
  • 模板中一个非事件表达式对应一个watcher, 一个watcher中可能包含多个dep(表达式中包含了几个data属性)
  • 数据绑定使用到2个核心技术
    • defineProperty()
      • 订阅者-发布者

双向数据绑定

  1. 双向数据绑定是建立在单向数据绑定(model==>View)的基础之上的
  2. 双向数据绑定的实现流程:
    • 在解析v-model指令时, 给当前元素添加input监听
    • 当input的value发生改变时, 将最新的值赋值给当前表达式所对应的data属性

Vue CLI

一、安装

npm install -g @vue/cli# ORyarn global add @vue/cli

二、vue的脚手架

  1. 脚手架V2: 相对老的项目
  2. 脚手架v3: 新的项目
  3. 脚手架v4: 最新的(当前用得还少)

三、使用vue的脚手架

脚手架v3

npm install -g @vue/cli# 创建一个项目vue create vue-app3

脚手架v2

Vue CLI >= 3 和旧版使用了相同的 vue 命令,所以 Vue CLI 2 (vue-cli) 被覆盖了。如果你仍然需要使用旧版本的 vue init 功能,你可以全局安装一个桥接工具:

npm install -g @vue/cli-init# `vue init` 的运行效果将会跟 `vue-cli@2.x` 相同vue init webpack my-project

四、比较V2与V3创建的项目

  1. v2的配置是直接可见, v3是包装隐藏起来了

  2. 修改配置: v2是直接在配置文件中修改, v3提供了一个专门的配置: vue.config.js, 我们可以根据文档在此文件中添加配置

    depIds //表达式中各级属性所对应的dep对象的集合对象

    //属性名为dep的id, 属性值为dep
    }

>总结: dep与watcher的关系: 多对多* 一个data中的属性对应对应一个dep, 一个dep中可能包含多个watcher(模板中有几个表达式使用到了属性)* 模板中一个非事件表达式对应一个watcher, 一个watcher中可能包含多个dep(表达式中包含了几个data属性)* 数据绑定使用到2个核心技术  * **defineProperty()**    * 订阅者-发布者>**双向数据绑定**1. 双向数据绑定是建立在单向数据绑定(model==>View)的基础之上的2. 双向数据绑定的实现流程:   * 在解析v-model指令时, 给当前元素添加input监听   * 当input的value发生改变时, 将最新的值赋值给当前表达式所对应的data属性# Vue CLI## 一、安装~~~shellnpm install -g @vue/cli# ORyarn global add @vue/cli

二、vue的脚手架

  1. 脚手架V2: 相对老的项目
  2. 脚手架v3: 新的项目
  3. 脚手架v4: 最新的(当前用得还少)

三、使用vue的脚手架

脚手架v3

npm install -g @vue/cli# 创建一个项目vue create vue-app3

脚手架v2

Vue CLI >= 3 和旧版使用了相同的 vue 命令,所以 Vue CLI 2 (vue-cli) 被覆盖了。如果你仍然需要使用旧版本的 vue init 功能,你可以全局安装一个桥接工具:

npm install -g @vue/cli-init# `vue init` 的运行效果将会跟 `vue-cli@2.x` 相同vue init webpack my-project

四、比较V2与V3创建的项目

  1. v2的配置是直接可见, v3是包装隐藏起来了
  2. 修改配置: v2是直接在配置文件中修改, v3提供了一个专门的配置: vue.config.js, 我们可以根据文档在此文件中添加配置
  3. vue使用的是不带编译器的版本, 打包文件更小 不写template配置, 直接render配置

转载地址:http://vabki.baihongyu.com/

你可能感兴趣的文章
系统处理 IRQ_EINT0 IRQ_EIN…
查看>>
系统处理 IRQ_EINT0 IRQ_EIN…
查看>>
misc_register和register_ch…
查看>>
misc_register和register_ch…
查看>>
misc_register和register_ch…
查看>>
misc_register和register_ch…
查看>>
platform设备添加流程(转载)
查看>>
platform设备添加流程(转载)
查看>>
GCC编译关键字“__attribute_…
查看>>
GCC编译关键字“__attribute_…
查看>>
Linux对I/O端口资源的管理( …
查看>>
Linux对I/O端口资源的管理( …
查看>>
[转载]Linux内核中的platfor…
查看>>
[转载]Linux内核中的platfor…
查看>>
IO端口和IO内存 (转载)
查看>>
IO端口和IO内存 (转载)
查看>>
Linux内核驱动模块
查看>>
Linux内核驱动模块
查看>>
linux中同步例子(完成量completion…
查看>>
linux中同步例子(完成量completion…
查看>>