Vue是一套用于构建用户界面的渐进式框架,与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用
Vue.js框架的作用主要注重动态的构建用户界面,前端工程和模块化开发
借鉴了React的组件化和虚拟DOM,借鉴了Angular的模块化和数据绑定
安装:下载到本地,用script标签引入;
CDN引入(两个较稳定的CDN):<script src="https://cdn.bootcss.com/vue/2.6.6/vue.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
脚手架工具:①vue-cli是基于npm的,所以要安装node.②安装完毕,npm install -g vue-cli;③命令行输入vue出现Usage表示成功④使用指令生成一个vue应用:vue init webpack wqqProject
⑤进入刚刚建的项目发文件夹内,输入npm run start将vue应用运行起来⑥成功执行后打开浏览器输入http://localhost:8080,就看到一个vue应用
1,Vue开发者工具安装:
Vue Devtools ,浏览器插件,允许在一个更友好的界面中审查和调试Vue应用
①下载对应浏览器的Vue Devtools
- Get the Chrome Extension / (beta channel)
- Get the Firefox Addon / (beta channel)
- Get standalone Electron app (works with any environment!)
安装之后控制台没有vue按钮,需要找到插件安装的路径,改mainfest.json文件中的第三行,"persistent":true,然后重新打开浏览器窗口,控制台的最后选项就会有vue
2,双大括号表达式 进行页面输出数据和调用对象方法
<div id="app">
<input type="text" v-model="msg">
<p>{{msg}}</p>
</div>
<script>
var app = new Vue({
el:'#app',//el: 挂载点
data:{ //data:数据选项
msg:'hello'
}
})
</script>
msg绑定Vue实例中的数据,在浏览器中就被渲染成data选项中的msg的值
但是通过使用 v-once
指令你也能执行一次性地插值,当数据 改变时,插值处的内容 不会更新。但是你需要注意一下,该元素节点下面其他数据的绑定,数据改变,内容也不会更新 <p v-once>msg:{{msg}}</p>
3,若是插入html元素,v-html指令
<div id="app" v-html="msg"></div>
<script>
var app = new Vue({
el:'#app',//el: 挂载点
data:{ //data:数据选项
msg:'<h1>hello wqq</h1>'
}
})
</script>
//结构就是h1样式的hello wqq
4,双大括号语法不能作用在HTML标签属性上,需要对标签属性操作,应该用v-bind指令:<div v-bind:class="syl-vue-course"></div>
HTML标签属性为布尔时.他们的存在表示为true,
<div id="app">
<input type="checkbox" v-bind:checked="isChecked">
</div>
<script>
var app = new Vue({
el:'#app',
data:{
isChecked:false // isChecked是否选中boolean
}
})
</script>
5,JavaScript表达式
<div id="app">
<!-- 运算符 -->
<p>num + 24 = {{num + 24}}</p>
<!-- 三元表达式 -->
<p>Are you ok? {{ok ? 'I am ok !':'no'}}</p>
<!-- 对象方法直接调用 -->
<p>名字倒过来写:{{name.split('').reverse().join('')}}</p>
<!-- 属性值运算操作 -->
<p v-bind:class="'col'+colNum">syl</p>
</div>
<script>
var app = new Vue({
el:'#app',
data:{
num:20,
ok:true,
name:'实验楼',
colNum:'12'
}
})
</script>
6.参数,接收参数的指令,在指令名称之后以冒号表示,eg,v-bind指令可以用于响应式的更新HTML特性,参数href,告知v-bind将该元素的href特性与表达式url的值绑定 <a v-bind:href="url">wqq</a>
<!-- 指令 参数-->
<div id="app">
<a v-bind:href="url">百度</a>
</div>
<script>
var app = new Vue({
el:'#app',
data:{
url:'http://baidu.com'
}
})
</script>
v-on指令:用于监听DOM事件
<div id="app">
<p>我叫:{{name}}</p>
<!-- handleClick 使我们在实例 methods 中写的方法 -->
<button v-on:click="handleClick">点我</button>
</div>
<script>
var app = new Vue({
el:'#app',
data:{
name:'实验楼'
},
methods: {//实例方法对象
handleClick:function(){
this.name = this.name.split('').reverse().join('')
}
},
})
</script>
7,动态参数 (属性或者事件可以动态)
<div id="app">
<p>我叫:{{name}}</p>
<button v-on:[event]="handleClick">点我</button>
</div>
<script>
var app = new Vue({
el:'#app',
data:{
name:'实验楼',
event:'click'
},
methods: {
handleClick:function(){
this.name = this.name.split('').reverse().join('')
}
},
})
</script>
//event此时是click
8,修饰符
以半角句号.指明的特殊后缀,用于指出一个指令应该以特殊方式绑定,有三类 事件修饰符,按键修饰符,系统修饰符
eg,.prevent修饰符和原生event.preventDefault()效果一样,可以阻止事件默认行为,在表单中点击提交按钮,就会发生页面跳转,但是使用了.prevent就不会跳转
<div id="app">
<form action="/" v-on:submit.prevent="submit">
<button type="submit">提交</button>
</form>
</div>
<script>
var app = new Vue({
el:'#app',
data:{
},
methods: {
submit:function(){
console.log('成功提交!')
}
},
})
</script>
//不加.prevent就会跳转,加了就不跳了
9,指令缩写
①v-bind: <a v-bind:href="url">lalakla</a> === <a :href="url">lalakla</a>
②v-on: <button v-on:click="handleClick">点我</button> === <button @click="handleClick">点我</button>
10,Vue实例中其他的属性
(1)计算属性 ①可以直接用{{}}向页面输出 例如下面定义的reverseName,可以直接在html中输出
<div id="app">
<p>我名字正着写:{{name}}</p>
<!-- reverseName 计算属性 可以像绑定普通属性一样在模板中绑定计算属性-->
<p>计算出我名字倒着写:{{reverseName}}</p>
</div>
<script>
var app = new Vue({
el:'#app',
data:{
name:'实验楼'
},
computed: {
//reverseName 是一个计算属性
reverseName:function(){
return this.name.split('').reverse().join('')
}
},
})
</script>
//这样的效果 也可以用methods:{}来实现,结果相同
区别:计算属性是基于他们的响应式依赖进行缓存的,只有相关依赖发生改变时它们才会重新求值,而调用方法总是会执行函数,所以当不希望有缓存的时候,用方法
②setter和getter
<div id="app">
<p>firstName:{{firstName}}</p>
<p>lastName:{{lastName}}</p>
<p>全名是:{{fullName}}</p>
<button v-on:click="changeName">改姓</button>
</div>
<script>
var app = new Vue({
el:'#app',
data:{
firstName:'王',
lastName:'花花'
},
methods: {
//changeName 定义一个方法改变 计算属性 fullName 的值
changeName:function(){
//修改计算属性 fullName 等于李花花
this.fullName = '李花花'
//上面一句等于触发了 fullName 属性的 setter
}
},
computed: {
fullName:{
//getter
get:function(){
return this.firstName+this.lastName
},
//setter 直接改变计算属性 fullName的值就可以触发setter this.fullName='XX'
set:function(newName){
var name = newName
this.firstName = name.slice(0,1) //取新值的第一个字符
this.lastName = name.slice(1) //从新值的第二个字符开始取值
}
}
}
})
</script>
//app.fullName ='wang qq',setter会被调用,app.firstName和app.lastName也会被更新
(2)侦听属性 在实例的watch选项中确定监听项(同样效果的话计算属性比侦听属性好),当需要在数据变化时执行异步或开销较大的操作时,使用侦听器比较合适。
<div id="app">
<p>{{msg}}</p>
<!-- v-on:click 简写为 @click -->
<button @click="handleClick('hello syl')">改变msg</button>
</div>
<script>
var app = new Vue({
el:'#app',
data:{
msg:'hello'
},
methods: {
//改变 msg的值
handleClick:function(val){
this.msg = val
}
},
// watch 监听属性
watch: {
//监听新旧值 监听属性有两个参数,第一个新值,第二个旧值
msg:function(newVal,oldVal){
alert('新值'+newVal+'----'+'旧值'+oldVal)
}
}
})
</script>
计算属性和监听属性功能都一样,区别是计算属性代码精简,可读性高,
//用侦听属性改写计算属性的例子
<div id="app">
<p>firstName:{{firstName}}</p>
<p>lastName:{{lastName}}</p>
<p>全名是:{{fullName}}</p>
<button v-on:click="changeName">改姓</button>
</div>
<script>
var app = new Vue({
el:'#app',
data:{
firstName:'王',
lastName:'花花',
fullName:'王花花'
},
methods: {
//changeName 定义一个方法改变 fullName 的值
changeName:function(){
this.fullName = '李花花'
}
},
watch: {
//fullName 侦听属性,监听fullName 值的改变
fullName:function(val){
var name = val
this.firstName = name.slice(0,1)
this.lastName = name.slice(1)
}
},
})
</script>
11,过滤器 计算属性和侦听属性处理数据时的加以过滤 用在双花括号插值和v-bind表达式(2.1.0开始支持),用|与过滤器分隔
eg:使用filter过滤器实现大写转换和自动去除字符串中的数字
<div id="app">
<!-- toUpperCase getString 为自定义的过滤器-->
<p>小写转换大写:过滤前:{{msg}} 过滤后: {{msg|toUpperCase}}</p>
<p>去除数字:过滤前:{{msg2}} 过滤后: {{msg2|getString}}</p>
</div>
<script>
var app = new Vue({
el:'#app',
data:{
msg:'hello',
msg2:'1s2y3l'
},
// filters 过滤器选项
filters:{
//toUpperCase 定义一个字符串转大写的过滤器
toUpperCase:function(val){
return val.toUpperCase()
},
//getString 定义一个获取去除数字的过滤器
getString:function(val){
let newVal = ''
val.split('').map(function(item){
if(9>=item&&item>=0){
return
}else{
return newVal+=item
}
})
return newVal
}
}
})
</script>
应用场景,商品价格过滤,表单数据过滤,比如返回的数据没有单位,可以用过滤器定义一个单位
<div id="app">
<!-- joint 为自定义的过滤器-->
<p>不要¥998,只要{{price|joint}}</p>
</div>
<script>
var app = new Vue({
el:'#app',
data:{
//后台价格数据
price:98
},
// filters 过滤器选项
filters:{
//joint 定义一个字符串转大写的过滤器
joint:function(price){
return '¥'+price
}
}
})
</script>
//结果:不要998,只要¥98
用计算属性和过滤器做购物车:
<div id="app">
<p>单价<span>{{price|joint}}</span></p>
数量:<input type="number" v-model="goodsNum">
<p>总价:<span>{{allPrice|joint}}</span></p>
</div>
<script>
var app = new Vue({
el:'#app',
data:{
price:98,
goodsNum:0
},
computed:{
allPrice: function () {
return this.goodsNum*this.price;
}
},
filters:{
joint:function(price){ //joint自定义的过滤器
return "¥"+price;
}
}
})
</script>
12.元素的class绑定 v-bind:class
①对象语法 给v-bind:class一个对象,以动态的切换class,语法表示active这个class存在与否将取决于数据属性isActive的Boolean值,{className:Boolean}
<style>
.active{
color:pink;
font-size: 22px;
}
.red-bg{
background: red;
}
</style>
<body>
<div id="app">
<span v-bind:class="{'active':isActive,'red-bg':isRed}">wqq</span>
</div>
<script>
var app = new Vue({
el:'#app',
data:{
isActive:true,
isRed:true
},
})
</script>
②数组语法
<style>
.active{
color:black;
font-size: 22px;
}
.red-bg{
background: red;
}
</style>
<body>
<div id="app">
<span v-bind:class="[activeClass,bgColorClass]">wqq</span>
</div>
<script>
var app = new Vue({
el:'#app',
data:{
activeClass:'active',
bgColorClass:'red-bg'
},
})
</script>
13,元素style绑定 (最好用驼峰命名) v-bind:style
①对象语法
<div id="app">
<p v-bind:style="{fontSize:size,backgroundColor:bgColor}">wqq</p>
</div>
<script>
var app = new Vue({
el:'#app',
data:{
size:'24px',
bgColor:'red'
},
})
</script>
或者直接绑定到一个样式对象上更简洁:
<div id="app">
<p v-bind:style="styleObject">wqq</p>
</div>
<script>
var app = new Vue({
el:'#app',
data:{
styleObject:{
fontSize:'24px',
backgroundColor:'red'
}
},
})
</script>
②数组语法 将多个样式对象应用到同一个元素上
<div id="app">
<p v-bind:style="[styleObject,styleObject2]">wqq</p>
</div>
<script>
var app = new Vue({
el:'#app',
data:{
styleObject:{
fontSize:'24px',
backgroundColor:'red'
},
styleObject2:{
marginTop:'100px',
textAlign:'center'
}
},
})
</script>
注意:属性的自动前缀,浏览器内核不同,使用某些css属性需要加前缀,在vue中使用了v-bind:style,就不用加前缀,vue在编译过程中,自动给需要前缀的加上
综合eg:动态改变style和切换class
<style>
.active{
color:red;
}
</style>
<body>
<div id="app">
<p v-bind:style="{fontSize:fontSize+'px'}" v-bind:class="{active:isActive}">wqq</p>
<button @click="handleClick">变大变红</button>
</div>
<script>
var app = new Vue({
el:'#app',
data:{
fontSize:20,
isActive:true
},
methods:{
handleClick: function () {
this.fontSize+=2
this.isActive=!this.isActive //取反
}
}
})
</script>
</body>
14,条件与循环渲染
①v-if和v-else v-if表示这块内容只会在指令的表达式返回除了false,0,"",null,undefined,NaN外的值的时候被渲染,否则就渲染v-else块元素(注意v-else必须紧跟在带有v-if和v-else-if元素后面)(不推荐同时使用 v-if
和 v-for,
而如果你的目的是有条件地跳过循环的执行,那么可以将 v-if
置于外层元素 (或 <template>
)上)
<div id="app">
<p v-if="display">wqq</p>
<p v-else>LALALA</p>
</div>
<script>
var app = new Vue({
el:'#app',
data:{
display:true
},
})
</script>
②v-show与v-if不同是,带有v-show的元素始终会被渲染并保留在DOM中,v-show只是简单地切换元素的css属性display,v-if是从虚拟DOM的层面操作(v-show适用于频繁切换,v-if适用于条件很少改变)(v-show
不支持 <template>
元素,也不支持 v-else)
<div id="app">
<p v-show="show">wqq</p>
</div>
<script>
var app = new Vue({
el:'#app',
data:{
show:false
},
})
</script>
③循环渲染 v-for 数组数据
<style>
ul{
width:100%;
height:40px;
list-style:none;
display:flex;/*布局,设置完之后,子元素的float、clear和vertical-align属性将失效*/
flex-direction:row;/*flex的属性,沿水平让元素从左到右排列,column是从上到下,row-reverse是从右到左*/
align-items:center;/*flex的属性,纵轴上居中放置*/
justify-content:center;/*flex的属性,在主轴(页面)上居中排列*/
background:grey;
}
ul li{
width:20%;
height:100%;
color:white;
line-height:40px;
text-align:center;
text-transform:capitalize;/*控制文本的大小写,仅有大写字母,lowercase,仅有小写,capitalize单词首位大写*/
}
</style>
<body>
<div id="app">
<ul class="nav">
<li v-for="navItem in nav">
{{navItem}}
</li>
</ul>
</div>
<script>
var app = new Vue({
el:'#app',
data:{
nav:['home','shop','contact','about','name','more','history']
},
})
</script>
<div v-for="item of items"></div> 可以用of代替 in,它更接近 JavaScript 迭代器的语法
③循环渲染 v-for 对象数据
<div id="app">
<div v-for="val in userInfo"><p>{{val}}</p></div>
</div>
<script>
var app = new Vue({
el:'#app',
data:{
userInfo:{
name:'wqq',
age:'22',
sex:'woman'
}
},
})
</script>
在遍历对象时,会按 Object.keys()
的结果遍历,但是不能保证它的结果在不同的 JavaScript 引擎下都一致
注意:由于js限制,Vue不能检测对象属性的添加或删除,直接进行app.userInfo.height='180cm'不会触发视图更新.必须用Vue.set(object,key,value)向对象添加响应式属性: Vue.set(app.userInfo,'height','180m')
④key属性 理想的key值是id,因为是属性,需要用个v-bind来绑定动态值
<div v-for='item in items' :key='item.id'></div>,尽可能用v-for时候提供key,除非遍历输出的DOM内容非常简单
⑤数组更新检测
变异方法(会直接改变原始数组):push(),pop(),shift(),unshift(),splice(),sort(),reverse(),视图会随之更新
非变异方法(不直接改变原数组):filter(),slice(),contat(),视图不会随之更新,可用数组替换方法,将非变异返回的新数组赋值给旧数组
this.nav=this.nav.slice(1,4)
注:由于js的限制,Vue不能检测一下变动的数组:
1)利用索引直接设置一个项时,eg:vm.items[indexOfItem]=newValue
2)修改数组长度,eg:vm.items.length=newLength
解决1)问题:
Vue.set(vm.items, indexOfItem, newValue)
vm.items.splice(indexOfItem, 1, newValue)
vm.$set(vm.items, indexOfItem, newValue) //是全局方法Vue.set的一个别名
解决2)问题: vm.items.splice(newLength)
15.对象变更检测注意事项
var vm = new Vue({ data: { a: 1 } }) // `vm.a` 现在是响应式的
vm.b = 2 // `vm.b` 不是响应式的
对于已经创建的实例,Vue不允许动态添加根级别的响应式属性.可使用Vue.set(object,propertyName,value) 方法向嵌套对象添加响应式属性eg:
var vm=new Vue({
data:{
userProfile:{
name:"wqq"
}
}
})
添加一个新的属性age到嵌套的userProfile对象:
Vue.set(vm.userProfile,"age",18) == vm.$set(vm.userProfile,"age",18)
若是添加多个属性,Object.assign()
或 _.extend(),但格式
不能按照上面的了,
vm.userProfile=Object.assign({},vm.userProfile,{
age:18,
favoriteColor:"red"
})
16,显示过滤/排序后的结果(不改变原数据),创建一个计算属性,来返回过滤或排序后的数组
eg:<li v-for="n in evenNumbers">{{ n }}</li>
data:{numbers:[1,2,3,4,5]},
computed:{
evenNumbers:function(){
return this.numbers.filter(function(number){
return number % 2 === 0
})
}
}
在计算属性不适用的情况下,在嵌套v-for循环中:
eg:<li v-for="n in even(numbers)">{{ n }}</li>
data:{ numbers:[1,2,3,4,5]},
methods:{
even:function(numbers){
return numbers.filter(function(number){
return number %2 === 0
})
}
}
17.在<template>上使用v-for
<ul>
<template v-for="item in items">
<li>{{item.msg}}</li>
<li class="divider" role="presentation"></li>
</template>
</ul>
18.修饰符
<!--事件修饰符-->
<!--阻止单击事件继续传播-->
<a v-on:click.stop="doThis"></a>
<!--提交事件不再重载页面-->
<form v-on:submit.prevent="onSubmit"></form>
<!---修饰符可以串联-->
<a v-on:click.stop.prevent="doThat"></a>
<!--只有修饰符-->
<form v-on:submit.prevent></form>
<!--添加事件监听器时使用事件捕捉模式-->
<!--即内部元素触发的事件先在此处理,然后才交由内部元素进行处理-->
<div v-on:click.capture="doThis"></div>
<!--只当在event.target是当前元素自身时触发处理函数-->
<!--即事件不是从内部元素触发的-->
<div v-on:click.self="doThat"></div>
<!--使用修饰符的顺序 v-on:click.prevent.self会阻止所有的点击,v-on.click.self.prevent只会阻止对元素自身的点击-->
新增:
v-on.click.once 只会触发一次;
v-on:scroll.passive="onScroll" 滚动事件会立即触发,不会等待onScroll完成,.passive尤其能提升移动端的性能
不要把 .passive
和 .prevent
一起使用,因为 .prevent
将会被忽略,同时浏览器可能会向你展示一个警告。请记住,.passive
会告诉浏览器你不想阻止事件的默认行为
按键修饰符:
v-on:keyup.enter="submit" (只有在key是enter时调用vm.submit())
<input v-on:keyup.page-down="onPageDown"> 处理函数只会在$event.key
等于 PageDown
时被调用
按键码: keycode事件用法已经废弃且可能不会被最新浏览器支持
使用keycode attribute也是允许的 <input v-on:keyup.13="submit">
为了在必要的情况下支持就浏览器,Vue提供了绝大多数常用的按键码别名:
.enter / .tab /.delete(捕获删除和退格) /.esc /.space /.up /.down/.left /.right
还可以全局config.keyCodes对象自定义按键修饰符别名 : Vue.config.keyCodes.f11=112
19.表单输入绑定
在文本区域插值 (<textarea>{{message}}</textarea>
) 并不会生效,应用 v-model
来代替
修饰符:
.lazy :<input v-model.lazy="msg" > <!-- 在“change”时而非“input”时更新 -->
.number <input v-model.number="age" type="number"> 自动将用户的输入值转为数值类型
.trim <input v-model.trim="msg"> 自动过滤用户输入的首尾空白字符
20.组件基础
// 定义一个名为 button-counter 的新组件
Vue.component('button-counter', {
data: function () {
return {
count: 0
}
},
template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>'
})
<div id="components-demo"> <button-counter></button-counter> <button-counter></button-counter> </div>
new Vue({el:"#components-demo"})
因为组件是可复用的 Vue 实例,所以它们与 new Vue
接收相同的选项,例如 data
、computed
、watch
、methods
以及生命周期钩子等。仅有的例外是像 el
这样根实例特有的选项。
一个组件的data选项必须是个函数,因此每个实例可以维护一份被返回对象的独立的拷贝
21.通过prop向子组件传递数据
prop是你可以在组件上注册的一些自定义attribute,当一个值传递给一个 prop attribute 的时候,它就变成了那个组件实例的一个属性
一个组件默认可以拥有任意数量的 prop,任何值都可以传递给任何 prop。在下面模板中,你会发现我们能够在组件实例中访问这个值,就像访问 data
中的值一样
Vue.component('blog-post', {
props: ['title'],
template: '<h3>{{ title }}</h3>'
})
使用: <blog-post title="My journey with Vue"></blog-post> 标题就是显示: "My journey with Vue"
也能用data放博文数组 :
new Vue({
el: '#blog-post-demo',
data: {
posts: [
{ id: 1, title: 'My journey with Vue' },
{ id: 2, title: 'Blogging with Vue' },
{ id: 3, title: 'Why Vue is so fun' }
]
}
})
为每篇博文渲染一个组件:用v-bind动态传递prop
<blog-post
v-for="post in posts"
v-bind:key="post.id"
v-bind:title="post.title"
></blog-post>
22单个根元素
当构建一个<blog-post>组件时,你的模板最终会包含的不仅一个标题,还有内容等,使之越来越复杂,所以可以重构这个组件,让它变成接受一个单独的 post
prop:
<blog-post
v-for="post in posts"
v-bind:key="post.id"
v-bind:post="post"
></blog-post>
Vue.component('blog-post',{
props:['post'],
template:`<div class="blog-post">
<h3>{{post.title}}</h3>
<div v-html="post.content"></div>
</div>
`
})
23 监听子组件事件
父组件通过v-on监听子组件实例的任意事件:<blog-post v-on:enlarge-text="postFontSize+=0.1"> </blog-post>
子组件通过调用内建的$emit方法并传入事件名称来触发一个事件:<button v-on:click="$emit('enlarge-text')">enlarge</button>
#使用事件抛出一个值,使用 $emit
的第二个参数来提供这个值:<button v-on:click="$emit('enlarge-text',0.1)">enlarge</button>
然后当在父级组件监听这个事件的时候,可以通过 $event
访问到被抛出的这个值:
<blog-post v-on:enlarge-text="postFontSize+=$event"></blog-post>
或者是个方法:
<blog-post v-on:enlarge-text="onEnlargeText"></blog-post>,那么这个值将会作为第一个参数传入这个方法:
methods:{
onEnlargeText:function(enlargeAmount){
this.postFontSize+=enlargeAmount
}
}
#在组件上使用v-model
自定义事件也可以用于创建支持 v-model
的自定义输入组件 <input v-model="searchText">
等价于
<input v-bind:value="searchText" v-on:input="searchText=$event.target.value">
当用在组件上时,v-model
则会这样
<custom-input v-bind:value="searchText" v-on:input="searchText=$event"></custom-input>
使用必须:
①将其value 属性绑定到一个名叫value的prop上
②在其input事件被触发时,将新的值通过自定义的input事件抛出
Vue.component('custom-input',{
props:['value'],
template:`
<input v-bind:value="value" v-on:input="$emit('input',$event.target.value)">
`
})
使用:<custom-input v-model="searchText"></custom-input>
24.通过插槽分发内容
和html元素一样,若要像一个组件传递内容:
<alert-box> something bad happened</alert-box> 渲染出首行Error字符并加粗
Vue.component('alert-box',{
template:`
<div class ="demo-alert-box">
<strong>Error!</strong>
<slot></slot></div>
`
})
25动态组件
<component v-bind:is="currentTabComponent"></component> (组件会在currentTabComponent改变时改变,currentTabComponent可以包括已注册组件的名字或一个组件的选项对象)
26解析DOM
<table> <blog-post-row></blog-post-row> </table>自定义组件 <blog-post-row>
会被作为无效的内容提升到外部,并导致最终渲染结果出错
解决: is 属性
<table> <tr is="blog-post-row"></tr> </table>
26组件注册
组件名称字母全小写且必须包含一个连字符 eg:my-component-name 引用的时候也要一样
第二种是MyComponentName,引用的时候可有两种写法,<my-component-name>
和 <MyComponentName>