《Vue.js实战》记录

目录

初识Vue.js

指令

v-html

v-pre

v-bind

v-on

v-cloak

v-once

v-show

v-for

v-model

自定义指令

全局指令

局部指令

钩子函数

计算属性

computed

表单与v-model

单选按钮

复选框

选择列表(下拉框)

组件

全局组件

局部组件

组件数据与方法

使用props传递数据

组件通信

使用slot分发内容

其他

使用Webpack 2

Vue工程配置

完善工程配置

Render函数

JSX

插件

前端路由

状态管理与Vuex


 

代码例子参考:

https://gitee.com/feistel/Blog/tree/master/%E5%89%8D%E7%AB%AF/forTest/src

webpack工程例子参考:

https://gitee.com/feistel/Blog/tree/master/%E5%89%8D%E7%AB%AF/demo

初识Vue.js

它提供了现代Web开发中的常见高级功能:

  • 解耦视图与数据
  • 可复用的组件
  • 前端路由
  • 状态管理
  • 虚拟DOM

指令

v-html

插入Html

v-pre

被修饰的元素其内部的字符不会被编译转换

v-bind

> :

动态更新HTML元素或组件元素的属性,如id,class,href,src等

v-bind绑定class的方式:

  1. 对象语法

    <div :class="{'active': isActive}"></div>
    

    当isActive为true时,渲染为<div class="active"></div>

  2. 数组语法

    <div> :class="[activeCls, errorCls]"</div>
    
    date: {
    	activeCls: 'active',
    	errorCls: 'error'
    }
    

    渲染后为<div class="active error"></div>

内联样式style与class用法一样。

v-on

> @

监听原生的DOM事件

事件修饰符(可以串联),如
.stop,阻止单击事件冒泡?
@submi.prevent,提交事件不重载页面
.capture
.self
@click.once,只触发一次
@click.native,表示修饰的是一个原生事件

对于@keyCode,包括但不限于:
.enter
.tab
.esc
.up
.down
.left
.right

v-cloak

它会在Vue实例结束编译时从绑定的html元素上移除,常和display:none配合使用 主要解决当vue.js还没加载时,会在页面上显示{{ xxx }}的字样,一闪而过,等Vue创建实例时才会被替换,可以连续点F5查看到。

<style type="text/css">
        [v-cloak] {
            display: none;
        }
</style>
<div id="app" v-cloak>
</div>

v-once

首次渲染后,不再随数据的变化重新渲染,被视为静态内容,到需要优化时用到。 v-if、v-else-if、v-else 条件渲染

v-show

为true时展示。改变元素的css属性display。 与v-if相比,适合于频繁切换条件的场景使用。

v-for

被修饰的元素,将被循环渲染。用法如:

    <ul>
        <li v-for="book in books">{{ book.name }}</li>
    </ul>

v-model

@input

当使用中文输入法,还没进行选词时不会实时绑定数据。可以用@input来实现,如下

<input type="text" @input="handleInput" placeholder="实时输入。。。">
<h1>还没选词也会显示:{{ message }}</h1>

methods: {
	handleInput: function (e) {
	this.message = e.target.value;
	}
}

与事件v-on(@)类似,v-model(:)也有修饰符,用于控制数据同步的时机。

.lazy

<input type="text" v-model.lazy="namee" placeholder="你的名字">

并不是实时改变,而是在失去焦点或回车时才更新

.number

将输入转换为Number类型

.trim

自动过滤输入的首尾空格

自定义指令

全局指令

Vue.directive('focus', {
	// 指令选项
})

局部指令

var app = new Vue({
	el: '#app',
	directives: {
		focus: {
			// 指令选项
		}
	}
})

渲染页面是,input将获得焦点。

<input type="text" v-focus>

Vue.directive('focus', {
	inserted: function (el) {
		el.focus();
	}
});

钩子函数

  • bind,第一次绑定到元素是调用
  • inserted,被绑定元素插入父节点时调用,例如:页面渲染时
  • update,被绑定元素所在的末班更新时调用
  • componentUpdated,被绑定元素所在模板完成一次更新 周期时调用
  • unbind,指令与元素解绑时调用

