MVVM模式
视图与模型的双向绑定,即数据的变动会导致页面的变化。视图与模型分开。
graph TD
view --> viewmodel --> model --> viewmodel --> view
vue初体验
将其引入html中即可使用vue相关语法。
<!-- 开发环境版本,包含了有帮助的命令行警告 --> <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<!-- 生产环境版本,优化了尺寸和速度 --> <script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
实例与数据绑定
//app代表Vue实例
var app = new Vue({
el:'#dom' // 页面存在的DOM元素
data:{} // 数据绑定,值为一个js对象
})
console.log(app.$el,app.data对象的对象key) // 访问方式
插值和表达式
双大括号{{}}是文本插值方法,可以实现数据双向绑定,可以使用三元运算计算结果,可以使用管道符计算结果{{data | formatDate}}(通过右边的函数计算结果)
标签属性(指令和事件)
- v-html 直接输出html(需要xss处理)
- v-pre 跳过编译过程
- v-bind 动态更新html元素上的属性=语法糖 :html元素属性
-
- 设置对象,可以动态切换值:class="{'active':isActive}"
-
- 设置方法,可以使用计算属性来getter值
-
- 设置数组,:class="[activecss,errorcss]"
-
- :style="以上三种" 设置内联样式方法
- v-on 绑定事件监听器=语法糖 @js事件
- v-cloak 会在实例结束编译时从绑定的html元素上移除
- v-once 元素或组件只会渲染一次
- key属性会使元素重新渲染
- v-if/v-show show适合频繁切换条件,if适合不经常改变的场景
- v-for 改变原始数组值的方法都会导致元素的重新渲染
- @click 点击事件语法糖 如果有参数会将event传入方法。vue特殊变量$event用于访问原生dom事件
- v-model 表单元素双向绑定数据,其值是表单的默认值;默认找的是它的value属性,如果没有就找text的值
- v-model.lazy 只会在离开焦点时渲染
- v-model.trim 去掉字符串头尾空格
- :value 表单值的动态修改
<div id ="app">
<select v-model ="selected">
<option : value ="{ number : 123 }"> 123</option>
</select>
{{ selec;ted.number }}
</div>
<script>
var app =new Vue ({
el :'#app',
data : {
selected :''
})
</script>
- @input 处理输入框
自定义指令
有如下钩子函数
- bind:只调用一次,可以用在初始化动作
- inserted:被绑定元素插入父节点时调用
- update:被绑定元素所在模板更新时调用
- componentUpdate:被绑定元素所在模板完成一次更新周期时调用
- unbind:只调用一次,指令与元素解绑时调用
每个钩子函数有如下参数
- el 指令绑定的元素
- binding(对象。以下面的demo为例)
- name 指令名 test
- value 指令绑定的值 message的值
- oldValue 执行绑定前一个值
- expression 绑定值的字符串形式 message
- arg 传给指令的参数 msg
- vnode 虚拟节点
- oldVnode 上一个虚拟节点
// test是指令名,message的值就是指令值,
<div v-test:msg.a.b="message"></div>
Vue.directive('test',{
bind:function(el,binding,vnode){}
})
修饰符
它的值可以是一个方法,也可以为空。
<!--阻止冒泡-->
<a @click.stop ="handle"></a>
<!--提交事件不再重新加载-->
<a @submit.prevent ="handle"></a>
<a @click.stop.prevent ="handle"></a>
<!--添加事件侦听器时使用事件捕获模式-->
<div @click.capture ="handle ”> ... </div>
<!--只触发一次-->
<div @click.once ="handle ”> ... </div>
<!--回车时触发-->
<div @key.13 ="handle ”> ... </div>
<!--配置具体的按键。使用方式@keyup.fl-->
Vue.config.keyCodes.fl = 112;
组件
- 关于组件的props类型验证有:String、Number、Boolean、Object、Array、Function。同时支持自定义验证validator:(data)=>{return data>10}
//全局组件声明方式
<div id ="app" >
<my-component maessage="父级"></my-component>
</div>
<script>
var child = {template:'<div>局部</div>'}
Vue.component ('my-component',{
props:['message'],与data return的区别就是,它的值来自于父级,而data的数据是属于它本身。它们的传递是单向的,只能是父到子
template:'<div>test</div>',// template必须由一个html元素包裹
data:()=>{// 与实例的区别就是 组件data必须是函数,而且有返回值
return {...}
}
)}
var app = new Vue({
el :'#app',
components:{'my-component':child} // 局部组件声明方式
})
</script>
- 组件通信
graph TD
子1 --> 子2 --> 子1 -->父--> 子2
- 子组件通过$emit()来触发(创建)自定义组件上的定义事件
- 父组件通过$on()来监听子组件的事件
- $refs在父组件中获取子组件索引集合
- $parent在自定义组件中获取父组件集合
//展示计数结果
<my-component @increase="getTotal"></my-component>
//my-component组件内方法定义
template:'<button @click="handleClick">+l</button>'
methods:{
handleIncrease:()=>{
//在自定义组件内部触发外部定义的increase事件
this.$emit('increase',this.counter)
}
}
//父类实例
var app = new Vue({
methods:{
getTotal:(total){}
}
})
一种总线模式的子父组件通信方式。即在父子的通信通过一个总线bus连接
<component-a></component-a>
//总线
var bus = new Vue();
template:'<button @click="handle"></button>',
methods:{
handle:()=>{
//通过bus触发on-message事件
bus.$emit('on-message','信息')
}
}
mounted:()=>{
//监听on-message事件
bus.$on('on-message',(data)=>{})
}
计算属性
- 处理复杂逻辑处理时,使用计算属性。即将数据与逻辑分开,只返回结果就可以了
- 计算属性可以在多个vue实例中交替使用,当一个实例数据发生变动时,另一个实例将发生变化
- 计算属性具有缓存性,数据发生时,它才会重新取值计算。而不是重新渲染,它就会被计算
var app =new Vue({
computed:{
processText:()=>{} // processText作为返回值,反应到页面中。默认使用getter方法。
fullName:{
get:()=>{},
set:(value)=>{} //app.fullName将调用该处方法
}
}
})
console.log(processText)
生命周期
var app = new Vue({
created:()=>{} //实例创建完成后调用。阶段完成了数据的观测等,但尚未挂载,$el还不可用。需要初始化处理一些数据时会比较有用
mounted:()=>{} //el挂载到实例上后调用,一般我们的第一个业务逻辑会在这里开始
beforeDestroy:()=>{}//实例销毁之前调用
}
slot(插槽)
组件标签内部的内容称为插槽。该插槽定义在组件内容。插槽内容的获取可以使用slots对象。this.slots.default
<child-component>
// slot
<template scope="props"> // props变量,用于获取插槽定义的数据
<p slot="指定内容在插槽显示的位置">父内容</p>
<p>{{props.msg}}</p> // props.msg=子内容
</template>
</child-component>
Vue.component('child-component',{
template:'<div><slot msg="子内容"></slot>
<slot name="指定内容在插槽显示的位置"></slot></div>'
})
vue-router用法
关于使用html5的history路由模式时,webpack-dev-server也需要配置支持该模式webpack-dev-server --open --history-api-fallback --config webpack.config.js
-
安装组件
npm install --save vue-router
-
引入并使用
import VueRouter from 'vue-router'; Vue.use(VueRouter)
-
路由方式
- 静态路径
const Routers =[{ path:'/index', component:(resolve) => require(['./index.vue'],resolve) },{ path:'/user/:id',// :id在user.vue可以使用$route.param.id获取值 component:(resolve) => require(['./user.vue'],resolve) }, ] const RouterConfig ={ mode:'history'//使用html5 history路由模式 routes:Routers } const router = new VueRouter(RouterConfig) new Vue({router:router})
- 路由跳转
<router-link to="调转配置好的静态路由path" tag="渲染时的标签" >
另外,repalce属性会导致无法使用后退;active-class属性会修改默认匹配路由后的class的名称- js代码
this.$router.push('调转配置好的静态路由path') // 执行js时候的跳转 this.$router.replace('调转配置好的静态路由path')// 无法使用后退 this.$router.go(-1) //后退1页
- 导航钩子
针对修改每一个跳转后的title,可以同一使用beforeEach钩子。在离开页面前执行。 跳转后的新页面可以使用afterEach钩子,使页面跳转到顶部。进入页面后执行。
const router = new VueRouter(RouterConfig) router.beforeEach((to,from,next) =>{ to 将进入目标的路由对象 from 当前即将离开的路由对象 next 进入下一个钩子 to和from对象可以通过meta获取信息 })
vuex用法
核心变化是使用了观察者模式,将逻辑代码进行了拆分,同时将变量数据全局化。
安装、引入、启用vuex npm install --save vuex; import VueRouter from 'vuex'; Vue.use(Vuex);
const store = new Vuex.Store({
state:{
count:0,
list:[1,2,3,4,5]
},
// 同步方式,可以些执行逻辑
mutations:{
increment (state,可以扩展基础类型参数/对象){
state.count++;
}
},
// 获取变量get方法
getters:{
filterList:state=>{
return state.list.filter(item=>item>2)
},
//该方法的默认参数有state对象变量本地,getter对象
listCount:(state,getters)=>{
return getters.filterList.length
}
},
actions:{
// context就是store对象
incrementAsyn (context){
context.commit('increment')
}
}
})
new Vue({store:store})
- 在页面中可以直接使用
{{$store.state.count}}
获取值 - 在页面中可以使用
this.$store.commit('increment',传入increment的参数)
increment为vuex中定义的逻辑方法 - 在页面使用
this.$store.getters.filterList
获取过滤后的数组 - 在页面actions块的调用方式是
this.$store.dispath('incrementAsyn')
,另外,可以actions块的逻辑块return promise对象,这样在调用的地方可以自定义回调响应
JavaScript的事件循环机制
调用同步js方法时:
- 生成运行环境(context,含有该方法的作用域、参数、this、引用)
- 发现内部方法,将其同上放入执行栈,返回结果后销毁,回到上一个运行环境
调用含有异步js方法时:
- 生成运行环境
- 发现有异步方法,将其放入一个队列中,并将结果放入一个队列中。主线程继续执行执行中的内容
- 当执行栈执行完毕后,再查找队列中的内容
- 取出排列第一位的事件,将其放入执行栈中
而vue异步更新dom的原理就是监听变量值的改变,将其值放入要给去重的队列中,等待下一个循环刷新队列并执行。$nextTick对象会立刻刷新队列(他的回调函数执行响应)
虚拟节点
- 正常ul li渲染方式:创建一个ul节点,然后将字节点一个一个的渲染出来
- 虚拟节点渲染方式:创建一个虚拟ul节点,再创建li的子节点,然后一次新渲染出来。
手动挂载实例
依靠Vue.extend和$mount两个方法挂载实例
var myComponent = Vue.extend({
template:'<div>{{name}}</div>',
data:()=>{
retrun {name:'test'}
}
})
new myComponent().$mount('#mount-div')
vue对jsx的支持
new Vue(
el:'#app',
render (){
retrun (<h1>test<h1>)
}
})
webpack基础
- 重要也是必选的两项是入口(Entry)和出口(Output)。入口的作用是告诉webpack从哪里开始寻找依赖,并且编译,出口则用来配置编译后的文件存储位置和文件名。
- output.path存放打包后文件的输出目录
- output.publicPath指定资源文件引用目录
- ooutput.filename指定输出文件名称
- module对象的rules可以指定一系列加载器
- module.test 正则表示式。编译过程中遇到的每一个import导入的css文件都用使用css-loader转换,然后style-loader转换
- module.use 编译顺序是从后往前
- plugins是一个定制的插件功能。
- webpack就是一个js文件:webpack.config.js
var ExtractTextPlugin = require('extract-text-webpack-plugin')
var config ={
entry:{
main:'./main'
},
output:{
path:path.join(_driname,'./dist'),
publicPath:'/dist/',
filename:'main.js'
},
module:{
rules:[{
test:/\.css$/,
use:['style-loader','css-loader']
},{
rules:[{
test:/\.css$/,
use:ExtractTextPlugin.extract({
use:'css-loader',
fallback:'style-loader'
})
}]
},
plugins:[new ExtractTextPlugin('mian.css')]
}
module.exports= config;
安装webpack与webpack-dev-server
npm install webpack --save-dev //开发版
npm install webpack-dev-server --save-dev //提供启动一个服务器、热更新、接口dialing等
安装CSS样式加载器
npm install css-loader --save-dev
npm install style-loader --save-dev
安装将所有css合并到一个css的插件
npm install extract-text-webpack-plugin --save-dev
启动webpack-dev-server服务脚本
webpack-dev-server --open --config webpack.config.js
生成环境编译命令
webpack --progress --hide-modules
webpack Vue Demo
- 针对生成环境
新建webpack.prod.config.js
,同时增加"build":"webpack --progress --hide-modules --config webpack.prod.config.js"
- 开发环境的scripts命令
"build":"webpack-dev-server --open --config webpack.config.js"
npm install --save vue
npm install --save-dev vue-loader
npm install --save-dev vue-style-loader
npm install --save-dev vue-template-compiler
npm install --save-dev vue-hot-reload-api
npm install --save-dev babel
npm install --save-dev babel-loader
npm install --save-dev babel-core
npm install --save-dev babel-plugin-transform-runtime
npm install --save-dev babel-preset-es2015
npm install --save-dev babel-runtime
npm install --save-dev url-loader // 文件支持
npm install --save-dev file-loader // 图片支持
npm install --save-dev webpack-merge //打包支持
npm install --save-dev html-webpack-plugin //打包支持
webpack.config.js
module.options是进一步对不同语言进行配置。因为vue的内容含有<template>、<script>、<style>,如果编译含有css就先使用css-loader加载,再使用vue-style-loader加
var path=require('path');
var ExtractTextPlugin=require('extract-text-webpack-plugin');
var config={
entry:{
main:'./main'
},
output:{
path:path.join(_dirname,'./dist'),
publicPath:'/dist/',
filename:'main.js'
},
module:{
rules:[{
test:/\.vue$/,
loader:'vue-1oader',
options:{
loaders:{
css:ExtractTextPlugin.extract({
use:'css-loader',
fallback:'vue-style-loader'
})
}
}
},
{
test:/\.(gif|jpg|png|woff|svg|eot|ttf)\??.*$/,
loader:'url-loader?limit=1024' //小于1kb 使用base64加载
},
{
test:/\.js$/,
loader:'babel-loader',
exclude:/nodemodules/
},
{
test:/\.css$/,
use:ExtractTextPlugin.extract({
use:'css-loader',
fallback:'style-loader'
})
}]
},
plugins:[
newExtractTextPlugin(”main.css”)
]
}
module.exports = config
webpack.prod.config.js
主是将开发环境的配置和生成环境进行合并,即prod是webpack.config.js的扩展
var webpack =require('webpack');
var HtmlwebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var merge = require('webpack-merge');
var webpackBaseConfig =require ('./webpack.config.js');
webpackBaseConfig.plugin=[]
module.exports=merge(webpackBaseConfig,{
output:{
publicPath:'/dist/',
//将入口文件重命名为带有20位hash值的唯一文件,解决线上缓存的问题
filename:'[name].[hash].js'
},
plugins:[
new ExtractTextPlugin({
filename : '[name].[hash].css',
allChunks:true
}),
//定义当前node环境为生产环境
new webpack.DefinePlugin({
'process.env':{
NODE_ENV:'"production"'
}
}),
new webpack.optimize.UglifyJsPlugin({
compress:{
warings:false
}
}),
//提取模板,保存入口html文件
new HtmlwebpackPlugin({
filename:'../index_prod.html',
template:'./index.ejs', //是一个模板文件
inject:false
})
]
})
//index.ejs
<!DOC TYPE html>
<html lang="zh-CN">
<head>
<meta charset ="UTF-8">
<title>webpack App</title>
<link rel="stylesheet" href="<%=htmlwebpackPlugin.files.css[0]%>">
</head>
<body>
<div id ="app"></div>
<script type="text/javascript" src="<%=htmlwebpackPlugin.files.js[0]%>"></script>
</body>
</html>
.babelrc
在webpack同级目录建立.babelrc文件,写入babel配置,webpack会依赖此配置文件来使用babel编译es6代码
{
"presets":["es2015"],
"plugins":["transorm-runtime"],
"comments"false
}
Vue插件机制,可以全局添加一些功能
MyPlugin.install = function(Vue,options){
//全局组件注册
Vue.component('component-name',{})
//添加实例方法
Vue.prototype.$Notice = function(){}
//添加全局方法或属性
Vue.globalMethod = function(){}
//添加全局混合
Vue.mixin({mounted:function(){}})
}
//使用插件
vue.use(myPlugin)
ES6扫盲
data(){} 等同于 data:functoin(){}
h=>h('test') 等同于 function(h){return h('test')} 也等同于 h=>{return h('test')}
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!