Vue 的开发形式有多种,有 script
标签引入的形式,也有脚手架启动 web
服务的形式。
一般我们都是采用脚手架的形式学习,如下所示:(已安装可忽略)
下载完之后,通过如下指令查看安装的版本:
vue --version
通过此脚手架初始化一个 Vue 项目:
vue create demo1
按照步骤都选择 Yes 或者默认的便可,新建项目需要一些时间。
通过如下命令启动 demo1 项目:
cd demo1
npm run serve
待项目启动之后,点击右侧边栏「Web 服务」,打开浏览器如下所示,说明开发环境配置成功了:
清空 App.vue 文件里的代码,我们开始学习 Vue 指令。
都能展示数据,且属于单向绑定。即数据的变化会影响插值的变化,而插值的变化,不会影响数据的变化。其实 v-text 也可以简写为 {{ }} 。
v-text:只能渲染纯文本,浏览器不会对其进行 html 解析。
v-html:用于输出 html,浏览器会解析 html。
下面通过代码实例来验证,打开 App.vue 代码如下:
{{ text }}
{{ html }}
0
通过变量控制标签内容的显示或隐藏。
v-if 在浏览器上表现为整个 DOM 节点不会被渲染;
v-show 的呈现形式相当于给 DOM 节点添加了一个 CSS 属性 — display: none ;
v-else 则类似 JS 语法的 if else 判断语句,需要紧跟在 v-if 后面。
下面通过代码实例来验证,App.vue 代码如下:
我是coder one
我是coder two
我是code one
我是coder two
我是消失的coder
打开浏览器,展示效果
v-for 指令解决的是模板循环渲染问题,没有 Vue、React 等框架之前都是通过 for 循环拼接字符串的形式,通过 append 将拼接好的节点塞入指定的 DOM 节点。现在有了 v-for 指令,就不用这么麻烦了,得到数组之后,只需以 (item, index) in array 的形式渲染数据。
下面是代码演示:
{{ index }}{{ item }}
浏览器展示效果如下:
index 数组对象所对应的索引值,渲染模版的时候如果需要做一些逻辑运算的时候,会用到这个索引值,比如只让索引值为偶数的项进行渲染,就可以结合之前的 v-if、v-show 指令去实现需求。
小知识 1:v-for 和 v-if 不要一起使用
v-for 的优先级高于 v-if ,当它们处于同一节点,v-for 的优先级比 v-if 更高,这意味着 v-if 将分别重复运行于每个 v-for 循环。比较好的解决方式是,先通过 computed 属性将需要渲染的列表提前过滤,再将过滤后的列表放到模板中渲染,这样做的目的是让页面渲染效率更高,避免不必要的资源浪费。
小知识 2: v-for 可以渲染 Object 类型数据
比如上述例子我们可以改成如下:
{{ index }}{{ val.name }}
v-on 就是监听事件,可以用 v-on 指令监听 DOM 事件来触发一些方法函数。
v-on 有一种简写形式,用 @ 符号代替。它还能监听一些键盘事件,如键盘的回车键 v-on:keyup.enter 等,大家可以类推其他的键盘事件。
下面就来看看代码示例:
数字:{{ count }}
效果如下:
在 Vue 的众多指令里,v-model
算是举足轻重的,因为它的双向绑定特性,能解决很多业务上的复杂需求,下面就用几个小示例来诠释它的强大,代码演示如下:
1、最简单的双向绑定
用户名:{{ username }}
2、结合复选框
checkbox
{{ fruit }}
结合复选框实现切换复选框内的值,动态地改变数据
3、结合单选框
radio
{{ sex }}
4、几个需要注意的修饰符
v-bind
对变量属性的一个绑定,比如说需要绑定一个图片只需如下:
// 可简写为
绑定 CSS 样式,一般用在需要计算表达式的时候使用:
绑定class
// 判断变量
绑定class中的判断
// 三元运算符
绑定class中的三元表达式判断
// 绑定 style
绑定style
v-cloak
作用:在使用双大括号赋值时,页面数据没有返回之前,页面会闪烁一下 '“{{}}”'双大括号,只需在全局样式下添加如下:
[v-cloak] {
display: none;
}
在绑定的变量节点上加上 :
{{msg}}
试想用户打开网页,闪过一片 {{parmas}}
,不起眼的小指令,却极大的优化了网页的用户体验。
v-pre
直接跳过 Vue 的编译,输出原始值。在标签中如下使用:
{{message}}
最终在网页上输出的结果是 {{message}}
。
v-once
只在第一次渲染时执行,之后的操作都被视为静态内容,跳出之后的所有渲染过程。
用户名:{{ username }}
举个比较好理解的例子,Vue 就好比一块蛋糕,生命周期钩子函数以及内部指令可以理解为做蛋糕用的面粉、糖、鸡蛋等。而全局 API 就是裹在蛋糕外面的奶油,让整个蛋糕(Vue)看起来更加美味。全局 API 的作用就是给 Vue 更多的自由,大家可以根具自己项目的需求,通过全局 API 来制作出各种各样的方法工具。
之前也学了 v-model、v-show 等官方定义的指令,在项目的开发过程中,我们会有一些特殊的需求,要自定义指令,Vue.directive 就是为什么做这件事情的 API。
假如来了一个需求,需要让加上 v-color 指令的标签的字体颜色通过传入的变量值进行改变,比如 v-color=“red” 标签就会变为红色。
代码演示如下,进入 App.vue:
嘻嘻哈哈
在 main.js 下添加如下代码:
import Vue from 'vue';
import App from './App.vue';
Vue.config.productionTip = false;
Vue.directive('color', function (el, binding, vnode) {
console.log('el', el); // 被绑定的node节点
console.log('binding', binding); // 一个对象,包含指令的很多信息
console.log('vnode', vnode); // Vue编译生成的虚拟节点
el.style = 'color:' + binding.value;
});
new Vue({
render: (h) => h(App),
}).$mount('#app');
浏览器效果如下所示:
自定义组件的回调函数有三个参数。
自定义组件包含几个生命周期,也就是在调用自定义组件时,几个钩子函数会被触发,分别是如下。
在解释 Vue.set 之前先了解一下 Vue 的响应式原理:
当你把一个 JS 对象传给 Vue 实例的 data 属性时,Vue 将遍历此对象的所有属性,并使用 Object.defineProperty 把这些属性全部转为 getter/setter。Object.defineProperty 是 ES5 中一个无法 shim 的特性,这也就是为什么 Vue 不支持 IE8 以及更低版本的浏览器。
受限于现代浏览器,Vue 检测不到对象的添加和删除;因为 Vue 在初始化实例时对 data 属性执行 getter/setter 转化操作,所以对象必须在 data 中才能让其响应式。
Vue 不允许在已经创建的实例上动态添加新的根级响应式属性,不过可以使用 Vue.set 方法将响应式属性添加到嵌套的对象上。代码演示如下:
{{ item }}
{{ fruit }}
浏览器效果如下所示:
当点击按钮“变”的时候,渲染没有变化,当点击按钮“外部添加”的时候,渲染数据发生了变化。
全局过滤器是一个在项目中时常会用到的 API,使用场景也非常丰富,比如说数据的统计,保留小数点参数等等,在后续的商场实战中也会被运用到实战中。
下面我们演示一个简单的过滤器,需求是使用过滤器将需要过滤的目标值加上 4,代码演示如下:
App.vue
{{ count | sum }}
main.js
import Vue from 'vue';
import App from './App.vue';
Vue.config.productionTip = false;
Vue.filter('sum', function (value) {
return value + 4;
});
new Vue({
render: (h) => h(App),
}).$mount('#app');
浏览器预览:
屏幕上会出现 24 这个数字,注意的是,声明 sum 过滤器,必须要放在声明实例 app 之前,否则不会被注入到实例中。
nextTick 是一个比较重要的高级特性,应用场景在很多地方会出现。Vue 是异步渲染的框架,一开始就是如此,当你改变 data 属性内部的变量,视图不会立即更新,在此时你若是进行 DOM 操作,是拿不到最新的渲染结果,这个时候你就要借助 Vue.nextTick 高级特性,在该特性的回调函数内获取最新的渲染结果。
this.$nextTick(function () {
// 写在需要在某个操作改变 dom 结构之后
});
混入(mixin)提供了一个非常灵活的方式,来分发 Vue 组件中的可复用功能。一个混入对象可以包括任意组件选项。当组件使用混入对象时,所有混入对象的选项将被「混合」进入该组件本身的选项。
上面这段摘录自 Vue 的官方文档,文字有点难理解,笔者通过举实例来解释 mixin 的具体用法。 其实我们可以用 Object 的思想去理解 mixin,假设有一个变量 A,它的值为 { a: 1, b: 2 },有另一个变量 B,它的值为 { a: 3, c: 4 },B 作为混入的对象混入 A,那么 A 中已有的属性 a 不会被覆盖,A 会新增一个 c 属性,最终 A 为 { a: 1, b: 2, c: 4 }。
通过 Vue 的代码进行分析如下:
// mixin.js
export default {
data() {
return {
username: '张三',
age: 30,
hasWife: true,
};
},
mounted() {
console.log('mixin');
},
methods: {
speak() {
console.log('这是mixin');
},
cry() {
console.log('这是cry');
},
},
};
// App.vue
import mixin from './mixin';
export default {
data() {
return {
username: '李四',
age: 31,
hasHusband: true,
};
},
mounted() {
console.log('app');
},
mixins: [mixin],
methods: {
speak() {
console.log('这是app');
},
eat() {
console.log('吃饭');
},
},
};
// 最终得到的结果如下
export default {
data() {
return {
name: '李四', // name为共有属性,最终保留 app.vue 的
age: 31, // 同上
hasHusband: true, // app.vue 独有属性,保留
hasWife: true, // app.vue 没有的属性,会被添加进来
};
},
mounted() {
// 在钩子函数中的,会被合并到 app.vue 的钩子函数中,minix中的代码会在前面
console.log('mixin');
console.log('app');
},
methods: {
// 两边都有的方法,会被封装为一个数组,先执行 minix 中的,后执行 app 自己的
speak() {
[
function () {
console.log('这是mixin');
},
function () {
console.log('这是app');
},
].forEach((cb) => {
cb();
});
},
// 自身独有的,保留
eat() {
console.log('吃饭');
},
// 自身没有的方法,会被添加进来
cry() {
console.log('这是cry');
},
},
};
上述为组件中使用 mixins 方法进行「混入」,下面我们来介绍「全局混入」,「混入」可以在入口页进行全局注册,但是使用它时要格外小心,一旦使用全局混入,它将会影响每一个之后创建的 Vue 实例。 官方示例如下:
// 为自定义的选项 'myOption' 注入一个处理器。
Vue.mixin({
created: function () {
var myOption = this.$options.myOption;
if (myOption) {
console.log(myOption);
}
},
});
new Vue({
myOption: 'hello!',
});
// => "hello!"
单页面开发模式,每个页面都可以理解为一个 Vue 组件,每个页面都是一个鲜活的生命,在它的一生中,从出生到消亡都会有对应的钩子函数,下面就让我们认识一下它们。
Vue 生命周期代码演示如下:
{{ count }}