目录
- 常用内置指令
- v-text与v-html
- v-text : 更新元素的 textContent
- v-html : 更新元素的 innerHTML
- 注意:v-html有安全性问题!!!!
- v-once与v-pre
- v-once
- v-pre
- ref与v-cloak
- ref
- v-cloak
- 自定义指令
- 案例
- 定义语法
- 配置对象中常用的3个回调
- 备注
- 使用指令
- 代码解释
- 全局指令写法
- 回调函数(钩子函数)
- Vue生命周期
- VUE组件化编程
- 模块:
- 组件:
- 总结
- 非单文件组件
- 创建组件:
- 注册组件:
- 使用组件(写组件标签)
- 代码示例
- 注意事项
- 关于组件名:
- 一个单词组成:
- 多个单词组成:
- 备注:
- 关于组件标签:
- 组件嵌套
- 非单文件组件小结
- 单文件组件
- 模板页:
- JS 模块对象:
- 样式:
- 问题
- 解决
常用内置指令
内置指令 | 说明 |
---|---|
v-text | 更新元素的 textContent |
v-html | 更新元素的 innerHTML |
v-if | 如果为true, 当前标签才会输出到页面 |
v-else | 如果为false, 当前标签才会输出到页面 |
v-show | 通过控制display样式来控制显示/隐藏 |
v-for | 遍历数组/对象 |
v-on | 绑定事件监听, 一般简写为@ |
v-bind | 强制绑定解析表达式, 可以省略v-bind |
v-model | 双向数据绑定 |
v-text与v-html
v-text : 更新元素的 textContent
- 作用:向其所在的节点中渲染文本内容。
- 与插值语法的区别:v-text会替换掉节点中的内容,{{xx}}则不会。
v-html : 更新元素的 innerHTML
- 作用:向指定节点中渲染包含html结构的内容。
- 与插值语法的区别:
- v-html会替换掉节点中所有的内容,{{xx}}则不会。
- v-html可以识别html结构。
注意:v-html有安全性问题!!!!
- 在网站上动态渲染任意HTML是非常危险的,容易导致XSS攻击。
- 一定要在可信的内容上使用v-html,永不要用在用户提交的内容上!
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue初体验</title>
<!-- 1.引入Vue -->
<script src="../js/vue.js"></script>
</head>
<body>
<!-- 2.准备一个容器 -->
<div id="root">
<div>你好,{{name}}</div>
<div v-text="name">HELLO,</div>
<div v-text="ele"></div>
<div v-html="ele"></div>
</div>
<script>
//3.创建Vue实例
const vm = new Vue({
el:'#root',
data:{
name:'Vue',
ele: '<a href="https://www.baidu.com">百度</a>'
}
});
</script>
</body>
</html>
v-once与v-pre
v-once
- v-once所在节点在初次动态渲染后,就视为静态内容了。
- 以后数据的改变不会引起v-once所在结构的更新,可以用于优化性能。
v-pre
- 跳过其所在节点的编译过程。(vue 不去解析 插值等语法)
- 可利用它跳过:没有使用指令语法、没有使用插值语法的节点,会加快编译。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue初体验</title>
<!-- 1.引入Vue -->
<script src="../js/vue.js"></script>
</head>
<body>
<!-- 2.准备一个容器 -->
<div id="root">
<div v-once>v-once,{{n}}</div>
<div v-pre>v-pre,{{n}}</div>
<div>当前n的值是:{{n}}</div>
<button @click="n++">n+1</button>
</div>
<script>
//3.创建Vue实例
const vm = new Vue({
el:'#root',
data:{
n:1
},
});
</script>
</body>
</html>
ref与v-cloak
ref
- 为某个元素注册一个唯一标识, vue对象通过$refs属性访问这个元素对象。
v-cloak
- 使用它防止闪现表达式, 与css配合: [v-cloak] { display: none }
- 本质是一个特殊属性,Vue实例创建完毕并接管容器后,会删掉v-cloak属性。
- 使用css配合v-cloak可以解决网速慢时页面展示出{{xxx}}的问题。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue初体验</title>
<!-- 1.引入Vue -->
<script src="../js/vue.js"></script>
<style>
[v-cloak]{
display: none;
color: red;
border: 3px solid green
}
</style>
</head>
<body>
<!-- 2.准备一个容器 -->
<div id="root">
<p ref="content"><a href="">baidu.com</a></p>
<button @click="hint">点击</button>
<p v-cloak>{{msg}}</p>
<h2 v-cloak>{{name}}</h2>
</div>
<script>
//3.创建Vue实例
const vm = new Vue({
el:'#root',
data:{
msg:'消息',
name:'Vue'
},
methods:{
hint(){
console.log(this.$refs.content.innerHTML);
console.log(this.$refs.content.textContent);
}
}
});
</script>
</body>
</html>
自定义指令
案例
- 需求1:定义一个v-big指令,和v-text功能类似,但会把绑定的数值放大10倍。
- 需求2:定义一个v-fbind指令,和v-bind功能类似,但可以让其所绑定的input元素默认获取焦点。
定义语法
- 局部指令(new Vue({xx})):xx为directives:{指令名:配置对象}或directives{指令名:回调函数}
- 全局指令:Vue.directive(指令名,配置对象)或Vue.directive(指令名,回调函数)
配置对象中常用的3个回调
- bind:指令与元素成功绑定时调用。
- inserted:指令所在元素被插入页面时调用。
- update:指令所在模板结构被重新解析时调用。
备注
- 指令定义时不加v-,但使用时要加v-;
- 指令名如果是多个单词,要使用kebab-case命名方式,不要用camelCase命名。
使用指令
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue初体验</title>
<!-- 1.引入Vue -->
<script src="../js/vue.js"></script>
</head>
<body>
<!-- 2.准备一个容器 -->
<div id="root">
<h1>当前n的值是:<span v-text="n"></span></h1>
<h1>放大10倍后的n的值是:<span v-big="n"></span></h1>
<button @click="n++">点击n+1</button>
<hr>
<input type="text" v-fbind:value="n">
</div>
<script>
//3.创建Vue实例
const vm = new Vue({
el:'#root',
data:{
n:10,
},
directives:{
big(el,binding){
el.innerText = binding.value * 10;
},
fbind:{
bind(el,binding){
el.value = binding.value;
},
// 指令的定义
inserted(el,binding){
el.focus();
},
update(el,binding){
el.value = binding.value;
el.focus();
}
}
},
});
</script>
</body>
</html>
代码解释
directives:{
//指令名如果是多个单词,别忘了加"",方法内部放的是"key,value值",
//大部分情况""可省略,但是加了-之后引号必须带
//全写是'big-number':function(element,binding){}
//函数写法
//big函数何时会被调用?1.指令与元素成功绑定时(一上来就是),
//2.指令所在的模板被重新解析时
big(el,binding){//两个参数 当前DOM元素(span),本次绑定的所有信息
console.log('big',this)//注意这里的this是window
el.innerText = binding.value * 10;
},
//对象写法
fbind:{
//指令与元素成功绑定时调用
bind(el,binding){
el.value = binding.value;
},
// 指令在元素插入页面时调用
inserted(el,binding){
el.focus();//input输入框自动获取焦点,这句代码必须放在将input放入页面的后面
},
//指令所在的模板重新定义时调用
update(el,binding){
el.value = binding.value;
el.focus();
}
}
},
全局指令写法
Vue.directives('fbind',{
bind(el,binding){
el.value = binding.value;
},
// 指令的定义
inserted(el,binding){
el.focus();
},
update(el,binding){
el.value = binding.value;
el.focus();
}
})
Vue.directives('big',function (el,binding) {
el.innerText = binding.value * 10;
})
回调函数(钩子函数)
- el:指令所绑定的元素,可以用来直接操作 DOM
- binding:一个对象,包含以下 property:
name
:指令名,不包括 v- 前缀。value
:指令的绑定值,例如:v-my-directive=“1 + 1” 中,绑定值为 2。oldValue
:指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用。expression
:字符串形式的指令表达式。例如 v-my-directive=“1 + 1” 中,表达式为 “1 + 1”。arg
:传给指令的参数,可选。例如 v-my-directive:foo 中,参数为 “foo”。modifiers
:一个包含修饰符的对象。例如:v-my-directive.foo.bar 中,修饰符对象为 { foo: true, bar: true }vnode
:Vue 编译生成的虚拟节点oldVnode
:上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue初体验</title>
<!-- 1.引入Vue -->
<script src="../js/vue.js"></script>
</head>
<body>
<!-- 2.准备一个容器 -->
<div id="root" v-demo:foo.a.b="name"></div>
<hr>
<div id="root2" v-demo:foo.a.b.c="1+1"></div>
<script>
Vue.directive('demo',{
bind:function (el,binding,vnode) {
var s = JSON.stringify
el.innerHTML =
'name: ' + s(binding.name) + '<br>' +
'value: ' + s(binding.value) + '<br>' +
'expression: ' + s(binding.expression) + '<br>' +
'argument: ' + s(binding.arg) + '<br>' +
'modifiers: ' + s(binding.modifiers) + '<br>'
}
})
//3.创建Vue实例
const vm = new Vue({
el:'#root',
data:{
name:'Vue',
},
});
const vm2 = new Vue({
el:'#root2',
data:{
},
});
</script>
</body>
</html>
Vue生命周期
- 又名:生命周期回调函数、生命周期函数、生命周期钩子。
- 是什么:Vue在关键时刻帮我们调用的一些特殊名称的函数。
- 生命周期函数的名字不可更改,但函数的具体内容是程序员根据需求编写的。
- 生命周期函数中的this指向是vm 或 组件实例对象(vue内部做了处理)
初始化显示
beforeCreate()、created()、beforeMount()、mounted()
更新状态
beforeUpdate()、updated()
销毁 vue 实例: vm.$destory()
beforeDestory()、destoryed()
总结起来:
- 创建前阶段(beforeCreate): 实例刚在内存中被创建出来,此时还未进行数据初始化和事件的监听。
- 创建阶段(created): 实例已经在内存中创建完毕,完成了数据初始化,但尚未挂载到页面上。
- 挂载前阶段(beforeMount): 实例将要挂载到页面上,此时 render 函数首次被调用。
- 挂载阶段(mounted): 实例已经挂载到页面,此时页面上的 DOM 元素可以被访问。
- 更新前阶段(beforeUpdate): 当数据发生变化时,虚拟 DOM 将被重新渲染,但尚未更新到页面上。
- 更新阶段(updated): 数据已经更新到页面上,此时页面上的 DOM 元素也得到了更新。
- 销毁前阶段(beforeDestroy): 实例将要被销毁,此时可以进行一些清理工作,如取消定时器、解绑事件等。
- 销毁阶段(destroyed): 实例已经被销毁,所有的事件监听器都已经被移除,所有的子实例也都被销毁。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue初体验</title>
<!-- 1.引入Vue -->
<script src="../js/vue.js"></script>
</head>
<body>
<!-- 2.准备一个容器 -->
<div id="root">
<h1>{{name}}</h1>
<button @click="changeName">点击更换内容</button>
</div>
<script>
//3.创建Vue实例
const vm = new Vue({
el: '#root',
data: {
name: 'Hello Vue',
},
beforeCreate() {
console.log('beforeCreate: 实例创建前的钩子函数');
},
created() {
console.log('created: 实例创建完毕,数据初始化完成');
},
beforeMount() {
console.log('beforeMount: 实例将要挂载到页面上');
},
mounted() {
console.log('mounted: 实例已经挂载到页面上');
},
beforeUpdate() {
console.log('beforeUpdate: 数据将要更新,虚拟 DOM 重新渲染前');
},
updated() {
console.log('updated: 数据已经更新,页面上的 DOM 元素也已更新');
},
beforeDestroy() {
console.log('beforeDestroy: 实例将要被销毁');
},
destroyed() {
console.log('destroyed: 实例已经被销毁');
},
methods: {
changeName() {
this.name = 'Hello World!!!';
}
}
})
</script>
</body>
</html>
生命周期的应用场景
钩子 | 描述 |
---|---|
created 钩子 | 在这个阶段,可以进行数据初始化、异步请求、事件监听等操作。通常用于初始化组件所需的数据。 |
mounted 钩子 | 在组件挂载后执行,适合执行需要访问DOM元素的操作,如使用第三方库对页面进行操作。 |
beforeUpdate 钩子 | 在数据更新但尚未更新到页面上时执行,可以用于获取更新前的DOM状态,或执行一些更新前的准备工作。 |
updated 钩子 | 在数据更新且更新到页面上后执行,适合执行需要操作更新后的DOM的任务。 |
beforeDestroy 钩子 | 在组件销毁前执行,可以用于清理定时器、解绑事件等清理工作。 |
destroyed 钩子 | 在组件销毁后执行,适合执行一些需要在组件销毁后进行的清理工作。 |
VUE组件化编程
- 组件定义:实现应用中局部功能代码和资源的集合
模块:
- 理解:向外提供特定功能的js程序,一般就是一个js文件
- 为什么:js文件很多很复杂
- 作用:复用js,简化js的编写,提高js运行效率。
组件:
- 理解:用来实现局部(特定)功能效果的代码集合(html/css/js/image……)
- 为什么:一个界面的功能很复杂
- 作用:复用编码,简化项目编码,提高运行效率
总结
- 模块化:当应用中的js都以模块来编写的,那这个应用就是一个模块化的应用。
- 组件化:当应用中的功能都是多组件的方式来编写的,那这个应用就是一个组件化的应用。
非单文件组件
使用组件的三大步骤
创建组件:
使用Vue.extend(options)
创建,其中 options和 new Vue(options)时传入的那个 options几乎一样,但有以下区别
- 不要写 el——最终所有的组件都要经过一个vm的管理,由vm中的 el决定服务哪个容器
- data必须写成函数——避免组件被复用时,数据存在引用关系
- 引申出data为什么需要是一个函数(利用一个最基本的函数调用销毁原理返回新对象)
- 【备注】使用 tempalte可以配置组件结构
注册组件:
- 局部创建:new Vue的时候传入 components选项
- 全局创建:Vue.component(‘组件名’, 组件)
使用组件(写组件标签)
代码示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue初体验</title>
<!-- 1.引入Vue -->
<script src="../js/vue.js"></script>
</head>
<body>
<!-- 2.准备一个容器 -->
<div id="root">
<h1>{{name}}</h1>
<hr>
<!-- 第三步:使用模板 -->
<School></School>
<!--<hr>
<Student></Student>-->
</div>
<script>
//第一步:创建模板
const School = Vue.extend({
template: `
<div>
<h1>学校名称:{{schoolName}}</h1>
<h1>学校地址:{{schoolAddress}}</h1>
<button @click="showName">点击显示学校名称</button>
</div>
`,
//el:'root',//组件定义时不支持el属性,因为最终所有的组件都要被一个vm管理,由vm决定服务于哪个容器
data(){
return {
schoolName:'复旦大学',
schoolAddress:'上海'
}
},
methods: {
showName() {
alert(this.schoolName)
}
}
})
//Vue.component("School",School) // 全局注册
//3.创建Vue实例
const vm = new Vue({
el: '#root',
components: {//局部注册,第二步:注册模板
School
},
data(){
return{
name: 'Hello Vue',
}
},
methods: {
showName() {
alert(this.schoolName)
}
}
})
</script>
</body>
</html>
注意事项
关于组件名:
一个单词组成:
- 第一种写法(首字母小写): school
- 第二种写法(首字母大写): School
多个单词组成:
- 第一种写法(kebab-case命名): my-school
- 第二种写法(CamelCase命名): MySchool(需要Vue脚手架支持)
备注:
- 组件名尽可能回避HTML中已有的元素名称,例如h2、H2
- 可以使用 name配置项指定组件在开发者工具中呈现的名字(写标签名的时候还得按注册的写法)
关于组件标签:
- 第一种写法:
- 第二种写法: (不使用脚手架会导致后续组件不能渲染)
- 简写方式:
const school = Vue.extend(options) 可以简写成 const school = options
组件嵌套
- 极尽可能的复用代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue初体验</title>
<!-- 1.引入Vue -->
<script src="../js/vue.js"></script>
</head>
<body>
<!-- 2.准备一个容器 -->
<div id="root">
<h1>{{name}}</h1>
<hr>
<!-- 第三步:使用模板 -->
<School></School>
<hr>
<Student></Student>
</div>
<script>
const Student = Vue.extend({
template: `
<div>
<h1>学校名称:{{studentName}}</h1>
<h1>学校地址:{{studentAge}}</h1>
<button @click="showStudentName">点击显示学生名称</button>
</div>
`,
data(){
return {
studentName:'朱家宝',
studentAge:18
}
},
methods: {
showStudentName() {
alert(this.studentName)
}
}
})
//第一步:创建模板
const School = Vue.extend({
template: `
<div>
<h1>学校名称:{{schoolName}}</h1>
<h1>学校地址:{{schoolAddress}}</h1>
<button @click="showName">点击显示学校名称</button>
<div style="border: 1px solid red;width: 50%">
<Student></Student>
</div>
</div>
`,
components: {//局部注册,第二步:注册模板
Student
},
data(){
return {
schoolName:'复旦大学',
schoolAddress:'上海'
}
},
methods: {
showName() {
alert(this.schoolName)
}
}
})
//3.创建Vue实例
const vm = new Vue({
el: '#root',
components: {//局部注册,第二步:注册模板
School,Student
},
data(){
return{
name: 'Hello Vue',
}
}
})
</script>
</body>
</html>
非单文件组件小结
- 模板编写没有提示
- 没有构建过程, 无法将 ES6 转换成 ES5
- 不支持组件的 CSS
- 真正开发中几乎不用:
单文件组件
单文件组件 vue 文件的组成(3 个部分)
模板页:
<template>
页面模板
</template>
JS 模块对象:
<script>
export default{...}
</script>
样式:
<style>
样式定义
</style>
问题
解决
- Vue脚手架