本文根据自己工作中总结的Vue2.0学习方法,帮助更多人更快的理解使用vue框架,大家都知道学习前端框架Vue,目前使用基数不断增加,有超React框架。Vue入门更简单,目前已更新Vue3.0语法,大家可以去项目中使用,并且相应的配套Vite下一代前端开发与构建工具,后期去代替一直使用的Webpack也是有可能。
目录
一、Vue相关文档
Vue官方文档https://v3.cn.vuejs.org/guide/introduction.html
二、Vue介绍、原理、优缺点
1.Vue.js 是什么
Vue 是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。另一方面,当与现代化的工具链以及各种支持类库结合使用时,Vue 也完全能够为复杂的单页应用提供驱动。
2.Vue原理
Vue的数据驱动是通过MVVM( Model-View-ViewModel )模式来实现的,MVVM主要包含3个部分,分别是Model、View 和ViewModel。Model指的是数据部分,主要负责业务数据; View指的是视图部分,即DOM元素,负责视图的处理。ViewModel是连接视图与数据的数据模型,负责监听Model或者View的修改。
在MVVM中,数据(Model)和视图(View)是不能直接通信的,视图模型(ViewModel)就相当于一个观察者,监控着双方的动作,并及时通知进行相应操作。当Model 发生变化的时候,ViewModel能够监听到这种变化,并及时通知View做出相应的修改。反之,当View发生变化时,ViewModel监听到变化后,通知Model进行修改,实现了视图与模型的互相解耦。
3.优点
- 轻量级的框架
- 双向数据绑定
- 组件化开发
- 单页面路由
- 虚拟dom
- 渐进式框架
- 数据和结构的分离
- 运行速度快
- 插件化
- 学习成本低
补充:
所谓组件化,就是把页面拆分成多个组件,每个组件依赖的 CSS、JS、模板、图片等资源放在一起开发和维护。 因为组件是资源独立的,所以组件在系统内部可复用,组件和组件之间可以嵌套,如果项目比较复杂,可以极大简化代码量,并且对后期的需求变更和维护也更加友好。
4.缺点
- 不支持IE8以下
- 社区可能没有Angular和React那么丰富
- 因为是单页面应用,不利于seo优化
- 初次加载时耗时多
三、Vue 指令
综合示例:
父组件:ceshi.vue
<template>
<div class=" pb30">
<div style="margin-top:92px">demo示例</div>
<nav-bar-top :titleText="titleName" :arrowTrue="arrowTrue"></nav-bar-top>
<!-- 条件判断 -->
<div v-if="isShowName">船长在船上的博客:</div>
<div v-if="isShowblog">https://blog.csdn.net/SmartJunTao</div>
<div v-show="isShow">记得关注!</div>
<!-- 循环 -->
<ul v-if="isShowName">
<li class="border" v-for="(item,index) in newslist" :key="index">
点击跳转:<a :href="item.address" target="_blank">{{item.title}}</a>
</li>
</ul>
<div v-text="msg"></div>
<div v-html="htmlMsg"></div>
<!-- 路由跳转 -->
<button @click="handleLink">跳转页面</button>
<!-- 表单绑定 -->
<input v-model="userTaxNumber" placeholder="请输入税号"/>
</div>
</template>
<script>
// 组件引入
import navBarTop from "../../components/navbarOut";
export default {
components:{
navBarTop
},
data(){
return {
titleName:"demo示例",
arrowTrue:true,
isShowblog:true,
isShowName:true,
isShow:true,
newslist:[
{
title:"vue使用高德地图搜索地址添加标记marker,定位,拖拽选址功能",
address:"https://blog.csdn.net/SmartJunTao/article/details/123955679"
},
{
title:"vue使用高德地图aMap实现轨迹动画查询显示",
address:"https://blog.csdn.net/SmartJunTao/article/details/124126318"
},
],
msg:"welcom",
htmlMsg:"<b>hello world!</b>",
userTaxNumber:"111"
}
},
methods:{
handleLink(){
// 几种写法都可以
this.$router.push({path:"/"})
// this.$router.push("/")
// this.$router.replace("/")
}
}
}
</script>
<style lang="scss" scoped>
.border{
border:1px solid #ccc;
padding:10px;
font-size:22px;
margin:20px;
}
a{
color: rebeccapurple;
}
</style>
子组件:navbar.vue
<!-- -->
<template>
<div>
<van-nav-bar :title="titleText" fixed @click-left="onClickLeft" safe-area-inset-top>
<template #left v-if="arrowTrue">
<van-icon name="arrow-left" size="22px" color="#024EE0" />
</template>
<template v-else> </template>
</van-nav-bar>
<div class="top"></div>
</div>
</template>
<script>
import { Toast } from "vant";
export default {
name: "navBarTop",
props: ["titleText", "arrowTrue", "soltName"], // 传入子组件的数据
data() {
return {
};
},
components: {},
computed: {},
mounted() {},
methods: {
// 返回到上一页
onClickLeft() {
// if (this.$route.name == "系统消息详情") {
// Bus.$emit("isNoticeSysDetail", '1');
// }
if (this.soltName == "toFirst") {
this.$router.push({ path: "/first/first"});
sessionStorage.setItem("sources","0");
} else if (this.arrowTrue == true) {
this.$router.go(-1);
}
}
}
};
</script>
<style lang='scss' scoped>
::v-deep.van-nav-bar,
.top {
height: 92px;
}
::v-deep.van-nav-bar__title {
font-size: 30px;
}
::v-deep.van-nav-bar--fixed {
z-index: 100;
}
::v-deep.van-nav-bar__left,
::v-deep.van-nav-bar__right {
font-size: 30px;
}
::v-deep.van-nav-bar ::v-deep.van-icon {
color: #333 !important;
}
</style>
以下单个指令分开介绍:
1.v-text
示例:
<span v-text="msg"></span>
<!-- 等价于 -->
<span>{{msg}}</span>
2.v-html
WARNING
在网站上动态渲染任意 HTML 是非常危险的,因为容易导致 XSS 攻击。只在可信内容上使用
v-html
,永不用在用户提交的内容上。
在单文件里,scoped
的样式不会应用在 v-html
内部,因为那部分 HTML 没有被 Vue 的模板编译器处理。如果你希望针对 v-html
的内容设置带作用域的 CSS,你可以用一个额外的全局 <style>
元素手动设置。
示例:
<div v-html="'<h1>Hello World</h1>'"></div>
3.v-show
控制显示与隐藏
<div v-show="true">显示</div>
<div v-show="false">隐藏</div>
4.v-if 、v-for
当和 v-for
一起使用时,v-if
的优先级比 v-for
更高。
- 不推荐在同一元素上使用
v-if
和v-for
<div v-if="data.length>0" v-for="(item,index) in data" :key="index">你好</div>
- 可以把
v-for
移动到<template>
标签中来修正
<template v-for="todo in todos" :key="todo.name">
<li v-if="!todo.isComplete">
{{ todo.name }}
</li>
</template>
5.v-else-if 、v-else
示例:
<div v-if="type === 'A'">
你好
</div>
<div v-else-if="type === 'B'">
你不好
</div>
<div v-else>
你到底好不好
</div>
5.v-on
示例:
<button v-on:click="handle"></button>
<!-- 缩写 -->
<button @click="handle"></button>
6.v-model
- 使用:表单绑定
<input> <select> <textarea>
- 修饰符:
.lazy - 取代 input 监听 change 事件
.number - 输入字符串转为有效的数字
.trim - 输入首尾空格过滤
<input v-model="textValue"/>
7.自定义指令
有的情况下,你仍然需要对普通 DOM 元素进行底层操作,这时候就会用到自定义指令。
当页面加载时候,该元素将获得焦点 。只要你在打开这个页面后还没点击过任何内容,这个输入框就应当还是处于聚焦状态。现在用指令来实现这个功能:
// 注册一个全局自定义指令 `v-focus`
Vue.directive('focus', {
// 当被绑定的元素插入到 DOM 中
inserted: function (el) {
// 聚焦元素
el.focus()
}
})
如果想注册局部指令,组件中也接受一个 directives
的选项:
directives: {
focus: {
// 指令的定义
inserted: function (el) {
el.focus()
}
}
}
你可以在模板中任何元素上使用新的 v-focus
property,如下:
<input v-focus>
四、组件通讯props
props
作用:
1.props
用于父子组件的通信。
2.props
具有单向下行绑定,由父组件传递给子组件。且子组件不能修改props
。
3.子组件不能修改props
,若需要修改props
的值,可以把props
作为初始值赋值给组件自己的data。
子组件中props的多种类型:
props: {
propA: Number,
// 多种类型
propB: [String, Number],
// 必传&&字符串
propC: {
type: String,
required: true
},
// 数字,有默认值
propD: {
type: Number,
default: 100
},
// 数组/对象的默认值设置函数返回
propE: {
type: Object,
default: function () {
return { message: 'hello' }
}
},
// 自定义验证函数
propF: {
validator: function (value) {
return value > 10
}
}
String
Number
Boolean
Function
Object
Array
Symbol
示例:
父组件:parents.vue
<template>
<div>
<template v-for="item in list">
<child :article="item"></child>
</template>
</div>
</template>
<script>
import child from '@/components/child.vue';
export default {
data() {
return {
list: [
{
title: "天龙八部",
name: "金庸"
},
{
title: "射雕英雄传",
name: "金庸"
}
]
}
},
components: {
child
}
}
</script>
子组件:child.vue
<template>
<div>
<p>
子组件:{{article.title}}--{{article.name}}
</p>
</div>
</template>
<script>
export default {
props: ['article'],
mounted() {
console.log(this.article);
}
}
</script>
重点是props: ['article']
,我们定义了一个名为article
的props属性,用来接收父组件传过来的值。
注意article
属性可以在template,以及mounted或者methods方法中自由引用。
五、组件通信emit
作用: 子组件使用 $emit,让父组件监听到自定义事件
用法:vue.$emit(自定义事件名称, 参数)
子组件:child.vue
<template>
<div>
<p>
{{article.title}}--{{article.author}}
<button @click="delete(article)">删除</button>
</p>
</div>
</template>
<script>
export default {
props: ['article'],
mounted() {
console.log(this.article);
},
methods: {
delete(article) {
this.$emit("remove", article);
}
}
}
</script>
注意,当点击删除按钮时,触发delete方法,而delete方法内容为this.$emit("remove", article);
,即调用了父组件的remove方法,且传递参数article
。
所以点击子组件删除按钮后,父组件中对应的内容会被删除。
六:路由
安装vue-router:
npm install vue-router -g
page1.vue
<template>
<div>
<h1>page1</h1>
</div>
</template>
router.js
import Vue from 'vue';
//引入vue-router
import VueRouter from 'vue-router';
Vue.use(VueRouter)
//引用页面
//import page1 from './page1.vue';
const routes=[
{
path:'/page/page1',
name:"申请发票成功",
component: resolve => require(['@/page/page1'], resolve),//路由懒加载
meta: {
requireAuth:true,
keepAlive: true,
}
]
const router=new VueRouter({
routes
});
//抛出
export default router
App.vue:
<template>
<div id="app">
<router-link to="/page/page1">Page1</router-link>
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'App'
}
</script>
扩展:vue路由跳转和传参
1.router-link:
不带参数:
<router-link :to="{name:'page'}">跳转到page页面</router-link>
<router-link :to="{path:'/page'}">跳转到page页面</router-link>
带参数:
<router-link :to="{name:'page',params: {orderId:123456}}">page</router-link>
<router-link :to="{name:'page',query: {orderId:123456}}">page</router-link>
page页面接受传递过来的参数:
template:
<div>{{$route.query.id}}</div>
<div>{{$route.params.id}}</div>
js:
this.$route.query.id
this.$route.params.id
2. 函数里面调用
不带参数:
this.$router.push({name:'page'})
this.$router.push({path:'/page'})
带参数:
this.$router.push({name:'home',query: {id:'123456'}})
this.$router.push({name:'home',params: {id:'123456'}})
this.$router.push({path:'/home',query: {id:'123456'}})
注意:参数传参,当用params进行传参的时候只能由name引用路由;使用query进行传参的时候,以path,name引入路由都是可以的。
后续会继续更新其它学习内容。
>✨ 原创不易,还希望各位支持一下!
>👍 点赞,你的认可是我创作的动力!
>⭐️ 收藏,你的青睐是我努力的方向!
>✏️ 评论,你的意见是我进步的财富!