钩子函数的参数

  • el,指令所绑定的元素,可以用来直接操作DOM
  • binding,包括如下属性
    • name,指令名,不包括v-前缀,如v-focus,name为focus
    • value,指令绑定的值,如v-focus="1+1",value为2
    • oldValue,指令的前一个值
    • expression,绑定值得字符串形式,如v-focus="1+1",expression为"1+1"
    • arg,传给指令的参数,如v-focus:foo,arg为foo
    • modifiers,一个包含修饰符的对象,如v-focus.foo.bar,modifiers为{foo: true, bar: ture}
  • vnode,Vue编译生成的虚拟节点
  • oldVnode,上一个虚拟节点

计算属性

computed

只能被当做属性来用,不能加'()',即不能送参数。

computed与methods的区别是:

  1. 不能接受参数

  2. 使用时当做属性,而不是方法,不能加'()'

  3. 计算属性基于依赖缓存,例如, 计算Date.now(),不会刷新,而在methods会。

     <div> {{ now }}</div>
     <div> {{ nowDate() }}</div>
    
         // 计算属性
         computed: {
             now: function () {
                 return Date.now();
             }
         },
         methods: {
             nowDate: function () {
                 return Date.now();
             }
         },
    

表单与v-model

单选按钮

<br>
<input type="radio" v-model="picked" value="html" id="id_html">
<label for="html">HTML</label>
<br>
<input type="radio" v-model="picked" value="js" id="id_js">
<label for="js">javaScript</label>
<p>选择的项是: {{ picked }} </p>

picked: "js"

复选框

  • 单个使用时,用v-model来绑定一个布尔值

  • 组合使用时,绑定到同一个数组类型

    <br>
    <input type="checkbox" v-model="checked" value="html" id="id_html">
    <label for="html">HTML</label>
    <br>
    <input type="checkbox" v-model="checked" value="js" id="id_js">
    <label for="js">javaScript</label>
    <p>选择的项是: {{ checked }} </p>
    
    checked: []
    

选择列表(下拉框)

<select v-model="selected" multiple>
	<option></option>
	<option value="js">javaScript</option>
	<option value="css">css</option>
</select>
<p>选择的项是: {{ selected }} </p>

selected: []

组件

全局组件

Vue.component('my-component', {
	template: '<div>组件内容</div>'
})

局部组件

var Child = {
	template: '<div>组件内容</div>'
}

var app = new Vue({
	el: '#app',
	component: {
		'my-component': Child
	}
})

组件数据与方法

在使用data时,和Vue实例有区别,data必须是函数,然后将数据return出去。

Vue.component('my-component', {
	template: '<div>{{ message }}</div>',
	data: function () {
		return {
			message: '组件内容'
		}
	}
});

使用props传递数据

父组件中包含子组件,父组件哟啊正向传递数据或参数,这个正向传递过程就是通过props实现的。

> Vue 2.x与Vue 1.x的改变就是props传递数据是单向的了,只能正向传递给子组件。尽可能将父子组件解耦。 > > Vue 1.x提供了.sync修饰符来支持双向绑定。

组件中,props选项声明需要从父级接受的数据,props可以是:

  1. 数组

    <!-- html不区分大小写,这里必须要用中横杆分隔命名 -->
    <!-- 传递进来的通常不是写死的,而是来自父级的动态数据,使用v-bind来动态绑定。 -->
    <input type="text" v-model="parentMessage">
    <my-component :props-message="parenMessage"></my-component>
    
    Vue.component('my-component', {
    	// 必须使用驼峰命名
    	props: ['propsMessage'],
    	template: '<div>{{ propsMessage }}--{{ message }}</div>',
    	data: function () {
    		return {
    			message: '组件内容'
    		}
    	}
    });
    
  2. 对象

    当prop需要验证时,就需要对象写法。

    props: {
    	propsMessage: {
    		type: Boolean,
    		default: true
    	}
    }
    

    type类型可以是:

    String

    Number

    Boolean

    Object

    Array

    Function

