Vue 基础篇
一、框架与库的区别
- JQ库->DOM(DOM操作) + Ajax请求
- art-template库->模板引擎
- 框架 -> 全方位、功能齐全
- 简易的DOM体验 + 发请求 + 模板引擎 + 路由功能 + ...
- 代码上的不同:
- 一般使用库:调用某个函数,自己可以把控库的代码
- 一般使用框架:其框架在帮我们运行已编写好的代码
- 框架:初始化自身的一些行为
- 执行你所编写的代码
- 施放一些资源
库:小而精
框架:大而全 ( 框架包含了各种库 )
二、起步
- 引包
- 直接用
<script>
引入 - CDN
- NPM
- 直接用
npm install --yes
npm install vue --save ( npm install vue -S )
- 创建实例化对象 **new Vue( options 对象 ) **
- options
- el : 目的地( 选择器 )
- data : 数据属性 ( 既可以是一个对象,也可以是一个函数 )
- 数据驱动试图:数据发生改变时,视图 发生改变。
- 除了数据属性,vue 实例还暴露了一些有用的实例属性和方法。他们都有前缀 el,$data 。
- template : 模板内容
- 优先级:如果 template 中定义了内容,那么有限加载 template;反之,加载 el 挂载的模板
- options
- vue的模板语法:
- {{}} 双大括号插值 同 react 中的 {}
- {{ 表达式 }}
- 对象 ( 不要连续三个大括号 {{ { key : value } }} )
- 字符串 {{ ’XXX‘ }}
- 判断后的布尔值 {{ true }}
- 三元表达式 {{ true ? '正确' : '错误' }}
- 可以用于页面中简单粗暴的调试
- 注意:必须在 data 这个函数中返回的对象中声明
- 设计模式:MVC 与 MVVM
- MVC:Model( 数据模型 )、View( 视图 )、Controller( 控制器 )
- 数据不是主动展示到 视图 上的,它是靠 控制器 取到 model 然后展示到 view。
- MVVM:Model、View、ViewModel
- vue的设计模式为MVVM, 只关注的是视图层
- MVC:Model( 数据模型 )、View( 视图 )、Controller( 控制器 )
三、指令 ( v-xxx )
- 在vue中提供了一些对于页面+数据的更为方便的输出,这些操作就叫做指令
- 比如html页面中的属性
<div v-xxx></div>
- 指令中封装了一些DOM行为,结合属性作为一个暗号,暗号有对应的值,根据不同的值,框架会进行相关的DOM操作的绑定。
- 比如html页面中的属性
- 常用指令
- v-text:元素的InnerText属性,其实就是给元素的innerText赋值,必须是双标签,跟{{}}效果是一样的,使用较少。
- v-html:元素的InnerHtml,其实就是给元素的innerHtml赋值。
- v-if:判断是否插入这个元素,相当于对元素的销毁和创建。appendChild()、removeChild()
- v-else-if
- v-else
- v-show:隐藏元素,如果确定要隐藏,会给元素的style加上
display:none;
,是基于css样式的切换。
- v-if 与 v-show 的区别 ( 官网解释 )
-
v-if
是“真正”的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当的被销毁和重建。 -
v-if
也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。 - 相比之下,
v-show
就简单的多——不管初始条件是什么,元素总会被渲染。并且只是简单的基于css进行 显/隐 切换。 - 一般来说,
v-if
有更高的切换开销,而v-show
有更高的初始渲染开销。因此,如果需要非常频繁的切换,则使用v-show
较好;如果在运行时条件很少改变,则使用v-if
较好。
-
- v-bind:绑定标签上的属性( 内置的属性和自定义的属性 ),
v-bind:class="box"
,简写:
。
<div class="container" :class="{active: true}"></div>
// 渲染为 DOM
<div class="container active"></div>
- v-on:
v-on:原生事件名 = '函数名'
,简写@
// html
<div class="container" @click="clickHandler"></div>
// js
methods:{
clickHandler(e){
console.log(this);
}
}
- v-for:
v-for="item,index in arr"
<ul>
<li v-for="item,index in list">
{{index}}--{{item}}
</li>
</ul>
- v-model:数据双向绑定
- 只会体现在UI空间中,只能应用在有value属性的元素。
<input v-model="msg">
// 等同于
<input :value="msg" @input="msg = $event.target.value" />
那么
v-model
其实就是v-bind
和v-on
的语法糖。
四、组件
1.局部组件
局部组件使用打油诗:声子挂子用子
声明子组件;父组件挂载子组件;父组件使用子组件。
// 局部组件的声明
var App = {
data(){
return{
}
},
template:`
<div>我是入口组件</div>
`
}
// vue实例
new Vue({
el:"",
data(){
},
// 挂载子组件
components:{
App
},
// 父组件直接可以使用
template:`<App />`
})
组件命名:
1.短横线分隔 命名:当引用组件时,也要使用 短横线分隔 形式。( 如: <my-compnent-name> )
2.驼峰式命名:当引用组件时,可以使用 短横线分隔 形式或者 驼峰 形式。( 如: <my-compnent-name> 或 <MyCompnentName>)
[注]:直接在DOM( 即非字符串的模板 )中使用时只有 短横线分隔 形式是有效的。
[建议]:命名时用 驼峰 形式,使用时用 短横线分隔 形式。
2.全局组件
Vue.component("组件名", options)
// 全局组件声明
// 第一个参数是组件的名字,第二个参数是options配置项
Vue.component("Vbtn", {
template:`
<button>按钮</button>
`
})
// 全局组件使用
var App = {
template:`
<div>
...
<Vbtn />
</div>
`
}
五、组件通信
1.通过 prop 往子组件通信
- 1.Parent 2.Child
- 先给父组件中绑定自定义的属性
Vue.component("Parent", {
data(){
return{
msg:"我是父组件的数据"
}
},
template:`
<div>
<p>我是父组件</p>
<Child :childData="msg" />
</div>
`
})
在子组件中使用 props 接收父组件传递的数据
在子组件中任意使用
Vue.component("Child", {
template:`
<div>
<p>我是子组件</p>
<input type="text" v-model="childData" />
</div>
`,
props:["childData"]
})
2.通过 事件 向父组件发送消息
- 在父组件绑定自定义的事件
- 在子组件中 触发原生的事件,在函数中使用
$emit
触发其父组件中自定义的事件$emit("自定义的事件名", "消息")
// Child
Vue.component("Child", {
template:`
<div>
<p>我是子组件</p>
<input type="text" v-model="childData" @input="changeValue(childData)" />
</div>
`,
props:["childData"],
methods:{
changeValue(val){
// 自定义的事件一定要通过 this.$emit() 去触发
// $emit("自定义的事件名", "消息")
this.$emit(childHandler, val)
}
}
})
// Parent
Vue.component("Parent", {
data(){
return{
msg:"我是父组件的数据"
}
},
template:`
<div>
<p>我是父组件</p>
<Child :childData="msg" @childHandler="childHandlerFn" />
</div>
`,
methods:{
childHandlerFn(val){
console.log(val);
}
}
})
六、插槽 slot
插槽:内置组件 slot,作为承载分发内容的出口
/* 模拟 elementUI 按钮组件的实现 */
// 子组件
Vue.component("Vbtn", {
template:`
<button class="default" :class="type">
<slot>按钮</slot>
</button>
`,
props:["type"]
})
// 父组件
var App = {
template:`
<div>
...
<Vbtn type="primary">登陆</Vbtn>
<Vbtn type="success">注册</Vbtn>
</div>
`
}
具名插槽
// 子组件
Vue.component("liItem", {
template:`
<li>
第一个槽
<slot name="idx-1"></slot>
第二个槽
<slot name="idx-2"></slot>
</li>
`
})
// 父组件
var App = {
template:`
<div>
<ul>
<liItem>
<h1 slot="idx-1">我是第一个槽</h1>
<h3 slot="idx-2">我是第二个槽</h3>
</liItem>
</ul>
</div>
`
}
七、过滤器
- 过滤器的作用:为页面中的数据进行添油加醋的功能
- 分类
- 局部过滤器
- 全局过滤器
/* 局部过滤器 */
// 1.声明过滤器
// 2. {{ 数据 | 过滤器的名字 }}
var App = {
data(){
return{
price:0,
msg:"hello filter"
}
},
template:`
<div>
<input type="number" v-model="price" />
<!-- 使用过滤器 -->
<h2>{{ price | myCurPrice }}</h2>
<h3>{{ price | myReverse }}</h3>
</div>
`,
filters:{
// 声明过滤器
myCurPrice: function(val){
return "¥" + val
}
}
}
/* 全局过滤器 */
// 字符串反转过滤器
Vue.filter("myReverse", function(val){
return val.split("").reverse().join("");
})
{{ 数据 | 过滤器的名字(可以传值) }}
例:
{{ price | myReverse("这里是传入的值") }}
// 其中 arg 就是传入的值
Vue.filter("myReverse", function(val, arg){
return val.split("").reverse().join("");
})
八、watch 监听
watch 监听的是单个属性
基本的数据类型 -- 简单监视
复杂的数据类型 -- 深度监视
- 监听简单数据类型
new Vue({
el:"",
data(){
return{
msg : ''
}
},
watch:{
msg: function(newVal, oldVal){
console.log(newVal, oldVal);
}
}
})
- 监听复杂数据类型 obj, arr, 等 -- 深度监视
new Vue({
el:"",
data(){
return{
userList : [{name:"jack"}]
}
},
watch:{
userList: {
deep:true, // 深度监视
handler: function(newVal, oldVal){
console.log(newVal, oldVal);
}
}
}
})
九、计算属性
- 计算属性 getter
// html
<img :src="getCurSrc" />
<ul>
<li v-for="item,index in dataList" @click="clickHandler(index)" :class="{active: curIdx == index}">{{ index }}</li>
</ul>
// js
new Vue({
el:"",
data(){
return{
dataList:[{imgsrc:'1'},{imgsrc:'2'},{imgsrc:'3'}],
curIdx : 0
}
},
computed:{
// 计算属性默认只有 getter
getCurSrc: function(){
return this.dataList[this.curIdx].imgsrc
}
},
methods:{
clickHandler(index){
this.curIdx = index;
}
}
})
- 计算属性 setter
// js
new Vue({
computed:{
getCurSrc: {
set: function(newVal){
console.log(newVal);
this.curIdx = newVal;
},
get: function(){
return this.dataList[this.curIdx].imgsrc
}
}
},
methods:{
clickHandler(index){
// 点语法 set方法 和 get方法
// getter 方法
console.log(this.getCurSrc);
// 调用set方法
this.getCurSrc = index;
}
}
})
十、生命周期
- beforeCreate:组件创建之前会调用
- created:组件创建之后 会调用
- 在created这个方法中可以操作后端的数据,数据驱动视图
- 应用:发起Ajax请求
- beforeMount:挂载数据到 DOM 之前会调用
- mounted:挂载数据到 DOM 之后会调用
- 应用:操作DOM
- beforeUpdate:在更新DOM之前 调用该钩子
- 应用:可以获取原始的DOM
- updated:在更新DOM之后 调用该钩子
- 应用:可以获取最新的DOM
- beforeDestroy:组件销毁之前会调用
- destroyed:组件销毁之后会调用
vue 内置组件 <keep-alive></keep-alive>
:能在组件的切换过程中将状态保留在内存中,防止重复渲染DOM。
- activated:组件被激活了
- deactivated:组件被停用了