Vue2
vue的使用
vue双向绑定
Mvvm
M是数据, V是显示,
Vm是调度者 从m层获取数据 然后给 v层显示,从 v层获得数据 然后给 m层保存
在jquery中是通过抓取dom对象,通过修改dom对象中属性来修改信息,在vue中通过直接操作数据即可改变信息,不用再去抓取dom对象了
new Vue({el:目的地,template:模板内容})
{{ data里的变量 }}
vue指令
v-text 不可解析html标签
v-html 可解析html标签
v-if 做元素的插入(append)和移除(remove)操作
v-else-if
v-else
v-show display:none 和display:block的切换
自定义指令
<div id="app">
<input type="text" v-model="keyword" v-fontsize="1" v-color="yellow"/>
</div>
//定义全局指令
Vue.directive('color',{
//el 为dom对象,binding.value为传进来的yellow
bind:function(el,binding){
el.style.color=binding.value;
},
});
var app=new Vue({
el:'#app',
data:{
list:[
{id:1,name:'lizhiyu',time:new Date()},
{id:2,name:'lizhiyu',time:new Date()},
]
},
methods:{
add(){
this.list.push({id:this.id,name:this.name,time:new Date});
}
},
//自定义组件指令
directives:{
'fontsize':function(el,binding){
el.style.fontSize=parseInt(binding.value)+'px';
}
}
});
vue事件
<div id="app">
//事件都有 keydown keyup click dbclick
<input type="button" value="添加" v-on:click="add"/>
<input type="button" @click="add" value="添加" />
</div>
var app=new Vue({
el:'#app',
data:{
id:''
},
methods:{
add(){
this.list.push({id:this.id,name:this.name,time:new Date});
}
});
vue绑定
<input v-bind:value="name" v-bind:class="name">
//单项绑定 v-bind就是对属性的简单赋值,当内存中值改变,还是会触发重新渲染
<input v-model="name" v-bind:class="name">
//v-model 双向数据绑定(value改变内存中的值也随着改变),v-model只是绑定value属性
vue钩子函数
beforeCreate 数据没有初始化
created 可以操作数据
beforeMount 还未生成DOM
mounted 可以操作DOM
beforeUpdate 可以二次修改
updated 可以获取最终数据
beforeDestroy
destroyed
vue过滤器
全局过滤器Vue.filter(‘过滤器名’,过滤方式fn );
组件内的过滤器 filters:{ ‘过滤器名’,过滤方式fn }
{{ msg | 过滤器名}}
<div id="app">
<p v-fontweight="900" v-fontsize="50">{{msgg|haha('他')|filtera}}</p>
</div>
<script>
//自定义全局过滤器
//第一个是管道前面的数据 ,第二个参数是传过来的 想传几个参数就写几个参数
Vue.filter('haha',function(data,arg){
return data.replace(/我/g,arg);
});
var app=new Vue({
el:'#app',
data:{
},
filters:{//定义私有过滤器 过滤器有两个条件 过滤名称 和 处理函数
filtera(data){
return data+'123';
}
}
}
});
</script>
数据监听watch
<div id="app">
<div>watch监听数据,当下面文本框输入love会提示</div>
<input type="text" name="" v-model='msg.text'>
<div>computed计算属性</div>
(<input type="text" name="" v-model='n1'>+
<input type="text" name="" v-model='n2'>) ={{result}}
</div>
new Vue({
el:'#app',
data(){
return {
msg:{text:''},
n1:'',
n2:''
}
},
computed:{
result(){
return Number(this.n1)+Number(this.n2)
}
},
watch:{
// msg(newval,oldval){
// if(newval.text=='love'){
// alert(newval.text)
// }
// }
msg:{
//每次msg改变都会触发handler方法
handler(newval,oldval){
if(newval.text=='love'){
alert(newval.text)
}
},
//不开启深度监听如果监听的是数组则可能监听不到
deep:true
}
}
})
计算属性 computed
<div id="app">
{{priceInTax}}
</div>
var app=new Vue({
el:'#app',
data:{
price:100,
},
computed:{
priceInTax:function(){
return this.price * 2.00;
}
}
});
vue配套的ajax
axios.get('/user?ID=12345')
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
vue组件
<html>
<head>
<meta charset="UTF-8">
<title></title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="app">
<first-component></first-component>
<!--创建组件时采用驼峰命名privateComponent 在调用组件时将大写字母换成 -小写字母-->
<private-component></private-component>
<ol>
<!--将遍历的所有game数组中的数据item 传入-->
<my-component v-for="item in game" :game="item"></my-component>
</ol>
<button-component></button-component>
<button-component></button-component><br>
</div>
<script>
//定义的第一个全局组件
var firstComponent=Vue.extend({
template:'<h1>这里是第一个组件</h1>'
});
Vue.component('first-component',firstComponent);
//定义的第二个全局组件
Vue.component('my-component',{
// 在标签上传递过来的值
props:['game'],
template:'<li>{{game.title}}</li>'
});
//定义一个button-component组件
var buttonComponent=Vue.extend({
template:'<button @click="add">你点击了{{msg}}次</button>',
//这里的data必须是方法,不能是属性,因为方法是私有的,属性则是公共使用的
data(){
return { msg:'1'}
},
methods:{
add(){
this.msg++;
}
}
});
Vue.component('button-component',buttonComponent);
var app=new Vue({
el:'#app',
data:{
game:[{title:'第一个'},{title:'第二个'},{title:'第三个'}]
},
methods:{
},
components:{
//定义的私有组件
'privateComponent':{
template:'<h1>这里是一个私有组件</h1>'
},
},
});
</script>
</body>
</html>
vue父子传值
父传子
子组件中声明一个props:[‘属性名’],父组件使用组件时传入属性
<html>
<head>
<meta charset="UTF-8">
<title></title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="app">
</div>
<script>
//子组件声明
var children={
//子组件模板
template:'<div>这个是子组件 {{childrenMsg}}</div>',
//子组件接收一个childrenMsg属性
props:['childrenMsg']
};
//父组件
var parent={
//父组件模板
template:`<div>
这个是父组件
<children childrenMsg='父亲传递给子的信息'></children>
</div>`,
//这个组件中包含的组件
components:{
children
}
};
var app=new Vue({
el:'#app',
template:`<div><parent></parent></div>`,
data:{msg:'msg'},
methods:{},
components:{
parent
},});
</script>
</body>
</html>
子传父
子组件方法中调用 this.$emit(‘调用事件’,传递参数)
父组件使用子组件时 声明传值要调用的方法
<children @调用事件=‘要调用的父组件中的方法’> < /children>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="app">
</div>
<script>
//子组件声明
var children={
data(){
return {arg:1};
},
//子组件模板
template:`<div>
这个是子组件
<button @click='clientEvent(arg)' >点击给父组件传数据</button>
</div>`,
methods:{
clientEvent(arg){
//在这里调用父组件上的@sendfather 中指定的方法
this.$emit('sendfather',arg)
}
}
};
//父组件
var parent={
//初始化父组件中的信息
data(){
return {msg:0}
},
//父组件模板
/* <children @sendfather='getChildrenMsg' ></children>
代表 当children组件的方法中调用 this.$emit('sendfather',arg),会调用父组件中的getChildrenMsg方法*/
template:`<div>
这个是父组件的数据{{msg}}
<children @sendfather='getChildrenMsg' ></children>
</div>`,
//这个组件中包含的组件
components:{
children
},
methods:{
getChildrenMsg(arg){
this.msg=arg;
}
}
};
var app=new Vue({
el:'#app',
template:`<div><parent></parent></div>`,
data:{msg:'msg'},
methods:{},
components:{
parent
},});
</script>
</body>
</html>
非父子组件传值(兄弟组件传值)
<html>
<head>
<meta charset="UTF-8">
<title></title>
<script src="js/vue.js"></script>
<!--父组件向子组件中传值-->
</head>
<body>
<div id="app"></div>
<script>
//首先创建一个实例用于绑定监听事件,实例名随便起 这里起名为$bus
Vue.prototype.$bus=new Vue();
var myHead={
template:`<div>这里是头部数据 {{headMsg}}</div>`,
data(){
return {headMsg:'头部数据'};
},
//钩子函数 数据初始换完成时 dom对象还没有初始化时
created(){
//监听$bus对象上的sendMessage事件,如果有调用则触发方法
var self=this;
// this.$bus.$on('sendMessage',function(val){
// this.headMsg=val; 如果这里的this代表的是this.$bus对象,并不是myHead对象
// });
self.$bus.$on('sendMessage',function(val){
self.headMsg=val;
});
}
};
var myBody={
template:`<div>这里是尾部数据
<button @click='sendMsg(bodyMsg)'>向头部传递数据</button>
</div>`,
data(){
return {bodyMsg:'尾部数据'};
},
methods:{
sendMsg(bodyMsg){
//调用$bus实例的 sendMessage方法
this.$bus.$emit('sendMessage',bodyMsg);
}
}
};
var app=new Vue({
el:'#app',
template:`<div><my-head></my-head><my-body></my-body></div>`,
methods:{},
components:{
// myHead和 myBody是兄弟组件
myHead,myBody
},
});
</script>
</body>
</html>
vue中的路由
用于页面跳转
vue-router中的对象:
$route 路由信息对象,只读对象
$router 路由操作对象,只写对象
this.$router.push() 跳转到指定的url,会向history插入新记录
this.$router.replace() 同样是跳转到指定的url,但是这个方法不会向history里面
添加新的记录,点击返回,会跳转到上上一个页面。上一个记录是不存在的。
this.$router.go(-1) 常用来做返回,读history里面的记录后退一个
vue的路由有两种模式,1种是history,1中是hash
history看上局更简洁,使用后期容易出现问题(打包时候、ios兼容问题、后端跳转前端路径问题)
hash使用简单,后期ios兼容问题方便解决
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="js/vue.js"></script>
<script src="vue-router.js"></script>
</head>
<body>
<div id="app">
<!--两种通过路由跳转方式 第一种通过<a href=''></a> 方式跳转
第二种通过<router-link> 进行跳转-->
<a href="#/login">登录</a> | <a href="#/regist">注册</a>
| <router-link to="/login" tag="span">通过 router-link 跳转到登录</router-link> |
<button @click='goTo'>通过方法跳转到登录</button> |
<button @click='goToNoInsertHistory'>跳转到注册,跳转记录不插入history</button> |
<button @click='goBefore'>跳转到history的上一个记录</button>
<!--routerView 是用来显示数据的位置-->
<router-view></router-view>
</div>
<script>
window.onload=function(){
//当通过<a href=''></a> 方式跳转时 vue底层通过这种方式进行切换dom页面元素
window.addEventListener('hashchange', function(e) {
console.log(location.hash)
// switch(location.hash==''){
// dom.innerHTML="";
// }
})
}
var login={
template:'<h1>登录</h1>',
}
var regist={
template:'<h1>注册</h1>',
}
//当导入了vue-router之后 window 全局对象中就有了一个路由构造函数 叫 VueRouter
var routerObj=new VueRouter({//创建路由对象
routes:[//路由匹配规则
//每个路由规则,都是一个对象,这个规则对象身上必须的两个属性:
//1是path 表示监听哪个路由链地址
//2是component 如果路由匹配到path则展示component属性对应的那个组件
{path:'/',redirect:'/login'},
{path:'/login',component:login//component的属性值必须是一个组件模板对象,不能是组件的引用名称
},
{path:'/regist',component:regist}
]
});
var app=new Vue({
el:'#app',
data:{},
methods:{
goTo(){
//跳转
this.$router.push({path:'/login'});
},
goToNoInsertHistory(){
//跳转 同时跳转记录不插入到history中
this.$router.replace({path:'/regist'})
},
goBefore(){
//跳转到上一个页面(history中的上一个页面)
this.$router.go(-1)
}
},
router:routerObj // 将路由规则对象,注册到vm实例上,用来监听url地址变化 然后用来展示对应组件
});
</script>
</body>
</html>
vue路由传值
传递两种参数 1.查询参 2.路由参数
**1.查询参**
router-link标签中配置(传参) :to="{name:'login',query:{id:loginid}}"
组件中获取(取参) this.$route.query.id
**2.路由参数**
router-link标签中配置(传参) :to="{name:'路径',params:{id:registerid}}"
配置路由的规则 { name:'路径',path:'/路径/:id'}
组件中获取(取参) this.$route.params.id
**3.路由参数**
router-link标签中配置(传参) :to="{name:'路径',params:{id:registerid}}"
配置路由的规则 { name:'路径',path:'/路径/:id',props:true}
在组件中声明 props:['id(这里的id指的是参数名)']
组件中获取(取参) 直接使用参数{{id}} 因为在路由中配置了props:true
总结:
:to传参的属性里 params是和name配对的 query和name或path都可以
(使用params传参,router-link必须通过name跳转)
使用路由参数必须要配置路由规则里面配置好参数名,否则刷新页面参数会丢失
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="js/vue.js"></script>
<script src="vue-router.js"></script>
</head>
<body>
<div id="app">
<!--路由中查询参参数传递 必须使用query参数-->
<router-link :to="{name:'login',query:{id:'这个是路由跳转传递的参数'}}" tag="span">登录</router-link> |
<!--路由中参数传递-->
<router-link :to="{name:'regist',params:{arg:'这个是路由跳转传递的参数'}}" tag="span">注册</router-link> |
<router-link :to="{name:'test',params:{arg2:'这个是路由跳转传递的参数'}}" tag="span">测试</router-link>
<!--routerView 是用来显示数据的位置-->
<router-view></router-view>
</div>
<script>
var login={
template:'<h1>登录 {{msg}}</h1>',
data(){
return {msg:''};
},
created(){
//在组件中接收路由跳转的查询参
this.msg=this.$route.query.id;
}
}
var regist={
template:'<h1>注册 {{arg}}</h1>',
data(){
return {arg:''};
},
created(){
//在组件中接收参数
this.arg=this.$route.params.arg;
}
}
var test={
template:'<h1>test {{arg2}}</h1>',
//在组件中接收参数 但是在路由中要设置 props:true 才可以这样接收
props:['arg2']
}
//创建路由对象
var routerObj=new VueRouter({
//路由匹配规则
routes:[
{path:'/',redirect:'/login'},
{path:'/login',name:'login',component:login},
{path:'/regist/:arg',name:'regist',component:regist},
{path:'/test/:arg2',name:'test',props:true,component:test}
]
});
var app=new Vue({
el:'#app',
data:{},
methods:{
},
router:routerObj // 将路由规则对象,注册到vm实例上,用来监听url地址变化 然后用来展示对应组件
});
</script>
</body>
</html>
vue路由嵌套
路由跳转问题:
当路由跳转时,页面path没有改变但是传递参数改变了,页面上参数没有随着参数的改变而改变
解决方案:<router-view :key="$route.fullPath"></router-view>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="js/vue.js"></script>
<script src="vue-router.js"></script>
</head>
<body>
<div id="app">
<router-link to="/account">账户</router-link>
<router-view></router-view>
</div>
<template id="temp">
<div>
<router-link to="/account/login">登录</router-link>
<router-link to="/account/regist">注册</router-link>
<router-view></router-view>
</div>
</template>
<script>
var login={
template:'<h1>登录</h1>',
}
var regist={
template:'<h1>注册</h1>',
}
var account={
template:'#temp',
}
var router=new VueRouter({
routes:[
{
path:'/account',
component:account,
/*为什么子路由的path前没有/ 因为这样会在根目录匹配路径*/
/*使用children属性实现子路由同时path前面不要带/*/
children:[
{path:'regist',component:regist},
{path:'login',component:login},
],
}
],
});
var app=new Vue({
el:'#app',
data:{},
methods:{},
router,
});
</script>
</body>
</html>
require 使用说明
在模块化开发中,可以通过require异步加载组件(提交加载速度)
使用步骤如下
1、Load JavaScript Files 引入require.js文件
2、Define a Module 定义一个模块
3、import Define Module 导入定义的模块
webpack 使用说明
webpack主要用于将项目打包(html、css、js、img分别打包成想要的样子)
1、安装webpack和 webpack-cli
2、书写配置文件webpack.config.js
通过npm init 命令自动创建package.json
3、进行打包测试 webpack
4、为了webpack能够加载css文件,安装style-loader、css-loader、sass-loader
5、在webpack.config.js中配置这三个加载css的模块
6、打包测试
7、安装热部署插件(webpack-dev-server)
8、然后通过热部署插件启动
css 处理语言
css处理语言主要包括如下三种 less、sass、stylus他们的目的主要是为了将css的使用像js中的方法那样可以复用
webpack引入css处理语言
也可以安装file-loader1
url-loader
在打包时候对图片进行base64处理
//运行时依赖
"dependencies": {
"css-loader": "^5.1.1",
"html-webpack-plugin": "^5.2.0",
"sass-loader": "^11.0.1",
"style-loader": "^2.0.0",
"webpack": "^5.24.2",
"webpack-cli": "^4.5.0"
},
//开发时依赖
"devDependencies": {},
babel-loader
babel主要用于,webpack打包时候将es6转换成es5,es6有些浏览器不支持
安装
rules: [
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
//presets: ['@babel/preset-env'] 如果配置成这样会去项目中寻找babel.config.js的配置文件
presets: ['es2015']
}
}
}
]
vue-cli2和vue-cli3区别
vue-cli2
使用webpack 3 进行打包、
能看到少数webpack配置
vue-cli3
使用webpack 4 进行打包、
实现webpack零配置(移除build和config文件夹)、
实现一个vue ui来管理项目插件、
移除static文件夹,使用public文件夹代替
vue脚手架 vue-cli2安装项目
安装前准备
1.安装node
命令行输入node -v查询版本号,有版本号即安装成功
2.node自带npm包管理工具(安装好node也可以输入npm -v查看版本号)
npm太慢
3.下载国内淘宝镜像cnpm
(npm install -g cnpm --registry=https://registry.npm.taobao.org)
或者
修改npm的资源镜像链接
npm config set registry http://registry.npm.taobao.org
4.安装webpack
运行npm install webpack -g 或 cnpm install webpack -g
5.1安装vue-cli 2.x
npm install vue-cli -g
5.2安装vue-cli 3.x
npm install @vue/cli -g
执行命令 vue init webpack vue-study
安装项目
? Project name vue-study
? Project description 一个vue项目
? Author lizhiyu
? Vue build standalone
? Vue build (Use arrow keys)
Runtime + Compiler: recommended for most users(这个功能全,但是速度慢,初学建议使用这个)
Runtime Only(这个速度快,体积小)
这两者的区别在于创建项目的main.js不同,导入模板的方式不同Runtime Only后期使用可能有些问题
? Install vue-router? No
? Use ESLint to lint your code? Yes
? Pick an ESLint preset Standard
? Set up unit tests No
? Setup e2e tests with Nightwatch? No
? Should we run `npm install` for you after the project has been created? (recommended) npm
package.json
信息如下
"scripts": {
"dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js", //通过webpack-dev-server 启动
"start": "npm run dev", //执行上面的命令
"lint": "eslint --ext .js,.vue src",//测试eslint是否编译通过
"build": "node build/build.js"//通过node执行build.js
},
build.js
主要信息如下
const webpackConfig = require('./webpack.prod.conf')
//删除上次打包好的配置
rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
if (err) throw err
//根据生产配置文件进行打包
webpack(webpackConfig, (err, stats) => {
process.stdout.write(stats.toString({
colors: true,
modules: false,
children: false, // If you are using ts-loader, setting this to true will make TypeScript errors show up during build.
chunks: false,
chunkModules: false
}) + '\n\n')
})
})
vue脚手架 vue-cli3
vue-cli是一个脚手架工具,为我们搭建了开发所需要的环境和生成目录架构
vue-cli 安装和打包
npm uninstall -g vue-cli //卸载脚手架2
npm install @vue/cli -g //安装3
创建项目:vue create 项目名(不要取中文名字)
安装选择如下:
Please pick a preset: 选择当前要安装的
Manually select features 手动选择
(*) Choose Vue version 选择vue的版本,选vue2
(*) Babel 用于es5和es6转换的插件
( ) TypeScript
( ) Progressive Web App (PWA) Support
(*) Router 路由
(*) Vuex 状态管理
>(*) CSS Pre-processors css预处理
(*) Linter / Formatter elsint代码格式
( ) Unit Testing
( ) E2E Testing
Use history mode for router? n //history精通可以使用
Pick a CSS pre-processor 选Stylus,ui库中如果使用cube-ui就要选择个
Pick a linter / formatter config: 选ESLint + Standard config,标准的格式
Pick additional lint features:>(*) Lint on save 在保存时候eslint进行校验
? Where do you prefer placing config for Babel, ESLint, etc.?
> In dedicated config files 将配置文件分别存放到不同目录下
启动创建好的项目 cnpm run serve 运行项目
访问项目 浏览器中访问http://localhost:8080/
开发项目
打包 cnpm run build 进行打包
vue-cli 3.0配置
在 vue.config.js 文件中配置,每次修改配置要重启才生效
module.exports = {
publicPath: process.env.NODE_ENV === 'production' ? '/public/' : './',
/* 输出文件目录:在npm run build时,生成文件的目录名称 */
outputDir: 'dist',
/* 放置生成的静态资源 (js、css、img、fonts) 的 (相对于 outputDir 的) 目录 */
assetsDir: "assets",
/* 是否在构建生产包时生成 sourceMap 文件,false将提高构建速度 */
productionSourceMap: false,
/* 默认情况下,生成的静态资源在它们的文件名中包含了 hash 以便更好的控制缓存,你可以通过将这个选项设为 false 来关闭文件名哈希。(false的时候就是让原来的文件名不改变) */
filenameHashing: false,
/* 代码保存时进行eslint检测 */
lintOnSave: true,
/* webpack-dev-server 相关配置 */
devServer: {
/* 自动打开浏览器 */
open: true,
/* 设置为0.0.0.0则所有的地址均能访问 */
host: '0.0.0.0',
port: 8066,
https: false
},
}
VueX
VueX能做什么
当多个组件使用同一个数据的时候,由于数据不能共享,引入vuex来解决问题
当不存在vuex时,将数据定义在父组件,通过父组件传递给要使用数据的子组件
结构
图解
使用
安装vuex
Vue 创建项目
- cmd 执行命令 vue ui
- 创建项目时要安装如下组件
Bable
Router 路由
Vuex 状态管理工具
linter/Formatter 代码提示
配置文件 - 不使用history mode for router
- 安装Element-ui插件
- 在依赖中安装axios
- 将代码上传到github
在 github 上创建仓库,然后来到项目目录下进行推送代码
7. 代码开发
首先看自己所在分支 git status
创建一个分支 git branch login
切换分支 git checkout login (本地有没有提交的代码,则需要加 git checkout -f login 强制切换分支,这样没有提交的代码会丢失)
查看分支 git branch
8. 项目启动
在任务中运行serve 编译成功后启动app
- 删除没有必要的文件,代码结构说明
main.js 是最主要的入口文件