组件通信

自定义事件

在组件里使用this.$emit('increase', this.counter);触发事件

在使用组件处使用<my-component @increase="handleIncrease"></my-component>接受事件并在handleIncrease处理。

其中,this.counter表示从组件里传出的数据,将作为handleIncrease的入参,实现形如:

function handleIncrease (counter) {} 

> 语法糖: > > 在组件里使用this.$emit('input', this.counter);触发事件 > > 在使用组件处使用<my-component v-model="currentCounter"></my-component> > > 即可到达将子类数据,反向绑定到父组件的currentCounter中。

非父子组件通信

Vue.js 1.x

提供了$.dispatch()和$broadcast(),在Vue.js 2.x被废弃

组件内使用this.$dispatch('on-message', '内部组件的数据');发送事件

Vue.js 2.x

1.使用中央事件总线(bus)

> 当项目比较大,可以选择更好的状态管理解决方案vuex

var bus = new Vue();

Vue.component('my-component', {
	template: '<button @click="handleEvent">传递事件</button>',
	methods: {
        handleEvent: function () {
            bus.$emit('on-message', '来自my-component组件的数据');
        }
    }
});

var app = new Vue({
    el: '#app',
    data: {
        message: ''
    },
    mounted: function () {
        var _this = this;
        bus.$on('on-message', function (msg) {
            _this.message = msg;
        });
    }
});

2.父链

在子组件里直接使用this.$parent.message,message表示父级以上的变量。

或者在父组件使用,this.$children.message

> 父链使得父子组件紧耦合,最好还是通过props和$emit来通信。

3.子组件索引

使用组件时加上ref属性

<my-component ref="comA"></my-component>

使用this.$refs.comA.message获取组件内部数据,message表示组件的内部变量。

使用slot分发内容

> slot分发的内容,作用域时在父组件上的。 > > 人话:slot分发的内容中,内容是指,组件里的内容,比如,<my-component><p>内容</p></my-component>,其中'<p>内容</p>'就表示要分发的内容;分发是指内容将会被插入到子组件里。而编译的这个内容的作用域是父组件的,而不属于子组件。

其他

$nextTick

methods: {
	getText: function () {
		this.$nextTick (function () {
			var text = document.getElementById('div').innerHTML;
			console.log(text);
		});
	}
}

> 由于Vue异步更新DOM原理。Vue在观察到数据变化是并不是直接更新DOM,而是开启一个队列,并缓冲在同一事件循环中,在下一个事件循环tick中,Vue刷新队列并执行实际的工作。

$nextTick表示在下一个事件循环中执行。

手动挂载组件

new MyComponent().$mount('#mount-div');

使用Webpack 2

> 单页富应用(SPA),就是只有一张Web页面的应用。单页应用程序 (SPA) 是加载单个HTML 页面并在用户与应用程序交互时动态更新该页面的Web应用程序。 > > 百度百科https://baike.baidu.com/item/SPA/17536313?fr=aladdin

Vue工程配置

新建目录demo目录

npm init将生成一个package.json文件

npm init

局部安装webpack

npm install webpack --save-dev
使用命令 --save 或者说不写命令 --save  ,都会把信息记录到 dependencies   中
dependencies 中记录的都是项目在运行时需要的文件
使用命令 --save-dev 则会把信息记录到devDependencies 中
devDependencies 中记录的是项目在开发过程中需要使用的一些文件,而在项目最终发布时是不需要的

> --save 和 --save-dev 的作用和区别简单描述: > > https://blog.youkuaiyun.com/cvper/article/details/88728505

局部安装webpack-dev-server,它提供很多服务,如启动一个服务器,热更新,接口代理。

npm install webpack-dev-server --save-dev

安装

npm install webpack-cli

package.json文件内容:

{
  "name": "demo",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" &amp;&amp; exit 1"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "webpack": "^4.43.0",
    "webpack-dev-server": "^3.11.0"
  },
  "dependencies": {
    "webpack-cli": "^3.3.11"
  }
}

webpack就是一个.js配置文件。

新建空的main.js文件,作为入口文件。

