文章目录
vue是什么
Vue.js是一套构建用户界面的渐进式的MVVM框架,Vue 采用自下向上增量开发的设计,其核心库只关注视图层,易于上手,同时vue完全有能力驱动采用单文件组件和 Vue 生态系统支持的库开发的复杂单页应用。其实抛开官方的一些不知所云的说法,简单来说,在传统web开发中,我们搭建项目都以html结构为基础,然后通过jquery或者js来添加各种特效功能,需要去选中每一个元素进行命令,这些内容在简单的项目中或者不变的项目中还能应付得来,一旦项目改动或者项目工程较大,代码的修改将是复杂繁琐的,而这时候用了vue,这些问题都不复存在。在比如一些单网页制作成的应用程序,一般涉及到数据交互的内容都很多,而应用了vue之后将大大缩减工作量。
详细文档可参考 官方文档
安装和使用vue
首先我们得先安装好node.js,可以用node -v查看下node版本看本机上是否成功安装上node。
1.我们先全局安装下vue-cli脚手架工具
npm install -g vue-cli
2.在目标文件下创建vue项目()
vue init webpack my-project
//在构建vue项目的时候esline可以选择no(非严格模式)
3.我们进入到my-project中加载依赖
npm install
4.现在我们可以运行vue项目了
npm run dev
5.我们在浏览器上输入localhost:8080 就可以看到以下页面
概念和项目结构
先看一个最简单的vue例子
<div id="app">
<p>{{ message }}</p>
</div>
<script>
new Vue({
el: '#app',
data: {
message: 'Hello Vue.js!'
}
})
挂载点:就是el属性对应html中的节点,实例只会处理挂载点下的内容。
模版:在挂载点内部的内容,也可以将模版内容卸载实例里面
如果是用vue-cli创建的项目其脚手架已经帮我们自动挂载,其结构如下
<template>
<div>
{{message}}
</div>
</template>
<script>
export default{
data(){
return {
message:"hello world"
}
},
methods: {}
}
</script>
<style lang="scss" scoped>
</style>
vue-cli创建的项目大体都是上述结构,
lang="scss"表示样式使用scss语言 如果使用css把这个属性去掉就好
vue的生命周期
生命周期先了解以下概念,等看完后面的文章,在实战过程中再来看这生命周期,可能更容易理解一点。
生命周期:
beforCreate created 创建期
beforeMount mouted 挂载期
beforeUpdate updated 更新期
beforeDestroy destroyed 结束期
项目的主要结构
一些常用的配置会在文章后面做介绍
基本操作指令
插值表达式:
<template>
<div>{{message}}</div>
</template>
<script>
export default{
data(){
return {
message:"hello world"
}
}
}
</script>
注: 如果在data数据没有加载完时,使用这种方式加载的数据可能会出现闪屏问题。
我们可以用v-text或v-html解决这个问题。
v-text表达式:
<div v-text="message"></div>
v-html表达式:
<div v-html="message"></div>
注意:v-text和v-html的区别:v-html会进行内容转义为html,而v-text则不会
v-once使用
<template>
<div v-once>{{message}}</div>
</template>
<script>
export default{
data(){
return {
message:"hello world"
}
}
}
</script>
挂载点的内容页面只渲染一次,渲染后,其元素/组件及子节点都会当作静态内容跳过,可优化更新性能。
v-on使用(可简写为@)
<template>
<div @click="change">{{message}}</div>
</template>
<script>
export default{
data(){
return {
message:"hello world"
}
},
methods:{
change(){
this.message = " I had changed"
}
}
}
</script>
v-on有点类似js的添加事件功能。用法如上
当我们点击监听时,其就会触发methods下的onchange事件。当然 双引号内也可以写js代码。
v-bind使用(可简写为:)
<div v-bind:class-"title" class="title"/>
<div v-bind:message =“message” >
动态绑定一个或多个特性,或一个组件prop到表达式
当绑定clsss或style特性时,其不会和原属性冲突,
绑定prop时用于父子传值,后续会有介绍。
v-model使用(可简写为@)
<div v-model="message">{{message}}</div>
这个指令主要用于数据的双向绑定,也是mvvm框架的亮点。
当我们修改data中的message值的时候,div中的message值也会同步修改
v-if/v-show使用
<div v-if="change">v-if内容</div>
<div v-if="change">v-show内容</div>
其两个都是用来操作元素的显示或隐藏,当data中change值为true则显示,反则隐藏。
但其有本质的区别:
v-if:其会将整个标签在dom树中移除,性能代价牺牲较大。
v-show:其只是单单将display设为none,没有根本上删除元素。
v-for使用
<template>
<div><li v-for="(item,index) of list" :key="index">{{item}}</li></div>
</template>
<script>
export default{
data(){
return {
list:[1,2,3,4,5]
}
}
}
</script>
遍历list数组,:key为遍历的索引值,可有可无,但建立保留,严格模式下会出现报错。
计算、过滤属性、侦听器
computed计算属性
<div id="example">
<p>Original message: "{{ message }}"</p>
<p>Computed reversed message: "{{ reversedMessage }}"</p>
<p>Original message: "{{ setMessage }}"</p>
</div>
//vue
var vm = new Vue({
el:'#example',
data:{
message:'Hello',
setMessage:"nothing",
},
computed:{
reversedMessage:
get:function(){
//this 指向当前挂载点vm
return this.message.splist('').reverse().join(''); //olleH
},
set:function(){
this.setMessage = "I had changed";
}
}
)}
计算属性,只有它依赖的属性的值发生变化的时候他才会重新计算。其不是方法。
方法不会有缓存,而computed回根据依赖的属性进行缓存。
watch侦听器
<div id="example">
<p>Original message: "{{ message }}"</p>
</div>
//vue
var vm = new Vue({
el:'#example',
data:{
message:'Hello',
},
watch:{
message:function(){
//this 指向当前挂载点vm
console.log("侦听的元素发生改变")
}
}
)}
当侦听元素的值发生变化事才会触发。
虽然计算属性在大多数情况下更合适,但有时也需要一个自定义的侦听器。这就是为什么 Vue 通过 watch 选项提供了一个更通用的方法,来响应数据的变化。当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的。
filters过滤属性
<div id="example">
<p>Original message: "{{ message|filter1 }}"</p>
</div>
//vue
var vm = new Vue({
el:'#example',
data:{
message:'500',
},
filters:{
filter1:function(arg){
return arg+"$";
}}
)}
过滤属性主要是用于对值的初始化、格式化操作。例如日期、时间、金钱的格式规范化操作。
路由的使用
因为vue-cli已经帮我们导入了vue-router模块,我们直接配置使用既可。
当我们想添加或修改路由的配置的时候,我们直接可以配置./src/router/index.js文件即可
例如我们在./src/page中添加一个index页面。配置如下
import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'
import Indexs from './../page/index' //导入.vue文件
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: 'HelloWorld',
component: HelloWorld
},
{
path: '/pages', //访问的路径
name: 'Indexs', //页面名称
component: Indexs //注册导入的.vue文件
}
]
})
我们如果想修改默认打开页面,直接修改path即可。
注:每添加一个页面都需要注册路由并重启项目。
router-link
router-link组件支持用户在具有路由功能的应用中点击导航。通过to属性指定目标地址,默认渲染为带有正确连接的标签,可以通过配置tag属性生成其他标签。
<router-link to="home" tag="li" active-class="activeClass">Home</router>
当点击时跳转到/home页面,该router-line为li标签。actice-class表示的是链接激活时使用的CSS类名。
组件的使用
组件是vue的一大特性,充分利用组件进行模块化开发,能大大加快开发的进度。
我们可以直接在当前页面中创建一个组件例如下面
<div id="app">
<component-a></component-a>
<component-b></component-b>
</div>
Vue.component('component-a', { /* ... */ })//全局注册组件
var ComponentB = { /* ... */ }
new Vue({
el: '#app',
components: {
'component-b': ComponentB
}
})
上面两种方式都可以并引用组件。但器只能在当前页面中引用。所以一般不建议这样写组件。
因为我们一般都是用vue-cli生成项目,我们可以在components下创建一个.vue后缀的组件,然后需要的页面中引用该组件即可。像下面这样
// ./src/components/HelloWorld.vue
<template>
<div class="hello">
<p>Original message: "{{ message|filter1 }}"</p>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
data () {
return {
msg: 'Welcome to Your Vue.js App',
}
}
}
</script>
<style scoped>
</style>
接着我们在需要引入该组件的页面中导入该模块
<template>
<div class="wrapper">
<helloworld></helloworld>
</div>
</template>
import helloworld from './../components/HelloWorld' //导入组件
export default {
props:{},
data(){
return {
}
},
components:{
helloworld //组件注册
},
}
再在compents中注册一下该组件,如果是注册名和组件名一样只写组件名即可。
父传子、子传父
父组件向子组件传值
1.创建子组件,在src/component/文件下新建一个child.vue
2.child.vue中创建一个props,然后创建一个名为message的属性
<template>
<div>
<h2>child子组件部分</h2>
<p>{{message}}</p>
</div>
</template>
<script>
export default {
props:['message'],
}
3.在App.vue中注册child组件,并在template中加入child标签,标签中添加message属性并赋值
<template>
<div>
<div :message="jjj">哦咯</div>
</div>
</template>
<script>
export default {
}
</script>
这样子元素通过props就能接受到父元素传过来的hello值
子组件向父组件传值
1.首先我们在子组件创建一个按钮,点击时触发$emit事件
<template>
<div>
<h2>child子组件部分</h2>
<p>{{message}}</p>
<button v-on:click="sendMsgToParent">向父组件传值</button>
</div>
</template>
<script>
export default {
props:['message'],
methods:{
sendMsgToParent:function(){
this.$emit("listenToChildEvent","this message is from child");
}
}
}
</script>
其中$emit中第一参数为提交给父元素的事件名称,第二参数为提交的参数。
2.我们在父元素中通过v-on来绑定子元素提交的事件并处理
<template>
<div id="app">
<!-- <router-view/> -->
<child v-bind:message="parentMsg" v-on:listenToChildEvent="showMsgFromChild">
</child>
</div>
</template>
<script>
import child from './components/child'
export default {
name: 'App',
data(){
return{
parentMsg:"hello,child"
}
},
components:{
child
},
methods:{
showMsgFromChild:function(data){
this.parentMsg=data;
}
}
}
</script>
这段代码不单完成了父传子,还完成了子传父的过程,它将接受到子组件的值再传完到子组件中。
插槽slot
插槽其实就是将父组件中一些内容插入到子组件固定位置。
插槽中的属性也只能访问到原作用域(既父组件的作用域),不能访问被插入组件的作用域(子组件作用域)
默认插槽
在子组件创建一个插入口slot
<template>
<div>
<h2>child子组件部分</h2>
<slot></slot>
</div>
</template>
<script>
export default {
}
</script>
在父组件中引入字组件引入标签中的内容既为要插入到子组件的内容
<template>
<div id="app">
<div>下面就是插槽</div>
<child>这是父元素想要插入子元素的内容</child> //插入内容
</div>
</template>
<script>
import child from './components/child'
export default {
name: 'App',
components:{
child
}
}
</script>
当我们在子组件中的slot中加入内容,像这样后备内容,其作用就是当父元素没有插入任何内容时,其默认显示slot中的内容(既后备内容)
具名插槽
当我们定了多个插槽时,我们想将对应的值插入到对应的插槽中,这时我们就可以定义其插槽的名称来识别插入不同的插槽。
首先在子组件中定义不同插槽名称和位置
<template>
<div>
<h2>child子组件部分</h2>
默认:<slot></slot>
第一插槽:<slot name="first"></slot>
第二插槽:<slot name="second"></slot>
第三插槽:<slot name="third"></slot>
</div>
</template>
<script>
export default {
}
</script>
接着,我们需在父组件中插入多个template 通过表明v-slot来指向不同的插槽
<template>
<div id="app">
<div>下面就是插槽</div>
<child>
这是父元素想要插入子元素的内容
<template v-slot:second>
<p>第二个位置</p>
</template>
<template v-slot:first>
<p>第一个位置</p>
</template>
<template v-slot:third>
<p>第三个位置</p>
</template>
</child>
</div>
</template>
<script>
import child from './components/child'
export default {
name: 'App',
components:{
child
}
}
</script>
这就完成了简单具名插槽操作,如果我们想要动态修改插槽的话,我们只需要修改一下v-slot或name的值就可以了,这里就不演示了。
代理请求配置
受限于同源策略的影响,当请求一个url时,其域名、协议和端口号只要其中一个不同,就会出现跨越问题。
我们可以配置vue-cli中的跨域代理来处理这个问题。
1.我们打开./config目录下的index.js文件找到proxyTable配置项目
假如我们要请求http://binguo.online:8888中的数据,我们可以这样配置:
proxyTable: {
'/api':{
target:'http://binguo.online:8888', //目标网址
changeOrigin:true, //是否跨域
pathRewrite:{
"^/api":'' //替换target中的请求地址
}
}
},
‘/api’:表示访问路由路径
target:表示想要请求目标网址路径
changeOrigin:表示是否跨域
pathRewrite:参数是一个正则表达式,一般没特殊要求可以不配置。
(如何不配置pathRewrite 请求就被转发到 http://binguo.online:8888并把相应uri带上。比如:localhost:8080/api/xxx 会被转发到http://binguo.online:8888/api/xxx)
这里的作用,相当于是替代‘/api’,如果接口中是没有api的,那就直接置空,就像我截图的一样,如果接口中有api,那就得写成{‘^/api’:‘/api’},可以理解为一个重定向或者重新赋值的功能。
Element组件使用
element ui是基于vue2.0开发,其只需要引入即可使用,有点类似于傻瓜式框架bootstrap。下面直接说下怎么引用吧!,具体组件的使用可参考官方的文档!
Element官方文档
我们先现在目标文件下安装element-ui
npm isntall element-ui -d
接着 我们引入element-ui模块既可,我们修改一下./src/main.js配置文件
import Vue from 'vue'
import App from './App'
import router from './router'
import ElementUI from 'element-ui'; //导入eleement-ui
import 'element-ui/lib/theme-chalk/index.css';
Vue.config.productionTip = false
Vue.use(ElementUI); //全局引用Element-ui
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
components: { App },
template: '<App/>'
})
这样我们就可以直接在页面中引入element-ui。当我们要引用不同的组件时,只需要复制官网中相应组件的代码到指定位置,再根据需求修改一下便可。
axios
axios是基于promise的http库,可运行在浏览器端和node.js中。
其还可以实现拦截请求和响应、取消请求、转换json、防御XSRF攻击等。
详细文档参考axios文档
1.在目标文件夹中安装axios
npm isntall axios --save-dev
2.引入axios
import axios from 'axios'
发送get请求
axios.get('localhost:3000?userId=123')
.then(function(response){
console.log(response);
})
.catch(function(err){
console.log(err);
})
发送post请求
axios.post('localhost:3000'{
userID:'123',
userPwd:'123'
})
.then(function(response){
console.log(response);
})
.catch(function(err){
console.log(err);
})
我们可以发现其和promise的结构是十分相识的,更容易被我们理解。
如果想了解一下promise可以参考廖雪峰-promise
模拟请求mock
vue还有一个十分强大的功能,就是模拟请求。即使后台接口还没有写好,我们也可以虚拟出一个皆空,这样,当前后端对接的时候,就能有效加快开发速度和降低出错的几率。
我们可以在主目录下创建一个mock文件夹,新建一个json文件
// ./mock/goods.json
{
"status":"0",
"msg":"",
"result":[
{
"producted":"100001",
"productName":"小米6",
"productPrice":2499,
"productImg":"1.jpg"
}
]
}
接着我们修改./build/webpack.dev.conf.js配置文件,创建一个虚拟服务器。把下面的代码增加上去。
const express = require('express')
const app = express();
var appData = require('./../mock/goods.json');
var apiRoutes = express.Router();
app.use(apiRoutes)
接着在before(app){}里面写一下请求处理代码:
before(app){
app.get("/goods",function (req,res) {
res.json({
status:0,
result:appData
});
});
}
这段是epxress框架的代码,意思就是当该路径接受到get请求时,返回状态0和刚刚我们创建的json数据。
这里了解一下就好,如果想深入学习的话可以看下下面链接
菜鸟教程-node
express框架学习之路
---------以下内容可以等vue稍微熟悉一点再接触,如果刚入门理解起来可能会比较难
vuex、webpack配置
如果只是单纯用vue做一些不太复杂的项目的话,也可以暂时不需要学习这一部分内容。
1.因为vue-cli已经帮我们配置好webpack,无需太大的修改。但我们如果我们项目中没有像vue-cli这样帮我们生成webpack,我们就得自己配置webpack,当然我们也可以用gulp,但对于前沿的SPA来说gulp又显得力不从心,所以还是建议学习一下webpack。
2.Vuex帮助我们处理共享状态管理以及更多概念和样板的成本。这是短期和长期生产力之间的权衡。如果没接触过大型的SPA直接学习Vuex的话可能会觉得有点难理解,如果只是写简单的应用的话,没有Vuex或许会更好。
由于本文章的篇幅已过长,不方便查阅,所以我把vuex和webpack这两部分的总结分开来写,可以点击下方的链接来学习这两部分的内容。
带你由浅入深探索webpack4(一)
带你由浅入深探索webpack4(二)
vue快速入门和总结