新建文件webpack.config.js,如下

var path = require('path');

var config = {
	entry: {
		main: './main'
	},
	output: {
		// 指定打包后文件的输出目录
		path: path.join(__dirname, './dist'),
		// 指定资源文件引用的目录
		publicPath: '/dist/',
		// 指定输出文件的名称
		filename: 'main.js'
	}
};

module.exports = config;

新建index.html作为SPA的入口





    <meta charset="utf-8">
    <title>webpack App</title>



	<div id="app">
		Hello World.
	</div>
	<script type="text/javascript" src="/dist/main.js"></script>



配置package.json,当运行npm run dev时,将执行该命令。默认地址是127.0.0.1:8080。

  "scripts": {
    "test": "echo \"Error: no test specified\" &amp;&amp; exit 1",
	"dev": "webpack-dev-server --open --config webpack.config.js"
  },

使用命令启动

npm run dev

在main.js文件中,增加,保存,浏览器会实时显示改变内容,这就是webpack-dev-server的热更新功能。

document.getElementById('app').innerHTML = 'Hello webpack';

完善工程配置

在webpack里不同的模块需要不同的加载器(Loaders)来处理。

npm install css-loader --save-dev
npm install style-loader --save-dev

具体参考demo文件夹:

https://gitee.com/feistel/Blog/tree/master/%E5%89%8D%E7%AB%AF/demo

Render函数

用法参考:

https://gitee.com/feistel/Blog/blob/master/%E5%89%8D%E7%AB%AF/%5B%E8%BD%AC%E8%BD%BD%5Drender%E5%87%BD%E6%95%B0%E8%AF%A6%E8%A7%A3.md

JSX

简化render函数createElement盖楼一样的嵌套,Vue.js提供了插件babel-plugin-transform-vue-jsx来支持JSX语法,需要在webpack中配置编译器。

插件

前端路由

SPA的核心就是前端路由

SPA只有一个html,整个网站的内容都在这个html里,通过JavaScript来处理。

前端路由维护一个路由规则,使得url看起来像普通网站那样,以'/'分隔。

vue-router实现原理,路由不同的页面事实上就是动态加载不同的组件。

路由工程例子参考:

https://gitee.com/feistel/Blog/tree/master/%E5%89%8D%E7%AB%AF/demo

状态管理与Vuex

Vuex,管理和维护整个项目组件的状态。

与bus(中央事件总线)类似,用户触发和接收事件,进一步起到通讯的作用。

import Vuex from 'vuex';
Vue.use(Vuex);

const store = new Vuex.Store({
    state: {
        count: 0,
        list: [1, 5, 8, 10, 30, 50]
    },
    getters: {
        filteredList: state => {
            return state.list.filter(item => item < 10);
        },
        listCount: (state, getters) => {
            return getters.filteredList.length;
        }
    },
    mutations: {
        increment (state, n = 1) {
            state.count += n;
        },
        decrease (state) {
            state.count --;
        }
    },
    actions: {
        increment (context) {
            context.commit('increment');
        },
        asyncIncrement (context) {
            return new Promise(resolve => {
                setTimeout(() => {
                    context.commit('increment');
                    resolve();
                }, 1000)
            });
        }
    }
});

new Vue({
    el: '#app',
    router: router,
    store: store,
    render: h => {
        return h(App)
    }
});

使用:

<script>
    export default {
        computed: {
            count () {
                return this.$store.state.count;
            },
            list () {
                return this.$store.getters.filteredList;
            },
            listCount () {
                return this.$store.getters.listCount;
            }
        },
        methods: {
            handleIncrement () {
                this.$store.commit('increment');
            },
            handleDecrease () {
                this.$store.commit('decrease');
            },
            handleIncrementMore () {
                this.$store.commit('increment', 5);
            },
            handleActionIncrement () {
                this.$store.dispatch('increment')
            },
            handleAsyncIncrement () {
                this.$store.dispatch('asyncIncrement').then(() => {
                    console.log(this.$store.state.count);
                });
            }
        }
    }
</script>

《Vue.js实战》 梁灏

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值