如何为成都的专业手机网站建设和推广创建一个有效的WordPress菜单文件?
摘要:成都专业手机网站建设推广,wordpress菜单文件,营销软件网站,网站建设的市场需求1.介绍及安装 1.1 介绍 Vue是一套构建用户界面的渐进式框架。Vue只关注视图层,采用自底向上增量开发的设计。Vue的
成都专业手机网站建设推广,wordpress菜单文件,营销软件网站,网站建设的市场需求1.介绍及安装
1.1 介绍
Vue是一套构建用户界面的渐进式框架。Vue只关注视图层#xff0c;采用自底向上增量开发的设计。Vue的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件。
学习vue之前主要掌握的知识#xff1a;HTML、CSS、JavaScript、TypeScript
…1.介绍及安装
1.1 介绍
Vue是一套构建用户界面的渐进式框架。Vue只关注视图层采用自底向上增量开发的设计。Vue的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件。
学习vue之前主要掌握的知识HTML、CSS、JavaScript、TypeScript
兼容性说明Vue 不支持 IE8 及其以下版本因为 Vue 使用了 IE8 不能模拟的 ECMAScript 5 特性。但它支持所有兼容 ECMAScript 5 的浏览器。
1.2 安装
1.2.1 安装NodeJS
官网地址下载安装 Download | Node.js
1.2.2 安装npm
npm是随同NodeJS一起安装的包管理工具安装nodejs后就无需安装但是npm速度会慢一些推荐使用淘宝镜像及其命令cnpm使用如下命令安装淘宝镜像 npm install -g cnpm --registryhttps://registry.npmmirror.com cnpm -v 查看安装的淘宝镜像版本
1.2.3 安装vue
执行如下命令安装vue的最新稳定版本 npm install vue 安装指定版本的vue npm install vue版本号 比如要安装2.6.12版本的vue,执行命令 npm install vue2.6.12
1.2.4 安装vue命令行工具(CLI) npm install --global vue-cli 详细使用说明参见介绍 | Vue CLI
1.3 项目实例
1.3.1 项目创建
cmd cd命令到需要创建项目的目录下执行 vue create 项目名称 创建vue项目
在F磁盘下myVue文件夹下创建项目名称为bookmanage
注项目名称不能包含大写字母 回车默认Vue2项目模板然后回车等待项目初始化完成 使用VSCode打开项目 执行命令npm run serve,运行项目 文件目录说明
node_modules项目依赖文件夹public一般放置一些静态资源图片需要注意放在public文件夹中的静态资源webpack进行打包的时候会原封不动打包到dist文件夹中。src程序员源代码文件夹 asstes一般也是放置静态资源一般放置多个组件共用的静态资源需要注意放置在asstes文件夹里面的静态资源在webpack打包的时候webpack会把静态资源当作一个模块打包到js文件里面。 components一般放置非路由组件全局组件 App.vue唯一的根组件 main.js程序入口文件也是整个程序当中最先执行的文件babel.config.js配置文件babel相关package.json记录项目做什么有哪些依赖、项目怎么运行package-lock.json缓存性文件
1.3.2 CLI服务命令
在一个 Vue CLI 项目中vue/cli-service 安装了一个名为 vue-cli-service 的命令。你可以在 npm scripts 中以 vue-cli-service、或者从终端中以 ./node_modules/.bin/vue-cli-service 访问这个命令。 这是你使用默认 preset 的项目的 package.json 你可以通过 npm 或 Yarn 调用这些 script
npm run serve
# OR
yarn serve 1.3.2.1 vue-cli-service serve 用法vue-cli-service serve [options] [entry] 选项 --open 在服务器启动时打开浏览器 --copy 在服务器启动时将 URL 复制到剪切版 --mode 指定环境模式 (默认值development) --host 指定 host (默认值0.0.0.0) --port 指定 port (默认值8080) --https 使用 https (默认值false) vue-cli-service serve 命令会启动一个开发服务器 (基于 webpack-dev-server) 并附带开箱即用的模块热重载 (Hot-Module-Replacement)。 除了通过命令行参数你也可以使用 vue.config.js 里的 devServer 字段配置开发服务器。 命令行参数 [entry] 将被指定为唯一入口 (默认值src/main.jsTypeScript 项目则为 src/main.ts)而非额外的追加入口。尝试使用 [entry] 覆盖 config.pages 中的 entry 将可能引发错误
1.3.2.2 vue-cli-service build 用法vue-cli-service build [options] [entry|pattern] 选项 --mode 指定环境模式 (默认值production) --dest 指定输出目录 (默认值dist) --modern 面向现代浏览器带自动回退地构建应用 --target app | lib | wc | wc-async (默认值app) --name 库或 Web Components 模式下的名字 (默认值package.json 中的 name 字段或入口文件名) --no-clean 在构建项目之前不清除目标目录的内容 --report 生成 report.html 以帮助分析包内容 --report-json 生成 report.json 以帮助分析包内容 --watch 监听文件变化 vue-cli-service build 会在 dist/ 目录产生一个可用于生产环境的包带有 JS/CSS/HTML 的压缩和为更好的缓存而做的自动的 vendor chunk splitting。它的 chunk manifest 会内联在 HTML 里。 这里还有一些有用的命令参数
--modern 使用现代模式构建应用为现代浏览器交付原生支持的 ES2015 代码并生成一个兼容老浏览器的包用来自动回退。--target 允许你将项目中的任何组件以一个库或 Web Components 组件的方式进行构建。更多细节请查阅构建目标。--report 和 --report-json 会根据构建统计生成报告它会帮助你分析包中包含的模块们的大小。
1.3.2.3 vue-cli-service inspect 用法vue-cli-service inspect [options] [...paths] 选项 --mode 指定环境模式 (默认值development) 你可以使用 vue-cli-service inspect 来审查一个 Vue CLI 项目的 webpack config。
1.3.2.4 缓存和并行处理
cache-loader 会默认为 Vue/Babel/TypeScript 编译开启。文件会缓存在 node_modules/.cache 中——如果你遇到了编译方面的问题记得先删掉缓存目录之后再试试看。thread-loader 会在多核 CPU 的机器上为 Babel/TypeScript 转译开启。
1.3.3 开发基础配置
1.3.3.1 vue.config.js
vue.config.js是vue项目的配置文件专注于vue项目。使用脚手架安装项目的时候并没有创建vue.config.js所有一般是需要修改webpack的时候才会自己创建一个vue.config.js,然后就可以修改默认的webpack。
配置说明参见https://cli.vuejs.org/zh/guide/webpack.html
module.exports {lintOnSave: true, // 关闭eslint 默认是trueproductionSourceMap: false, // 不需要生产时的源映射(即.js.map文件不会生成) 默认是true// 部署应用包时的基本URL。 默认是/ 。如应用被部署在 https://www.my-app.com/my-app/则设置publicPath为/my-app/publicPath: process.env.NODE_ENV production ? / : /, // ./是当前目录 ; /是根目录outputDir: dist, // 默认dist 所以这句可以注释掉 assetsDir: static,// 项目打包的静态资源存放目录默认 staticindexPath: index.html,// 项目打包的index.html输出路径默认 index.htmlpages: undefined,// 多页应用配置参数默认 undefined// 配置代理跨域devServer: {open: true, //启动项目自动弹出浏览器port: 5200, // 开发运行时的端口https: false, // 是否启用 httpshost: 0.0.0.0, // 默认localhost 设置成0.0.0.0,在同一个局域网下可以通过http://ip:port/...访问项目proxy: { // 拦截所有api开头的请求请求时删除api根据自己实际情况来^/api/.*: {target: http://127.0.0.1:8090, // 服务器接口地址changeOrigin: true, // 是否跨域 rewrite: (path) path.replace(/^\/api/, ),}}},// css全局配置 参见 https://cli.vuejs.org/zh/guide/css.html#css-modules//特别说明配置前先安装好需要的依赖;如“sass-loader”: “^10.2.0”, “scss”: “^0.2.4”,安装的如果版本不一致会有报错 参见 https://www.npmjs.com/package/node-sass 查看nodejs与node-sass对应版本//如果使用scss/sass设置那么需要在每个vue文件中需要这样写style langscss/style 全局样式才会生效/*** sass-loader与node-sass对应版本号* sass-loader 4.1.1node-sass 4.3.0sass-loader 7.0.3node-sass 4.7.2sass-loader 7.3.1node-sass 4.7.2sass-loader 7.3.1node-sass 4.14.1sass-loader 10.0.1node-sass 6.0.1*/css: {// 是否将组件中的 CSS 提取至一个独立的 CSS 文件中、生产环境下默认 true开发环境下默认 falseextract: true,// 是否开启 css 的 source map 调试默认 falsesourceMap: false,//向 CSS 相关的 loader 传递选项(支持 css-loader postcss-loader sass-loader less-loader stylus-loader) 默认{}loaderOptions: { scss:{// v8 以前的写法 data: import /assets/css/index.scss;, // v8 以后的写法prependData: import /assets/css/index.scss;, // v10 以后的写法additionalData: import /assets/css/common.scss;// v8中这个选项名是 prependData},// sass:{// additionalData: import /assets/css/common.scss;// v8中这个选项名是 prependData// }}},//新增/修改 webpack 的 plugins 或者rules 的简单配置方式使用configureWebpack//参见 https://cli.vuejs.org/zh/guide/webpack.htmlconfigureWebpack:config{console.log(config);if(process.env.NODE_ENVdevelopment){//开发换进改配置}else if(process.env.NODE_ENVtest){//测试环境配置}else if(process.env.NODE_ENVproduction){//生产环境配置}},//新增/修改 webpack 的 plugins 或者rules 的链式操作 (高级)方式使用chainWebpack//参见 https://cli.vuejs.org/zh/guide/webpack.htmlchainWebpack: config {config.module.rule(vue).use(vue-loader).tap(options {// 修改它的选项...return options;});}
}
1.3.3.2 模式和环境变量
模式
模式是 Vue CLI 项目中一个重要的概念。默认情况下一个 Vue CLI 项目有三个模式
development 模式用于 vue-cli-service servetest 模式用于 vue-cli-service test:unitproduction 模式用于 vue-cli-service build 和 vue-cli-service test:e2e
你可以通过传递 --mode 选项参数为命令行覆写默认的模式。例如如果你想要在构建命令中使用开发环境变量 vue-cli-service build --mode development 当运行 vue-cli-service 命令时所有的环境变量都从对应的环境文件中载入。如果文件内部不包含 NODE_ENV 变量它的值将取决于模式例如在 production 模式下被设置为 production在 test 模式下被设置为 test默认则是 development。
NODE_ENV 将决定您的应用运行的模式是开发生产还是测试因此也决定了创建哪种 webpack 配置。
例如通过将 NODE_ENV 设置为 testVue CLI 会创建一个优化过后的并且旨在用于单元测试的 webpack 配置它并不会处理图片以及一些对单元测试非必需的其他资源。
同理NODE_ENVdevelopment 创建一个 webpack 配置该配置启用热更新不会对资源进行 hash 也不会打出 vendor bundles目的是为了在开发的时候能够快速重新构建。
当你运行 vue-cli-service build 命令时无论你要部署到哪个环境应该始终把 NODE_ENV 设置为 production 来获取可用于部署的应用程序。 NODE_ENV 如果在环境中有默认的 NODE_ENV你应该移除它或在运行 vue-cli-service 命令的时候明确地设置 NODE_ENV。 环境变量
你可以在你的项目根目录中放置下列文件来指定环境变量 .env # 在所有的环境中被载入 .env.local # 在所有的环境中被载入但会被 git 忽略 .env.[mode] # 只在指定的模式中被载入 .env.[mode].local # 只在指定的模式中被载入但会被 git 忽略 一个环境文件只包含环境变量的“键值”对 FOObar VUE_APP_NOT_SECRET_CODEsome_value 警告 不要在你的应用程序中存储任何机密信息例如私有 API 密钥 环境变量会随着构建打包嵌入到输出代码意味着任何人都有机会能够看到它。 请注意只有 NODE_ENVBASE_URL 和以 VUE_APP_ 开头的变量将通过 webpack.DefinePlugin 静态地嵌入到客户端侧的代码中。这是为了避免意外公开机器上可能具有相同名称的私钥。
想要了解解析环境文件规则的细节请参考 dotenv。我们也使用 dotenv-expand 来实现变量扩展 (Vue CLI 3.5 支持)。例如 FOOfoo BARbar CONCAT$FOO$BAR # CONCATfoobar 被载入的变量将会对 vue-cli-service 的所有命令、插件和依赖可用。 环境文件加载优先级 为一个特定模式准备的环境文件 (例如 .env.production) 将会比一般的环境文件 (例如 .env) 拥有更高的优先级。 此外Vue CLI 启动时已经存在的环境变量拥有最高优先级并不会被 .env 文件覆写。 .env 环境文件是通过运行 vue-cli-service 命令载入的因此环境文件发生变化你需要重启服务。 模式和环境变量配置示例 在实际开发过程中我们可能需要开发环境、测试环境和生产环境对应三个不同环境的地址这里我们在项目根目录中新增.env、.env.development、.env.test、.env.production三个文件分别对应所有环境、开发、测试、生产不同模式下的环境变量配置
.env NODE_ENVdevelopment VUE_APP_API_URL http://127.0.0.1:8080/ // 开发接口域 .env.development NODE_ENVdevelopment VUE_APP_API_URL http://127.0.0.1:8080/ // 开发接口域 .env.test NODE_ENVtest VUE_APP_API_URL http://127.0.0.1:8089/ // 开发接口域 .env.production NODE_ENVproduction VUE_APP_API_URL http://127.0.0.1:9095/ // 开发接口域 然后在package.json中的scrips中配置service命令 分别执行 npm run serve 和npm run test命令页面中显示process.env.NODE_ENV值的效果 1.3.3.3 路由基础配置
Vue路由是指根据url分配到对应的处理程序作用就是解析URL调用对应的控制器的方法并传递参数。Vue路由有助于在浏览器的URL或历史记录与Vue组件之间建立链接从而允许某些路径渲染与之关联的任何一个视图。 $route一般获取路由信息【路径、query、params等等】 $router一般进行编程式导航进行路由跳转【push|replace】 项目中创建router.js文件创建路径src/router/router.js
import Vue from vue;//引入vue
import VueRouter from vue-router;//引入vue-routerVue.use(VueRouter)//第三方库需要use一下才能用//定义routes路由的集合数组类型
//路由懒加载 当打包构建应用时JavaScript包会变得非常大影响页面加载。如果能把不同路由对应的组件分割成不同的代码块然后当路由被访问的时候才加载对应组件。
const routes [//路由配置
// { path: /login, component: () import(/views/login/index.vue)},
// { path: /index, component: () import(/views/home/index.vue)}
];//实例化 VueRouter 并将 routes 添加进去
const router new VueRouter({//ES6简写等于routesroutesroutes
});//抛出这个这个实例对象方便外部读取以及访问
export default router;
然后在main.js中引入路由js文件
import Vue from vue
import App from ./App.vue
import router from ./router/router.js//引用router.jsVue.config.productionTip falsenew Vue({router,render: h h(App),
}).$mount(#app)
1.3.3.4 全局样式设置
样式文件包含sass、scss、css、less等全局样式的设置方式如下 1main.js中引入 import /assets/css/common.scss // 全局样式 2vue.config.js 中配置 详情参见 1.3.3.1 vue.config.js中的关于全局css配置的相关注释说明及代码 2.基础知识汇总
2.1 应用实例
每个 Vue 应用都是通过用 Vue 函数创建一个新的 Vue 实例开始的
import Vue from vue//引入vuevar vm new Vue({// 选项
})
选项参数包含根组件、路由等的配置我们可以在入口程序main.js中的代码中看出在vue实例中调用根组件App.vue,根组件中调用子组件
main.js中的代码 根组件App.Vue中的代码 2.1.1 生命周期
每个 Vue 实例在被创建时都要经过一系列的初始化过程——例如需要设置数据监听、编译模板、将实例挂载到 DOM 并在数据变化时更新 DOM 等。同时在这个过程中也会运行一些叫做生命周期钩子的函数 挂载阶段beforeCreate、created、beforeMount、mounted
更新阶段beforeUpdate、updated
销毁阶段beforeDestroy、destroyed
beforeCreate在该函数执行时Vue实例仅仅完成自身事件绑定和生命周期函数的初始化工作Vue实例中还没有Dataelmethods相关属性created在该函数执行时Vue实例已经初始化data属性和methods中相关方法可以在此阶段调取后端数据了beforeMount在该函数进行模板编译生成虚拟dommounted在该函数将数据渲染到页面上生成真实dombeforeUpdate数据更新时触发该函数该函数执行时Vue实例中data数据变化但页面数据仍为旧数据即data数据与页面数据不同步updated数据更新触发但时机点位于beforeUpdated后此时页面数据与Vue实例中data数据能够保持一致beforeDestroy该函数执行时Vue实例中所有数据、methods、component还未销毁destroyed该函数执行时Vue实例彻底销毁
钩子函数常见的使用场景 1推荐在created中发送请求对服务端接口进行调用此时data数据已经创建可以获取服务端数据对其进行赋值相比beforeMount和mounted(),created能更快获取到服务端数据减少页面loading 时间
2在 mounted中Vue将编译好的模板挂在到页面上此时为真实DOM可以对DOM进行操作。此时可以做启动定时器、绑定自定义事件、订阅消息等初始化操作。
3beforeDestory可进行清除定时器、解绑自定义事件、取消消息订阅等操作
2.2 模板语法
Vue 使用了基于 HTML 的模板语法允许开发者声明式地将 DOM 绑定至底层 Vue 实例的数据。 Vue的核心是一个允许你采用简洁的模板语法来声明式的将数据渲染进 DOM 的系统。 结合响应系统在应用状态改变时 Vue 能够智能地计算出重新渲染组件的最小代价并应用到 DOM 操作上。
2.2.1 插值
2.2.1.1 文本
数据绑定最常见的形式就是使用 {{...}}双大括号的文本插值
通过使用v-once指令你也能执行一次性地插值当数据改变时插值处的内容不会更新。但请留心这会影响到该节点上的其它数据绑定
templatedivh1{{title}}/h1p v-once{{titleOnce}}/pbutton clickchangeOnce改变v-once指令绑定的数据/button/div
/template
script
export default {name: example1,//数据data(){return {title:欢迎来到vue2的世界,titleOnce:使用v-once指令你也能执行一次性地插值当数据改变时插值处的内容不会更新}},methods:{changeOnce(){this.titleOnce使用v-once指令;console.log(this.titleOnce);}}
}
/script
style scoped
h1 {color: red;
}
/style页面输出效果 2.2.1.2 纯HTML
双大括号将会将数据插值为纯文本而不是 HTML。若想插入 HTML你需要使用v-html指令
templatedivh2HTML/h2div v-htmlhtmlTxt/div /div
/template
script
export default {name: example1,//数据data(){return {htmlTxt:p你好v-html/pp这是一个纯html的插值语句/p}},methods:{}
}
/script
style scoped/style页面输出效果 2.2.1.3 属性
双大括号不能在 HTML attributes 中使用相应的应该使用v-bind指令
注v-bind可省略不写直接:属性值比如绑定id可以这样写:iddynamicId
templatediv!-- v-bind 绑定id 如果绑定的值是null或者undefined那么该 attribute 将会从渲染的元素上移除--div v-bind:iddynamicId v-htmlhtmlTxt/div!-- 布尔值的属性绑定比如disabled 如果 isButtonDisabled 的值是 null、undefined 或 false则 disabled attribute 甚至不会被包含在渲染出来的 button 元素中--button v-bind:disabledisDisableddisabled绑定/button!-- 动态绑定多个值 --div v-bindmultiAttr动态绑定多个值/div/div
/template
script
export default {name: example1,//数据data(){return {dynamicId:div2,isDisabled:true,htmlTxt:p你好v-html/pp这是一个纯html的插值语句/p,multiAttr:{id:divMulti,style:font-size:50px,class:txt1}}},methods:{}
}
/script
style scoped
h1 {color: red;
}
/style2.2.1.4 表达式
对于所有的数据绑定Vue都提供了完全的 JavaScript 表达式支持
在 Vue 模板内JavaScript 表达式可以被使用在如下场景上
在文本插值中双大括号。在任何 Vue 指令attribute以v-开头的特殊 attribute的值中。
表达式会被作为 JavaScript 以组件为作用域解析执行
templatediv!--数字计算--div当前数值是{{num1}}/div!--三元运算符--div当前状态是否ok{{isOk?是:否}}/div!--split--div姓氏{{message.split().join( )}}/div!-- 模板语句--div :idlist-${id}动态绑定id/div/div
/template
script
export default {name: example1,//数据data(){return {num:15,isOk:true,message:赵钱孙李,id:1}},methods:{}
}
/script
style scoped/style
运行输出结果 在绑定的表达式中可以使用一个组件暴露的方法调用函数
绑定在表达式中的方法在组件每次更新时都会被重新调用因此不应该产生任何effect副作用。比如改变数据或触发异步操作。
templatediv!--绑定的表达式中调用函数--span :titletoTitleDate(){{dateToStr()}}/span/div
/template
script
export default {name: example1,//数据data(){return {currDate:new Date()}},methods:{toTitleDate(){return this.currDate.toString();},dateToStr(){return this.currDate.getFullYear()年(this.currDate.getMonth()1)月this.currDate.getDate()日;}}
}
/script
style scoped/style
运行效果 注意事项 1在绑定的表达式中不支持语句 以下写法都是无效的 !-- 这是一个语句而非表达式 --
{{ var a 1 }}
!-- 条件控制同样不会工作请使用三元表达式 --
{{ if (ok) { return message } }} 2受限的全局访问 模板中的表达式将被沙盒化仅能够访问到有限的全局对象列表。该列表中会暴露常用的内置全局对象比如Math和Date。 没有显式包含在列表中的全局对象将不能在模板内表达式中访问。例如用户附加在window上的 property。然而你也可以自行在app.config.globalProperties上显式地添加他们供所有的 Vue 表达式使用。 2.2.2 指令
指令是带有v-前缀的特殊 attribute。指令 attribute 的期望值为一个 JavaScript 表达式v-for、v-on和v-slot将会是例外。使用指令是为了在其表达式值变化时响应式的更新 DOM。
以v-if为例
templatediv!--v-ifv-if 指令将根据表达式 seen 的值(true 或 false )来决定是否插入span元素--span v-ifseenv-if指令/span/div
/template
script
export default {name: example1,//数据data(){return {seen:true}},methods:{}
}
/script
style scoped/style
2.2.2.1 参数
一些指令能够接收一个“参数”在指令名称之后以:冒号隔开做标识。例如v-bind指令可以用于响应式地更新 HTML attribute
a v-bind:hrefurl ... /a
!-- 缩写 --
a :hrefurl ... /a
这里href就是一个参数它告诉v-bind指令将表达式url的值绑定到元素的href attribute 上。在缩写中参数前的一切例如v-bind:都会被缩略为一个:字符。
另一个例子是v-on指令它用于监听 DOM 事件
a v-on:clickdoSomething ... /a
!-- 缩写 --
a clickdoSomething ... /a
这里的参数是要监听的事件名称click。v-on也是少部分含有缩写的指令之一缩写字符为
2.2.2.2 动态参数
从 2.6.0 开始可以用方括号括起来的 JavaScript 表达式作为一个指令的参数 !--注意参数表达式有一些约束参见下面“动态参数表达式约束”一节的解释。-- a v-bind:[attributeName]url ... /a !-- 缩写 -- a :[attributeName]url ... /a 这里的attributeName会被作为一个 JavaScript 表达式进行动态求值求得的值将会作为最终的参数来使用。例如如果你的组件实例有一个data property attributeName其值为href那么这个绑定将等价于v-bind:href。 同样地你可以使用动态参数为一个动态的事件名绑定处理函数 a v-on:[eventName]doSomething ... /a !-- 缩写 -- a [eventName]doSomething 在这个示例中当eventName的值为focus时v-on:[eventName]将等价于v-on:focus 动态参数值限制动态参数预期会求出一个字符串异常情况下值为 null。这个特殊的 null 值可以被显性地用于移除绑定。任何其它非字符串类型的值都将会触发一个警告
动态参数表达式限制
动态参数表达式因为某些字符的缘故有一些语法限制比如空格和引号在 HTML attribute 名称中都是不合法的。例如下面的示例 !-- 这会触发一个编译器警告 -- a :[foo bar]value ... /a 如果你需要传入一个复杂的动态参数我们推荐使用计算属性替换复杂的表达式
当使用DOM 内嵌模板直接写在 HTML 文件里的模板时我们需要避免在名称中使用大写字母因为浏览器会强制将其转换为小写 !-- 在 DOM 中使用模板时这段代码会被转换为 v-bind:[someattr]。 除非在实例中有一个名为“someattr”的 property否则代码不会工作。 -- a :[someAttr]value ... /a 2.2.2.3 修饰符
修饰符 (modifier) 是以半角句号 . 指明的特殊后缀用于指出一个指令应该以特殊方式绑定。例如.prevent 修饰符告诉 v-on 指令对于触发的事件调用 event.preventDefault() form v-on:submit.preventonSubmit.../form 2.2.3 过滤器
vue允许你自定义过滤器被用作一些常见的文本格式化。由管道符指示, 格式如下 !-- 在两个大括号中 -- {{ message | capitalize }} !-- 在 v-bind 指令中 -- div v-bind:idrawId | formatId/div 过滤器函数接受表达式的值作为第一个参数
以下示例代码中将字符串转换为大写字符
templatediv!--字符转大写--span{{message|toUp}}/span/div
/template
script
export default {name: example1,//数据data(){return {message:vue}},methods:{},//过滤器filters:{toUp:function(value){return value.toUpperCase();}}
}
/script
style scoped/style过滤器可以串联 {{ message | filterA | filterB }} 过滤器是 JavaScript 函数因此可以接受参数 {{ message | filterA(arg1, arg2) }} 这里message 是第一个参数字符串 arg1 将传给过滤器作为第二个参数 arg2 表达式的值将被求值然后传给过滤器作为第三个参数。 2.3 样式绑定
数据绑定的一个常见需求场景是操纵元素的CSS类列表和内联样式。因为它们都是attribute我们可以使用v-bind来做这件事我们只需要通过表达式计算出一个字符串作为最终结果即可。然而频繁操作字符串连接很闹心也很容易出错的。因此 Vue 为class和style的v-bind使用提供了特殊的功能增强。除了字符串外表达式的结果还可以是对象或数组。
2.3.1 绑定class类
2.3.1.1 对象方式
templatediv!--是否绑定class 类名称active取决于isActive的真假值--!--渲染效果div classactive/div--div :class{active:isActive}根据字段值true/false绑定calss/div!--多字段来动态切换多个class--!--hasError为false时的渲染效果 div classstatic active/div--!--hasError为true时的渲染效果 div classstatic active text-danger/div--div classstatic :class{active:isActive,text-danger: hasError }多字段来动态切换多个class/div!--绑定数据对象来动态切换多个class--!--text-danger为false时的渲染效果 div classactive/div--!--text-danger为true时的渲染效果 div classactive text-danger/div--div :classclassObject绑定数据对象来动态切换多个class/div!--通过计算属性来动态切换多个class--div :classclassCal通过计算属性来动态切换多个class/div/div
/template
script
export default {name: example1,//数据data(){return {isActive:true,hasError:false,classObject:{active:true,text-danger:false}}},methods:{},//过滤器filters:{},//计算属性computed:{classCal:function(){return {active: this.isActive !this.hasError,text-danger: this.hasError} }}
}
/script
style scoped
.active{color: purple;font-weight: 700;
}
.static{font-size: 30px;
}
.text-danger{color: red;
}
/style渲染效果
2.3.2.1 数组方式
templatediv!--绑定数组的方式动态切换多个class--!--渲染效果div classactive static/div--div :class[activeClass,staticClass]绑定数组的方式动态切换多个class/div!--根据条件来动态切换多个class可以用三元表达式--div :class[activeClass,hasError?dangerClass:]根据条件来动态切换多个class/div!--当判断条件较繁琐的时候数组中使用对象的方式来动态切换多个class--div :class[{active:isActive},dangerClass]数组中使用对象的方式来动态切换多个class/div/div
/template
script
export default {name: example1,//数据data(){return {isActive:true,hasError:false,activeClass:active,staticClass:static,dangerClass:text-danger}},methods:{},//过滤器filters:{},//计算属性computed:{}
}
/script
style scoped
.active{color: purple;font-weight: 700;
}
.static{font-size: 30px;
}
.text-danger{color: red;
}
/style渲染效果
2.3.3.2 组件绑定calss
当在一个自定义组件上使用 class property 时这些 class 将被添加到该组件的根元素上面。这个元素上已经存在的 class 不会被覆盖
比如使用HelloWorld的组件v-bind:class方式同样适用 HelloWorld msgWelcome to Your Vue.js App :classactive:isActive/ 2.3.2 绑定内联样式
2.3.2.1 对象方式
v-bind:style 的对象语法十分直观——看着非常像 CSS但其实是一个 JavaScript 对象。CSS property 名可以用驼峰式 (camelCase) 或短横线分隔 (kebab-case记得用引号括起来) 来命名
templatediv!--对象方式设置内联样式--div :style{ color:red, fontSize:30px }对象方式设置内联样式/div!--样式对象设置内联样式--div :stylestyleObject样式对象设置内联样式/div!--计算属性设置内联样式--div :stylestyleCal计算属性设置内联样式/div/div
/template
script
export default {name: example1,//数据data(){return {styleObject:{color:purple,fontSize:20px,fontWeight:600},isActive:true,haError:false}},methods:{},//过滤器filters:{},//计算属性computed:{styleCal:function(){return{color:this.haError?red:purple,fontSize:this.isActive?30px:20px}}}
}
/script
style scoped/style渲染效果
2.3.2.2 数组方式
内联方式的数组是数组对象
templatediv!--数组方式设置内联样式--div :style[styleColor,styleSize]数组方式设置内联样式/div/div
/template
script
export default {name: example1,//数据data(){return {styleColor:{color:purple},styleSize:{fontSize:20px}}},methods:{},//过滤器filters:{ },//计算属性computed:{}
}
/script
style scoped/style渲染效果 2.3.2.3 自动添加前缀
当你在:style中使用了需要浏览器特殊前缀的 CSS 属性时Vue 会自动为他们加上相应的前缀。Vue 是在运行时检查该属性是否支持在当前浏览器中使用。如果浏览器不支持某个属性那么将测试加上各个浏览器特殊前缀以找到哪一个是被支持的
如 transform
2.3.2.4 多重值
从 2.3.0 起你可以为 style 绑定中的 property 提供一个包含多个值的数组常用于提供多个带前缀的值例如 div :style{ display: [-webkit-box, -ms-flexbox, flex] }/div 这样写只会渲染数组中最后一个被浏览器支持的值。在本例中如果浏览器支持不带浏览器前缀的 flexbox那么就只会渲染 display: flex 2.4 条件语句
2.4.1 v-if
条件语句包含
v-ifv-if 指令用于条件性地渲染一块内容这块内容只会在指令的表达式返回 truthy 值的时候被渲染v-else-if表示v-if的“else-if 块”v-esle表示 v-if 的“else 块”v-else 元素必须紧跟在带 v-if 或者 v-else-if 的元素的后面否则它将不会被识别
注意不推荐同时使用 v-if 和 v-for当 v-if 与 v-for 一起使用时v-for 具有比 v-if 更高的优先级。
templatediv!--v-if 和v-esle--div v-ifisSuperAdminspan大家好我是超级管理员/span/divdiv v-elsespan大家好我普通用户/span/div!--v-if 和v-esle-if 、v-else--div v-ifloginTypeadminspan大家好我管理员角色/span/divdiv v-else-ifloginTypesuperadminspan大家好我超级管理员角色/span/divdiv v-else-ifloginTypeinchargespan大家好我主管角色/span/divdiv v-elsespan大家好我是普通用户角色/span/div/div
/template
script
export default {name: example1,//数据data(){return {loginType:user,isSuperAdmin:true}},methods:{},//过滤器filters:{ },//计算属性computed:{}
}
/script
style scoped/style渲染效果
2.4.2 v-show
另一个用于根据条件展示元素的选项是 v-show 指令 不同的是带有 v-show 的元素始终会被渲染并保留在 DOM 中v-show 只是简单地切换元素的 CSS property display。注意v-show 不支持 template 元素也不支持 v-else。
templatediv!--v-show--div v-showisSuperAdminspan大家好我是超级管理员/span/divdiv v-show!isSuperAdminspan大家好我是普通用户/span/div!--v-if 和v-esle-if 、v-else--div v-showloginTypeadminspan大家好我是管理员角色/span/divdiv v-showloginTypesuperadminspan大家好我是超级管理员角色/span/divdiv v-showloginTypeinchargespan大家好我是主管角色/span/divdiv v-showloginTypeuserspan大家好我是普通用户角色/span/div/div
/template
script
export default {name: example1,//数据data(){return {loginType:user,isSuperAdmin:true}},methods:{},//过滤器filters:{ },//计算属性computed:{}
}
/script
style scoped/style渲染效果 2.4.3 v-if和v-show对比
v-if 是“真正”的条件渲染因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。v-if 也是惰性的如果在初始渲染时条件为假则什么也不做——直到条件第一次变为真时才会开始渲染条件块。相比之下v-show 就简单得多——不管初始条件是什么元素总是会被渲染并且只是简单地基于 CSS 进行切换。一般来说v-if 有更高的切换开销而 v-show 有更高的初始渲染开销。因此如果需要非常频繁地切换则使用 v-show 较好如果在运行时条件很少改变则使用 v-if 较好。
2.5 循环语句
循环语句使用v-for指令
循环语法 !--v-for in遍历-- v-foritem in items !--v-for of遍历-- v-foritem of items 2.5.1 遍历数组和对象
v-for 可遍历数组和对象在 v-for 块中我们可以访问所有父作用域的 property
遍历数组支持可选的第二个参数当前项的索引 !--v-for in遍历-- v-foritem in items !--v-for in遍历 可选参数 当前索引-- v-for(item,index)in items 遍历对象支持可选的第二个参数键名还支持 可选的第三个参数当前索引 !--v-for in遍历-- v-forvalue in object !--v-for in遍历 可选参数 键名-- v-for(value,name) in object !--v-for in遍历 可选参数 键名、当前索引-- v-for(value,name,index) in object 注意v-for 遍历时一定要绑定元素key值否则编译报错 :keyitem
在遍历对象时会按 Object.keys() 的结果遍历但是不能保证它的结果在不同的 JavaScript 引擎下都一致。
templatedivh2v-for遍历数组/h2!--v-for遍历数组--ul v-foritem in studentInfos :keyitemli{{item.studentName}}/li/ulh2v-for遍历数组——元素值和当前索引参数/h2!--v-for遍历数组--ul v-for(item,index) in studentInfos :keyindexli{{index}}.{{item.studentName}}/li/ulh2v-for遍历对象/h2ul v-forvalue of house :keyvalueli{{value}}/li/ulh2v-for遍历对象——值和键名参数/h2ul v-for(value,name) of house :keyvalueli{{name}}{{value}}/li/ulh2v-for遍历对象——值、键名、当前索引参数/h2ul v-for(value,name,index) of house :keyvalueli{{index}}、{{name}}{{value}}/li/ul/div
/template
script
export default {name: example1,//数据data(){return {studentInfos:[{studentName:马云,age:18,gender:男,classNo:高三1班},{studentName:马化腾,age:17,gender:男,classNo:高三2班},{studentName:董明珠,age:15,gender:女,classNo:高三3班},{studentName:郎朗,age:18,gender:男,classNo:高三4班},{studentName:高峰,age:19,gender:男,classNo:高三5班}],house:{door:white door,roomNum:3,area:100,address:常州市新北区太湖东路世茂香槟湖}}},methods:{},//过滤器filters:{ },//计算属性computed:{}
}
/script
style scoped
ul{display:flex;margin-left: 45%;
}
/style渲染效果 2.5.2 遍历整数 可以直接传给v-for一个整数值。在这种用例中将会将该模板基于1...n的取值范围重复多次
templatedivh2v-for遍历整数/h2!--v-for遍历数组--ul v-forn in 10 :keynli{{n}}/li/ul/div
/template
script
export default {name: example1,//数据data(){return {studentInfos:[{studentName:马云,age:18,gender:男,classNo:高三1班},{studentName:马化腾,age:17,gender:男,classNo:高三2班},{studentName:董明珠,age:15,gender:女,classNo:高三3班},{studentName:郎朗,age:18,gender:男,classNo:高三4班},{studentName:高峰,age:19,gender:男,classNo:高三5班}],house:{door:white door,roomNum:3,area:100,address:常州市新北区太湖东路世茂香槟湖}}},methods:{},//过滤器filters:{ },//计算属性computed:{}
}
/script
style scoped
ul{display:flex;margin-left: 45%;
}
/style渲染效果 2.5.3 通过key管理状态 当 Vue 正在更新使用 v-for 渲染的元素列表时它默认使用“就地更新”的策略。如果数据项的顺序被改变Vue 将不会移动 DOM 元素来匹配数据项的顺序而是就地更新每个元素并且确保它们在每个索引位置正确渲染。 div v-foritem in items v-bind:keyitem.id !-- 内容 -- /div 建议尽可能在使用 v-for 时提供 key attribute除非遍历输出的 DOM 内容非常简单或者是刻意依赖默认行为以获取性能上的提升。
因为它是 Vue 识别节点的一个通用机制key 并不仅与 v-for 特别关联。后面我们将在指南中看到它还具有其它用途。
2.5.4 组件和template使用v-for
template使用v-for
在 template使用v-for 来循环渲染一段包含多个元素的内容。比如 ul template v-foritem in items li{{ item.msg }}/li li classdivider rolepresentation/li /template /ul 组件中使用v-for
在使用组件时任何数据都不会被自动传递到组件里因为组件有自己独立的作用域为了把迭代数据传递到组件里我们要使用 prop my-component v-for(item, index) in items v-bind:itemitem v-bind:indexindex v-bind:keyitem.id /my-component 我们定义一个helloworld的组件组件参数为msg
templatediv classhelloh1{{ msg }}/h1/div
/templatescript
export default {name: HelloWorld,props: {msg: String}
}
/script!-- Add scoped attribute to limit CSS to this component only --
style scoped/style引用helloworld组件使用v-for
templatediv idappHelloWorld v-foritem in msgList :msgitem.msg :keyitem.id/HelloWorld/div/templatescript
import HelloWorld from ./components/HelloWorld.vue//引入子组件HelloWorldexport default {name: App,components: {HelloWorld},//数据data(){return {msgList:[{msg:你好,id:1},{msg:保存失败,id:2},{msg:保存成功,id:3}]}}
}/scriptstyle
/* #app {font-family: Avenir, Helvetica, Arial, sans-serif;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;text-align: center;color: #2c3e50;margin-top: 60px;
} */
/style渲染效果 2.5.5 数组更新检测
2.5.5.1 变更方法
变更方法会变更原始数组。Vue 能够侦听响应式数组的变更方法并在它们被调用时触发相关的视图更新。这些变更方法包括
push()向数组的末尾添加一个或多个元素并返回新的长度。pop()删除数组的最后一个元素并返回最后一个元素。shift()删除数组的第一个元素并返回第一个元素的值。unshift()向数组的开头添加一个或更多元素并返回新的长度。sort()对数组的元素进行排序。reverse()颠倒数组中元素的顺序。splice()向/从数组中添加/删除项目然后返回被删除的项目。 删除功能array.splice(index,num)。 index必需。数组元素的下标必须是数字。使用负数可从数组结尾处规定位置。num可选。要删除的项目数量。如果设置为 0则不会删除项目。如果未规定此参数则删除从 index 开始到原数组结尾的所有元素。插入功能array.splice(index,0,item)。 index必需。数组元素的下标必须是数字。使用负数可从数组结尾处规定位置。0必需是 0。表示插入功能。item必需。规定要添加到数组的新元素。从 index 所指的下标处开始插入。替换功能array.splice(index,num,item)。 index必需。数组元素的下标必须是数字。使用负数可从数组结尾处规定位置。num必需。规定应该替换多少元素。必须是正整数。item必需。规定要添加到数组的新元素。从 index 所指的下标处开始替换。 2.5.5.2 替换数组
替换数组不变更原始数组而总是返回一个新数组。当使用非变更方法时可以用新数组替换旧数组触发相关的视图更新。
filter()创建一个新的数组新数组中的元素是通过检查指定数组中符合条件的所有元素。concat()用于连接两个或多个数组。slice()从已有的数组中返回选定的元素。split()用于把一个字符串分割成字符串数组。 // items 是一个数组的 ref items.value items.value.filter((item) item.message.match(/Foo/)) 你可能认为这将导致 Vue 丢弃现有 DOM 并重新渲染整个列表。幸运的是事实并非如此。Vue 为了使得 DOM 元素得到最大范围的重用而实现了一些智能的启发式方法所以用一个含有相同元素的数组去替换原来的数组是非常高效的操作。
2.5.6 使用计算属性展示过滤或排序后的结果
当我们想要显示一个数组经过过滤或排序后的版本而不实际变更或重置原始数据。在这种情况下可以创建一个计算属性来返回过滤或排序后的数组。
templatedivh2使用计算属性展示过滤或排序后的结果/h2!--v-for遍历数组 使用计算属性展示过滤或排序后的结果--ul v-forn in evenNumbers :keynli{{n}}/li/ul/div
/template
script
export default {name: example1,//数据data(){return {numbers:[1,2,5,6,7,9]}},methods:{},//过滤器filters:{ },//计算属性computed:{//过滤数据evenNumbers: function () {return this.numbers.filter(function (number) {return number % 2 0})}}
}
/script
style scoped/style渲染效果 在计算属性不适用的情况下 (例如在嵌套 v-for 循环中) 你可以使用一个方法
ul v-forset in setsli v-forn in even(set){{ n }}/li
/ul
data: {sets: [[ 1, 2, 3, 4, 5 ], [6, 7, 8, 9, 10]]
},
methods: {even: function (numbers) {return numbers.filter(function (number) {return number % 2 0})}
} 在计算属性中使用reverse()和sort()请保持谨慎这两个方法将改变原始数组计算函数中不应该这么做。请在调用这些方法之前创建一个原数组的副本 // 慎用 return numbers.reverse() // 推荐 return [...numbers].reverse() 2.6 计算属性
当我们在模板中多次使用相同的表达计算方式或者计算逻辑复杂的推荐使用计算属性(computed)来描述依赖响应式状态的复杂逻辑计算属性会自动追踪响应式依赖。
使用计算属性可以减少代码的重复性降低维护难度增强代码的可读性。
使用计算属性实现反转字符串实例
templatedivh2使用计算属性展实现反转字符串/h2span{{reverseMsg}}/span/div
/template
script
export default {name: example1,//数据data(){return {message:Hello World}},methods:{},//过滤器filters:{ },//计算属性computed:{reverseMsg: function () {return this.message.split( ).reverse().join();}}
}
/script
style scoped/style渲染效果 2.6.1 计算属性的setter
计算属性默认只有 getter不过在需要时你也可以提供一个 setter
计算两个数据的占比实例
templatedivh2计算属性的setter/h2span{{calPercent}}/spanbutton clickchangeNum计算属性setter/button/div
/template
script
export default {name: example1,//数据data(){return {num:30,totalNum:500}},methods:{changeNum(){//计算属性 传值 setter会被调用更新num和totalNum的值那么对应的计算结果会改变this.calPercent[25,400];}},//过滤器filters:{ },//计算属性computed:{calPercent: {get: function() {return (this.num/this.totalNum*100).toFixed(2);},set:function(newValue){this.numnewValue[0];this.totalNumnewValue[1]; } }}
}
/script
style scoped/style2.6.2 计算属性缓存和方法对比 我们可以通过在表达式中调用方法来达到和计算属性同样的效果可以将同一函数定义为一个方法而不是一个计算属两种方式的最终结果确实是完全相同的。
然而不同的是计算属性是基于它们的响应式依赖进行缓存的只在相关响应式依赖发生改变时它们才会重新求值。
相比之下每当触发重新渲染时调用方法将总会再次执行函数。
我们为什么需要缓存假设我们有一个性能开销比较大的计算属性 A它需要遍历一个巨大的数组并做大量的计算。然后我们可能有其他的计算属性依赖于 A。如果没有缓存我们将不可避免的多次执行 A 的 getter如果你不希望有缓存请用方法来替代。
2.7 监听属性
计算属性允许我们声明性地计算衍生值。然而在有些情况下为了应对一些状态的变化我们需要运行些effect副作用例如更改 DOM或者根据异步操作的结果去修改另一处的状态。
我们可以使用watch()函数在每次响应式状态发生变化时触发回调函数
以监听question变量为实例的代码
templatedivpAsk a yes/no question:input v-modelquestion/pp{{ answer }}/pp{{changeInfo}}/pbutton clickchangeQuestion改变question/button/div
/template
script
export default {name: example1,//数据data(){return {question:,answer:I cannot give you an answer until you ask a question!,changeInfo:}},methods:{//改变问题changeQuestion(){this.questionI have a question about this computer;}},//过滤器filters:{ },//计算属性computed:{},//监听属性watch:{question:function(newVal,oldVal){this.changeInfoold question:${oldVal},new question:${newVal};this.answer Waiting for you to stop typing...;//metods等方法调用}}
}
/script
style scoped/style点击“改变question”按钮或者在文本框中输入问题页面显示 question变更后 2.8 事件处理器
2.8.1 监听事件
使用v-on指令缩写为符号来监听 DOM 事件并在触发事件时执行一些 JavaScript
按钮点击事件代码示例 button clickchangeQuestion改变question/button 或者 button v-on:clickchangeQuestion改变question/button 事件处理器的值可以是
内联事件处理器事件被触发时执行的内联 JavaScript 语句与 onclick 类似。方法事件处理器一个组件定义的方法名、或对某个方法的访问路径。
模板编译器会通过检查v-on的值是否是合法的 JavaScript 标识符或属性访问来断定是何种形式的事件处理器。举个例子foo、foo.bar和foo[bar]会被视为方法事件处理器而foo()和count会被视为内联事件处理器。
2.8.2 内联事件处理器
内联事件处理器的使用场景
简单事件处理调用方法访问事件参数有时需要在内联事件处理器中访问原生 DOM 事件。你可以向该处理器方法传入一个特殊的$event变量或者使用内联箭头函数多事件处理器事件处理程序中可以有多个方法这些方法由,逗号分隔
实例代码
templatedivh3内联事件处理器—简单场景/h3p计数{{ count }}/pbutton clickcount内联事件简单场景/buttonh3内联事件处理器—调用方法/h3p问题{{question}}/pbutton clickchangeQuestion改变question/buttonbutton clickchangeQ(This is a new quesuion) :style{marginLeft:20px}带参方法/buttonh3内联事件处理器—访问事件参数/h3button clickwarnMsg(访问事件参数$event变量,$event)访问事件参数$event变量/buttonbutton click(event){warnMsg(访问事件参数箭头函数,event)} :style{marginLeft:20px}访问事件参数箭头函数/buttonh3内联事件处理器—多事件处理器/h3button clickoneEvent(1),twoWvent()多事件处理器/button/div
/template
script
export default {name: example1,//数据data(){return {count:1,question:I cannot give you an answer until you ask a question!,muntiMethod:多事件处理器}},methods:{//改变问题changeQuestion(){this.questionI have a question about this computer;},//带参返回发changeQ(questionVal){this.questionquestionVal;},//事件参数warnMsg(msg,event){//这里可以访问DOM原生事件if(event){alert(msg);event.preventDefault(); }else{alert(不是事件);}},oneEvent(numVal){this.muntiMethodnumVal;},twoWvent(){alert(this.muntiMethod);}},//过滤器filters:{ },//计算属性computed:{},//监听属性watch:{}
}
/script
style scoped/style2.8.3 事件处理方法
随着事件处理器的逻辑变得愈发复杂内联代码方式变得不够灵活。因此v-on也可以接受一个方法名或对某个方法的调用
实例代码
templatedivh3事件处理方法/h3button clickgreetGreet/button/div
/template
script
export default { //数据data(){return {name: Vue2,}},methods:{//事件参数greet(event){// this 在方法里指向当前 Vue 实例alert(Hello this.name !)// event 是原生 DOM 事件if (event) {alert(event.target.tagName)}}},//过滤器filters:{ },//计算属性computed:{},//监听属性watch:{}
}
/script
style scoped/style2.8.4 DOM事件冒泡
DOM 在触发事件后会经历事件捕获和事件冒泡两个最重要阶段。在 W3C 标准中任何事件发生时先从顶层开始进行事件捕获直到事件触发到达了事件源元素。然后再从事件源往上进行事件冒泡直到到达 document。浏览器 IE 只支持事件冒泡。
事件捕获由最外层向最里层触发事件的过程叫事件捕获。事件从最不精确的 document 对象开始触发然后到最具体的元素。事件冒泡事件会从最内层的元素开始发生一直向外层向上传播直到 document 对象。阻止冒泡事件冒泡过程是可以被阻止的。防止事件冒泡而带来不必要的错误和困扰。阻止事件冒泡的三种手段 return false可以阻止默认事件和冒泡事件。event.stopPropagation可以阻止冒泡事件但是允许默认事件。IE 下event.cancelBubble trueevent.preventDefault()可以阻止默认事件但是允许冒泡事件。IE 下event.returnValue false
事件委托事件委托也叫事件代理“事件代理”即是把原本需要绑定在子元素的响应事件onclickonmouseoveronmouseout等委托给父元素让父元素担当事件监听的职务。事件代理的原理是 DOM 元素的事件冒泡。
2.8.5 事件修饰符
在处理事件时调用event.preventDefault()或event.stopPropagation()是很常见的。尽管我们可以直接在方法内调用但如果方法能更专注于数据逻辑而不用去处理 DOM 事件的细节会更好。 为解决这一问题Vue 为v-on提供了事件修饰符。修饰符是用.点表示的指令后缀。
.stop阻止事件冒泡。阻止事件向上级 DOM 元素传递。.prevent阻止默认事件。默认事件指对 DOM 的操作会引起自动执行的动作。比如点击超链接的时候会进行页面的跳转点击表单提交按钮时会重新加载页面等。.capture使用事件的捕获模式。使事件触发从包含这个元素的顶层开始往下触发。.self只有 event.target 是当前操作的元素时才触发事件。.once事件只触发一次。.passive事件的默认行为立即执行无需等待事件回调执行完毕。
!-- 阻止单击事件继续传播 --
a v-on:click.stopdoThis/a
!-- 提交事件不再重载页面 --
form v-on:submit.preventonSubmit/form
!-- 修饰符可以串联 --
a v-on:click.stop.preventdoThat/a
!-- 只有修饰符 --
form v-on:submit.prevent/form
!-- 添加事件监听器时使用事件捕获模式 --
!-- 即内部元素触发的事件先在此处理然后才交由内部元素进行处理 --
div v-on:click.capturedoThis.../div
!-- 只当在 event.target 是当前元素自身时触发处理函数 --
!-- 即事件不是从内部元素触发的 --
div v-on:click.selfdoThat.../div
注意使用修饰符时顺序很重要相应的代码会以同样的顺序产生。因此用 v-on:click.prevent.self 会阻止所有的点击而 v-on:click.self.prevent 只会阻止对元素自身的点击。
.capture.once和.passive修饰符与原生addEventListener事件相同 !-- 添加事件监听器时使用 capture 捕获模式 -- !-- 例如指向内部元素的事件在被内部元素处理前先被外部处理 -- div click.capturedoThis.../div !-- 点击事件最多被触发一次 -- a click.oncedoThis/a !-- 滚动事件的默认行为 (scrolling) 将立即发生而非等待 onScroll 完成 -- !-- 以防其中包含 event.preventDefault() -- div scroll.passiveonScroll.../div .passive修饰符一般用于触摸事件的监听器可以用来改善移动端设备的滚屏性能。注意请勿同时使用.passive和.prevent因为.prevent会被忽略并且你的浏览器可能会抛出警告。请记住.passive是向浏览器表明你不想阻止事件的默认行为。并且如果你这样做可能在浏览器中收到一个警告。
2.8.6 按键修饰符
在监听键盘事件时我们经常需要检查特定的按键。Vue 允许在v-on或监听按键事件时添加按键修饰符。 !-- 仅在 key 为 Enter 时调用 vm.submit() -- input keyup.entersubmit / 你可以直接使用KeyboardEvent.key暴露的按键名称作为修饰符但需要转为kebab-case形式。 input keyup.page-downonPageDown / 在上述示例中处理函数只会在$event.key等于PageDown时被调用。 Vue 为最常用的键提供了别名
.enter.tab.delete(捕获“删除”和“退格”键).esc.space.up.down.left.right 注意有一些按键 (.esc 以及所有的方向键) 在 IE9 中有不同的 key 值, 如果你想支持 IE9这些内置的别名应该是首选。
2.8.7 系统修饰键
可以用如下修饰符来实现仅在按下相应按键时才触发鼠标或键盘事件的监听器。
.ctrl.alt.shift.meta
注意在 Mac 系统键盘上meta 对应 command 键 (⌘)。在 Windows 系统键盘 meta 对应 Windows 徽标键 (⊞)。在 Sun 操作系统键盘上meta 对应实心宝石键 (◆)。在其他特定键盘上尤其在 MIT 和 Lisp 机器的键盘、以及其后继产品比如 Knight 键盘、space-cadet 键盘meta 被标记为“META”。在 Symbolics 键盘上meta 被标记为“META”或者“Meta”。 !-- Alt Enter -- input keyup.alt.enterclear / !-- Ctrl Click -- div click.ctrldoSomethingDo something/div 请注意修饰键与常规按键不同在和keyup事件一起用时事件触发时修饰键必须处于按下状态。换句话说keyup.ctrl只有在按住ctrl的情况下但松开了另一个键时才被触发。而单单释放ctrl也不会触发事件。
2.8.7.1 .exact修饰符
.exact 修饰符允许你控制由精确的系统修饰符组合触发的事件。 !-- 即使 Alt 或 Shift 被一同按下时也会触发 -- button v-on:click.ctrlonClickA/button !-- 有且只有 Ctrl 被按下的时候才触发 -- button v-on:click.ctrl.exactonCtrlClickA/button !-- 没有任何系统修饰符被按下的时候才触发 -- button v-on:click.exactonClickA/button 2.8.7.2 鼠标按钮修饰符
.left.right.middle
这些修饰符会限制处理函数仅响应特定的鼠标按钮。
2.9 表单
在前端处理表单时我们常常需要将表单输入框的内容同步给 JavaScript 中相应的变量。手动连接值绑定和更改事件监听器可能会很麻烦v-model指令帮我们简化了这一步骤。 另外v-model还可以用于各种不同类型的输入元素。它会根据所使用的元素自动扩展到不同的 DOM 属性和事件组合
文本类型的input、textarea元素会使用到value属性和input事件input typecheckbox和input typeradio使用checked property 和change事件select使用的value属性和change事件。
v-model会忽略所有表单元素的 attribute 的初始值比如value、checked、selected。它将始终将当前绑定的 JavaScript 状态视为数据的正确来源。你应该在 JavaScript 中声明该初始值使用响应式数据。
对于需要使用输入法 (如中文、日文、韩文等) 的语言你会发现 v-model 不会在输入法组合文字过程中得到更新。如果你也想处理这个过程请使用 input 事件 2.9.1 基础用法
包含文本(text)、多行文本(textarea)、复选框(checkbox)、单选按钮(radio)、选择框(select)控件的数据绑定
代码实例
templatedivh3文本绑定值{{txtContent}}/h3input v-modeltxtContent placeholder请输入文本内容h3多行文本绑定值{{txtAreaContent}}/h3textarea v-modeltxtAreaContent placeholder请输入多行文本内容/textareah3单个复选框/h3 input typecheckbox idcheckbox v-modelcheckedlabel forcheckbox单个复选框{{checked}}/labelh3多个复选框绑定到同一个数组或集合的值/h3input typecheckbox idjack valueJack v-modelmultiChecklabel forjackJack/labelinput typecheckbox idjohn valueJohn v-modelmultiChecklabel forjohnJohn/labelinput typecheckbox idmike valueMike v-modelmultiChecklabel formikeMike/labelbrspanChecked names: {{ multiCheck }}/spanh3单选按钮/h3input typeradio idone valueOne v-modelradioVallabel foroneOne/labelbrinput typeradio idtwo valueTwo v-modelradioVallabel fortwoTwo/labelbrspanPicked: {{ radioVal }}/spanh3选择框/h3select v-modelselectedoption disabled value请选择/optionoptionA/optionoptionB/optionoptionC/option/selectspanSelected: {{ selected }}/spanh3选择框多选绑定到一个数组多选时需要按住ctrl选择多个/h3select v-modelmultiSelect multiple stylewidth: 50px;optionA/optionoptionB/optionoptionC/option/selectbrspanSelected: {{ multiSelect }}/spanh3v-for 动态渲染绑定选择框/h3select v-modelselectedoption v-forsel in vforSelects :valuesel.value :keysel.value{{ sel.text }}/option/selectspanSelected: {{ selected }}/span/div
/template
script
export default { //数据data(){return {txtContent:,txtAreaContent:,checked:false,multiCheck:[],radioVal:,selected:,multiSelect:[],vforSelects:[{text:请选择,value:},{text:red,value:1},{text:balck,value:2},{text:white,value:3}]}},methods:{},//过滤器filters:{ },//计算属性computed:{},//监听属性watch:{}
}
/script
style scoped/style对于多行文本在文本区域插值 (textarea{{text}}/textarea) 并不会生效应用 v-model 来代替。
对于选择框如果 v-model 表达式的初始值未能匹配任何选项select 元素将被渲染为“未选中”状态。在 iOS 中这会使用户无法选择第一个选项。因为这样的情况下iOS 不会触发 change 事件。因此更推荐像上面这样提供一个值为空的禁用选项。
2.9.2 值绑定
对于单选按钮复选框及选择框的选项v-model绑定的值通常是静态字符串对于复选框也可以是布尔值但有时我们可能希望将该值绑定到当前活动实例上的动态属性那么可以使用v-bind来做到。此外使用v-bind还使我们可以将选项值绑定为非字符串类型
templatedivh3复选框值绑定/h3 !-- 这里的 true-value 和 false-value attribute 并不会影响输入控件的 value attribute因为浏览器在提交表单时并不会包含未被选中的复选框。如果要确保表单中这两个值中的一个能够被提交(即“yes”或“no”)请换用单选按钮 --input typecheckbox idcheckbox v-modelchecked false-valueno true-valueyeslabel forcheckbox复选框值绑定{{checked}}/label h3单选按钮值绑定/h3input typeradio idone v-modelradioVal :valueradioBindlabel foroneOne/labelbrinput typeradio idtwo valueTwo v-modelradioVallabel fortwoTwo/labelbrspanPicked: {{ radioVal }}/spanh3选择框的值绑定/h3select v-modelselectedoption value请选择/optionoption :valueselectBindA/optionoptionB/optionoptionC/option/selectspanSelected: {{ selected }}/span /div
/template
script
export default { //数据data(){return {checked:false,radioVal:,radioBind:A,selected:,selectBind:AA}},methods:{},//过滤器filters:{ },//计算属性computed:{},//监听属性watch:{}
}
/script
style scoped/style效果 2.9.3 修饰符
.lazy懒加载。在默认情况下v-model在每次input事件触发后将输入框的值与数据进行同步(除了上述输入法组织文字时)。你可以添加lazy修饰符从而转为在change事件之后更新数据同步.number确保为数值。如果想自动将用户的输入值自动转为数值类型可以给v-model添加number修饰符.trim去除两端空格。如果要自动去除用户输入内容中两端的空格可以给v-model添加trim修饰符
templatedivh3.lazy修饰符/h3 !-- 这里的 true-value 和 false-value attribute 并不会影响输入控件的 value attribute因为浏览器在提交表单时并不会包含未被选中的复选框。如果要确保表单中这两个值中的一个能够被提交(即“yes”或“no”)请换用单选按钮 --input v-model.lazymsgspan{{msg}}/span h3.number修饰符/h3input v-model.numberage typenumber /span{{age}}/span h3.trim修饰符/h3input v-model.trimtrimMsg /div
/template
script
export default { //数据data(){return {msg:,age:18,trimMsg: trim修饰符去除两端空格 }},methods:{},//过滤器filters:{ },//计算属性computed:{},//监听属性watch:{}
}
/script
style scoped/style注意如果使用了.lazy修饰符文本改变需要点击一下页面空白处页面中的变量值才会同步更新
2.10 组件
组件Component是 Vue 最强大的功能之一。 组件可以扩展 HTML 元素封装可重用的代码。 组件系统让我们可以用独立可复用的小组件来构建大型应用几乎任意类型的应用的界面都可以抽象为一个组件树 例如你可能会有页头、侧边栏、内容区等组件每个组件又包含了其它的像导航链接、博文之类的组件。 使用组件的步骤
1.定义组件创建组件实例 2.注册组件 全局组件component‘组件名’,组件实例 局部组件components:{组件实例…} 3.使用组件使用组件标签 组件名/组件名 双标签写法 组件名/ 单标签写法
组件命名方式 使用 kebab-case Vue.component(my-component-name, { /* ... */ }) 当使用 kebab-case (短横线分隔命名) 定义一个组件时你也必须在引用这个自定义元素时使用 kebab-case例如 my-component-name。 使用 PascalCase Vue.component(MyComponentName, { /* ... */ }) 当使用 PascalCase (首字母大写命名) 定义一个组件时你在引用这个自定义元素时两种命名法都可以使用。也就是说 my-component-name 和 MyComponentName 都是可接受的。注意尽管如此直接在 DOM (即非字符串的模板) 中使用时只有 kebab-case 是有效的。
2.10.1 全局组件
我们使用Vue.component来注册全局组件
方式一 Vue.component(my-component-name, { // ... 选项 ... }) 使用此方式注册的全局组件如果出现以下错误
You are using the runtime-only build of Vue where the template compiler is not available. Either pre-compile the templates into render functions, or use the compiler-included build. 解决方案
在vue.config.js配置文件中将runtimeCompiler设置为true module.exports { runtimeCompiler:true } 方式二 import 组件别名 from xx.vue; Vue.component(component-a, 引入的组件别名) 我们在main.js中注册全局组件实例代码
import Vue from vue
import App from ./App.vue//引入根组件
import router from ./router/router.js//引用router.js
import /assets/css/common.scss // 全局样式import allCountCom from ./components/VueAllCom.vue//引入组件Vue.config.productionTip false;
//注册全局组件——button-counter
Vue.component(button-counter, {data:function() {return {count: 0}},template: button v-on:clickcountYou clicked me {{ count }} times./button
});
//通过import vue文件方式注册全局组件
Vue.component(AllCounter,allCountCom);
//实例化vue
new Vue({router,render: h h(App),//导入根组件
}).$mount(#app);//mount挂载应用 根组件id
VueAllCom.vue 代码
templatedivbutton clickcountimport方式注册全局组件/buttonspan点击了{{count}}次/span/div
/template
script
export default{data(){return {count:0}}
}
/script使用全局组件
templatedivbutton-counter/button-counterAllCounter/AllCounter/div
/template
script
export default { //数据data(){return {}},methods:{},//过滤器filters:{ },//计算属性computed:{},//监听属性watch:{}
}
/script
style scoped/style效果 当组件中使用模板字符串来定义页面元素时当控件类型有多个时必须要在模板字符串中设置div根元素比如
//JavaScript 对象来定义局部组件 ButtonCounter
var ButtonCounter{data:function(){return {count:0}},props:{title:String,author:String},template:divbutton v-on:clickcountYou clicked me {{ count }} times./button br p标题{{title}}作者{{author}}/p/div
};
2.10.2 局部组件
全局注册往往是不够理想的。比如如果你使用一个像 webpack 这样的构建系统全局注册所有的组件意味着即便你已经不再使用一个组件了它仍然会被包含在你最终的构建结果中。这造成了用户下载的 JavaScript 的无谓的增加。
局部组件的注册方式
通过一个普通的 JavaScript 对象来定义组件然后在components中注册 //定义组件 var ComponentA { /* ... */ } var ComponentB { /* ... */ } var ComponentC { /* ... */ } components中注册组件 components: { component-a: ComponentA, component-b: ComponentB } 注意 JavaScript 对象来定义组件需要在vue.config.js中设置runtimeCompiler:true
使用import 引入vue文件然后在components中注册 import 组件别名 from xx.vue;//引入组件局部注册 components中注册组件 components: { 组件别名 } 我们将上述全局组件中的两个组件实例转换成局部组件代码如下
templatedivbutton-counter/button-counterAllCounter/AllCounter/div
/template
script
import AllCounter from ../components/VueAllCom.vue;//引入组件局部注册
//JavaScript 对象来定义局部组件 ButtonCounter
var ButtonCounter{data:function(){return {count:0}},template:button v-on:clickcountYou clicked me {{ count }} times./button
};
export default { //数据data(){return {}},//注册局部组件components:{button-counter:ButtonCounter,AllCounter}
}
/script
style scoped/style注意局部注册的组件在其子组件中不可用。例如如果你希望 ComponentA 在 ComponentB 中可用则你需要这样写 var ComponentA { /* ... */ } var ComponentB { components: { component-a: ComponentA }, // ... } 如果两个子组件都是单独的vue文件则需要在一个vue文件中通过import的方式引入另一个子组件 import ComponentA from ./ComponentA.vue export default { components: { ComponentA }, // ... } 2.10.3 prop子组件传参
prop 是子组件用来接受父组件传递过来的数据的一个自定义属性。
父组件的数据需要通过 props 把数据传给子组件子组件需要显式地用 props 选项声明 prop
2.10.3.1 prop的大小写
HTML 中的 attribute 名是大小写不敏感的所以浏览器会把所有大写字符解释为小写字符。这意味着当你使用 DOM 中的模板时camelCase (驼峰命名法) 的 prop 名需要使用其等价的 kebab-case (短横线分隔命名) 命名
Vue.component(blog-post, {// 在 JavaScript 中是 camelCase 的props: [postTitle],template: h3{{ postTitle }}/h3
})
!-- 在 HTML 中是 kebab-case 的 --
blog-post post-titlehello!/blog-post
重申一次如果你使用字符串模板那么这个限制就不存在了
2.10.3.2 prop类型 prop类型字符串数组、对象
/*数组类型*/
props: [title, likes, isPublished, commentIds, author]
/*对象 每个 prop 都有指定的值类型*/
props: {title: String,likes: Number,isPublished: Boolean,commentIds: Array,author: Object,callback: Function,contactsPromise: Promise // or any other constructor
}
2.10.3.3 传递静态或动态prop !-- 静态传值 --
blog-post titleMy journey with Vue/blog-post
!-- 动态赋予一个变量的值 --
blog-post v-bind:titlepost.title/blog-post
!-- 动态赋予一个复杂表达式的值 --
blog-post v-bind:titlepost.title by post.author.name/blog-post
实际上任何类型的值都可以传给一个 prop无需在意prop定义的数据类型
传入数字
!-- 即便 42 是静态的我们仍然需要 v-bind 来告诉 Vue --
!-- 这是一个 JavaScript 表达式而不是一个字符串。--
blog-post v-bind:likes42/blog-post
!-- 用一个变量进行动态赋值。--
blog-post v-bind:likespost.likes/blog-post
传入布尔值
!-- 包含该 prop 没有值的情况在内都意味着 true。--
blog-post is-published/blog-post
!-- 即便 false 是静态的我们仍然需要 v-bind 来告诉 Vue --
!-- 这是一个 JavaScript 表达式而不是一个字符串。--
blog-post v-bind:is-publishedfalse/blog-post
!-- 用一个变量进行动态赋值。--
blog-post v-bind:is-publishedpost.isPublished/blog-post
传入数组
!-- 即便数组是静态的我们仍然需要 v-bind 来告诉 Vue --
!-- 这是一个 JavaScript 表达式而不是一个字符串。--
blog-post v-bind:comment-ids[234, 266, 273]/blog-post
!-- 用一个变量进行动态赋值。--
blog-post v-bind:comment-idspost.commentIds/blog-post
传入对象
!-- 即便对象是静态的我们仍然需要 v-bind 来告诉 Vue --
!-- 这是一个 JavaScript 表达式而不是一个字符串。--
blog-post
v-bind:author{
name: Veronica,
company: Veridian Dynamics
}/blog-post
!-- 用一个变量进行动态赋值。--
blog-post v-bind:authorpost.author/blog-post
传入对象的所有property
!-- 定义对象--
post: {
id: 1,
title: My Journey with Vue
}!--对象传值--
blog-post v-bindpost/blog-post 2.10.3.4 prop单项数据流
所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定父级 prop 的更新会向下流动到子组件中但是反过来则不行。这样会防止从子组件意外变更父级组件的状态从而导致你的应用的数据流向难以理解。
额外的每次父级组件发生变更时子组件中所有的 prop 都将会刷新为最新的值。这意味着你不应该在一个子组件内部改变 prop。如果你这样做了Vue 会在浏览器的控制台中发出警告。
这里有两种常见的试图变更一个 prop 的情形
1.这个 prop 用来传递一个初始值这个子组件接下来希望将其作为一个本地的 prop 数据来使用。在这种情况下最好定义一个本地的 data property 并将这个 prop 用作其初始值
props: [initialCounter],
data: function () {
return {
counter: this.initialCounter
}
}
2.这个 prop 以一种原始的值传入且需要进行转换。在这种情况下最好使用这个 prop 的值来定义一个计算属性
props: [size],
computed: {
normalizedSize: function () {
return this.size.trim().toLowerCase()
}
}
注意在 JavaScript 中对象和数组是通过引用传入的所以对于一个数组或对象类型的 prop 来说在子组件中改变变更这个对象或数组本身将会影响到父组件的状态。
2.10.3.5 prop验证
为了定制 prop 的验证方式你可以为 props 中的值提供一个带有验证需求的对象而不是一个字符串数组。例如
Vue.component(my-component, {props: {// 基础的类型检查 (null 和 undefined 会通过任何类型验证)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 [success, warning, danger].includes(value)}}}
})
注意那些 prop 会在一个组件实例创建之前进行验证所以实例的 property (如 data、computed 等) 在 default 或 validator 函数中是不可用的。
类型检查
type 可以是下列原生构造函数中的一个
StringNumberBooleanArrayObjectDateFunctionSymbol
额外的type 还可以是一个自定义的构造函数并且通过 instanceof 来进行检查确认。例如给定下列现成的构造函数
function Person (firstName, lastName) {this.firstName firstNamethis.lastName lastName
}
你可以使用
Vue.component(blog-post, {props: {author: Person}
})
来验证 author prop 的值是否是通过 new Person 创建的。
2.10.3.6 传参实例
templatedivbutton-counter v-bindpropsData/button-counter!-- AllCounter/AllCounter --/div
/template
script
// import AllCounter from ../components/VueAllCom.vue;//引入组件局部注册
//JavaScript 对象来定义局部组件 ButtonCounter
var ButtonCounter{data:function(){return {count:0}},props:{title:String,author:String},template:divbutton v-on:clickcountYou clicked me {{ count }} times./button br p标题{{title}}作者{{author}}/p/div
};
export default { //数据data(){return {//props传参对象propsData:{title:Vue2,author:youyuxi}}},//注册局部组件components:{button-counter:ButtonCounter,// AllCounter}
}
/script
style scoped/style2.10.4 监听事件
2.10.4.1 使用事件抛出一个值
在我们开发组件时组件的一些功能可能要求我们和父级组件进行沟通。 比如我们需要设置文本的字号
最简单的方式是我们在父组件中统一设置文本内容的字号这样每个子组件中显示的字号都一致了实例代码
templatediv :style{ fontSize: postFontSize em }blog-post v-foritem in posts v-bind:postitem :keyitem.id/blog-post/div
/template
script
//JavaScript 对象来定义局部组件 blog-post
var BlogPost{data:function(){return {}},props:[post],template:div classblog-posth3{{ post.title }}/h3div v-htmlpost.content/div/div
};
export default { //数据data(){return {//props传参对象posts:[{id:1, title:Vue2,content:pVue是一套构建用户界面的渐进式框架。Vue只关注视图层采用自底向上增量开发的设计。Vue的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件。/p},{id:2, title:Vue3,content:p如果你是初学者可能会觉得这些概念有些复杂。别担心理解教程和指南的内容只需要具备基础的 HTML 和 JavaScript 知识。即使你不是这些方面的专家也能够跟得上/p},],postFontSize:2}},//注册局部组件components:{blog-post:BlogPost}
}
/script
style scoped/style效果 我们还可以通过监听子组件的事件来动态事件文本字体的变化我们需要在代码中做以下改变
1在子组建中添加事件 v-on:enlarge-textpostFontSize 0.1
2)在子组件中新增放大字体的按钮通过调用内建的 $emit 方法并传入事件名称来触发组件的enlarge-text事件 button click$emit(enlarge-text)放大文本字号/button 实例代码如下
templatediv :style{ fontSize: postFontSize em }blog-post v-foritem in posts v-bind:postitem :keyitem.id v-on:enlarge-textpostFontSize 0.1/blog-post/div
/template
script
//JavaScript 对象来定义局部组件 blog-post
var BlogPost{data:function(){return {}},props:[post],template:div classblog-posth3{{ post.title }}/h3button click$emit(enlarge-text)放大文本字号/buttondiv v-htmlpost.content/div/div
};
export default { //数据data(){return {//props传参对象posts:[{id:1, title:Vue2,content:pVue是一套构建用户界面的渐进式框架。Vue只关注视图层采用自底向上增量开发的设计。Vue的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件。/p},{id:2, title:Vue3,content:p如果你是初学者可能会觉得这些概念有些复杂。别担心理解教程和指南的内容只需要具备基础的 HTML 和 JavaScript 知识。即使你不是这些方面的专家也能够跟得上/p},],postFontSize:1}},//注册局部组件components:{blog-post:BlogPost}
}
/script
style scoped/style效果 当我们要考虑让子组件自己决定字号的大小那么此时我们需要做如下改变
1用事件来抛出一个特定的值子组件中的按钮$emit方法添加字号固定变大值
button click$emit(enlarge-text0.1)放大文本字号/button
2子组件的事件代码改为v-on:enlarge-textpostFontSize $event
实例代码如下
templatediv :style{ fontSize: postFontSize em }blog-post v-foritem in posts v-bind:postitem :keyitem.id v-on:enlarge-textpostFontSize $event/blog-post/div
/template
script
//JavaScript 对象来定义局部组件 blog-post
var BlogPost{data:function(){return {}},props:[post],template:div classblog-posth3{{ post.title }}/h3button click$emit(enlarge-text,0.1)放大文本字号/buttondiv v-htmlpost.content/div/div
};
export default { //数据data(){return {//props传参对象posts:[{id:1, title:Vue2,content:pVue是一套构建用户界面的渐进式框架。Vue只关注视图层采用自底向上增量开发的设计。Vue的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件。/p},{id:2, title:Vue3,content:p如果你是初学者可能会觉得这些概念有些复杂。别担心理解教程和指南的内容只需要具备基础的 HTML 和 JavaScript 知识。即使你不是这些方面的专家也能够跟得上/p},],postFontSize:1}},//注册局部组件components:{blog-post:BlogPost}
}
/script
style scoped/style子组件事件也可通方法完成字号放大的功能
1子组件事件改成调用方法onEnlargeText v-on:enlarge-textonEnlargeText
2父组件methods中创建onEnlargeText 方法 methods: { onEnlargeText: function (enlargeAmount) { this.postFontSize enlargeAmount } } 2.10.4.2 组件上使用v-model 以input的一个组件未示例展示如何实现在组件中使用v-model
实例代码
templatedivcustom-input v-modelsearchText/custom-input/div
/template
script
//JavaScript 对象来定义局部组件 custom-input 用来展示组件中v-model的使用
var CustomInput{data:function(){return {}},props:[value],template:input v-bind:valuevalue v-on:input$emit(input, $event.target.value)/
};
export default { //数据data(){return {searchText:组件中使用v-model}},//注册局部组件components:{custom-input:CustomInput}
}
/script
style scoped/style为了让组件正常工作这个组件内的 input 必须 将其 value attribute 绑定到一个名叫 value 的 prop 上 在其 input 事件被触发时将新的值通过自定义的 input 事件抛出 2.10.5 通过插槽分发内容
在prop子组件传参章节中我们学习到了子组件可以接受 props来接受父组件传递数据它可以是任何类型的 JavaScript 值。 但是模板内容呢在某些情况下我们可能希望把模板片段传递给子组件并让子组件在其自己的模板中渲染该片段我们就要用到插槽了插槽我们使用slot来进行占位
2.10.5.1 默认插槽
这里我们创建一个组件FilmClassify来展示分类信息组件中写入插槽slot
第一个在子组件组件film-classify插入模板ul...ul
第二个在子组件中插入一张风景图片
实例代码如下
templatedivfilm-classify title热门电影ul :style{marginLeft:45%,paddingInlineStart:0}li :styleliStyle肖申克的救赎/lili :styleliStyle1912/lili :styleliStyle零的执行人/li/ul/film-classifydiv :style{height:20px}/divfilm-classify title风景img src../imgs/风景.jpg alt :style{width:300px}/film-classify/div
/template
script
//JavaScript 对象来定义局部组件
var FilmClassify{data:function(){return {}},props:[title],template:divh3{{title}}/h3slot/slot/div
};
export default { //数据data(){return {liStyle:{textAlign:left}}},//注册局部组件components:{film-classify:FilmClassify}
}
/script
style scoped/style渲染效果 DOM解析会把子组件中的slot/slot插槽被插入的ul和img替换掉了
2.10.5.2 具名插槽
具名插槽其实只是在默认插槽的基础上给每个插槽起了名字作用为可以在组件中设置多个插槽可以更具体细分。首先给组件插槽起名字使用 namexxx。然后在子组件中插入模板时将模板内容插入指定名称的插槽中(slot插槽名称) 我们将默认插槽中实例的子组件插槽改成两个插槽一个命名为films一个命名为viewimg
修改后的代码
templatedivfilm-classify title热门电影ul :style{marginLeft:45%,paddingInlineStart:0} slotfilmsli :styleliStyle肖申克的救赎/lili :styleliStyle1912/lili :styleliStyle零的执行人/li/ulimg src../imgs/风景.jpg alt :style{width:300px} slotviewimg/film-classify/div
/template
script
//JavaScript 对象来定义局部组件
var FilmClassify{data:function(){return {}},props:[title],template:divh3{{title}}/h3slot namefilms/slotslot nameviewimg/slot/div
};
export default { //数据data(){return {liStyle:{textAlign:left}}},//注册局部组件components:{film-classify:FilmClassify}
}
/script
style scoped/style渲染效果 最终的DOM 2.10.5.3 作用域插槽
作用域插槽简单来说就是带有数据的插槽把组件中的数据绑定给插槽然后谁使用这个组件谁就能拿到这个数据使用也相当于一种数据通信其需要这样把数据绑定定义给组件插槽名称没有要求
然后就要使用组件时使用 slot-scopexxx 去接收或者直接使用 scope要注意的是此处标准一点最好写在 template 中
实例代码
templatedivfilm-classify title我的爱好template slot-scope{hobby}ul :style{marginLeft:45%,paddingInlineStart:0}li :styleliStyle v-for(h,index) in hobby :keyindex{{h}}/li/ul/template/film-classify/div
/template
script
//JavaScript 对象来定义局部组件
var FilmClassify{data:function(){return {hobby:[吃饭,睡觉,看电视]}},props:[title],template:divh3{{title}}/h3slot :hobbyhobby/slot/div
};
export default { //数据data(){return {liStyle:{textAlign:left}}},//注册局部组件components:{film-classify:FilmClassify}
}
/script
style scoped/style渲染效果 2.10.6 动态组件
实现动态组件需要使用内部组件component来实现内部组件的概念和属性 Vue内部提供的组件component组件作用是实现动态的渲染组件按需显示组件。 component 标签是 vue 内置的作用组件的占位符 is 属性的值表示要渲染的组件的名字 is 属性的值应该是组件在 components 节点下的注册名称 2.10.6.1 使用is 属性实现动态组件
我们会在一个多标签的界面中使用 is attribute 来切换不同的组件这里我们使用两个按钮来实现模拟tab动态切换的功能,实现组件的动态显示
实例代码
templatedivh3动态组件/h3divbutton clickcomName Left 展示Left组件/buttonbutton clickcomName Right 展示Right组件/button/divdiv!-- 要渲染的Left和Right组件 --component :iscomName/component/div/div
/template
script
//JavaScript 对象来定义局部组件
//left组件
var LeftCom{data:function(){return {}},template:divleft组件/div
};
//right组件
var RightCom{data:function(){return {}},template:divright组件/div
};
export default { //数据data(){return {comName:,txtMulti:}},//注册局部组件components:{Left:LeftCom,Right:RightCom},//方法methods:{}
}
/script
style scoped/style组件切换时的DOM解析 2.10.6.2 在动态组件上使用keep-alive
使用keep-alive我们可以在组件动态切换的时候使得组件实例能够被在它们第一次被创建的时候缓存下来从而不用在每次动态切换组件时都去创建一个新的组件实例
keep-alive 会把内部的组件进行缓存而不是销毁组件在使用 keep-alive 的时候可以通过 include 指定哪些组件需要被缓存或者通过 exclude 属性指定哪些组件不需要被缓存但是不要同时使用 include 和 exclude 这两个属性 keep-alive component :iscomName/component /keep-alive 2.10.7 异步组件
在大型应用中我们可能需要将应用分割成小一些的代码块并且只在需要的时候才从服务器加载一个模块。为了简化Vue 允许你以一个工厂函数的方式定义你的组件这个工厂函数会异步解析你的组件定义。Vue 只有在这个组件需要被渲染的时候才会触发该工厂函数且会把结果缓存起来供未来重渲染。例如
Vue.component(async-example, function (resolve, reject) {setTimeout(function () {// 向 resolve 回调传递组件定义resolve({template: divI am async!/div})}, 1000)
})
如你所见这个工厂函数会收到一个 resolve 回调这个回调函数会在你从服务器得到组件定义的时候被调用。你也可以调用 reject(reason) 来表示加载失败。这里的 setTimeout 是为了演示用的如何获取组件取决于你自己。一个推荐的做法是将异步组件和 webpack 的 code-splitting 功能一起配合使用
Vue.component(async-webpack-example, function (resolve) {// 这个特殊的 require 语法将会告诉 webpack// 自动将你的构建代码切割成多个包这些包// 会通过 Ajax 请求加载require([./my-async-component], resolve)
})
你也可以在工厂函数中返回一个 Promise
Vue.component(async-webpack-example,// 这个动态导入会返回一个 Promise 对象。() import(./my-async-component)
) 当使用局部注册的时候你也可以直接提供一个返回 Promise 的函数 components: {my-component: () import(./my-async-component)} 处理加载状态Vue2.3.0版本新增
异步组件工厂函数也可以返回一个如下格式的对象 const AsyncComponent () ({// 需要加载的组件 (应该是一个 Promise 对象)component: import(./MyComponent.vue),// 异步组件加载时使用的组件loading: LoadingComponent,// 加载失败时使用的组件error: ErrorComponent,// 展示加载时组件的延时时间。默认值是 200 (毫秒)delay: 200,// 如果提供了超时时间且组件加载也超时了// 则使用加载失败时使用的组件。默认值是Infinitytimeout: 3000
}) 注意如果你希望在 Vue Router的路由组件中使用上述语法的话你必须使用 Vue Router 2.4.0 版本。
2.10.8 解析DOM模板时的注意事项 字符串模板来源 单文件组件。以.vue后缀结尾的文件。内联模板字符串例如template:...。script typetext/x-template DOM 模板来源以.html后缀结尾的文件。 如果你想在 DOM 中直接书写 Vue 模板Vue 则必须从 DOM 中获取模板字符串。因为浏览器的原生 HTML 解析行为因此有一些需要注意的事项
大小写区分
HTML 标签和属性名称是不分大小写的所以浏览器会把任何大写的字符解释为小写。这意味着当你使用 DOM 内的模板时无论是PascalCase形式的组件名称、camelCase形式的prop名称还是v-on的事件名称都需要转换为相应等价的kebab-case(短横线连字符)形式
闭合标签
我们在上面的例子中已经使用过了闭合标签(self-closing tag) MyComponent /这是因为 Vue 的模板解析器将/作为标签关闭的标志无关其类型。然而在 DOM 模板中我们必须显式地写出关闭标签my-component/my-component。这是由于 HTML 只允许一小部分特殊的元素省略其关闭标签最常见的就是input和img。对于其他的元素来说如果你省略了关闭标签原生的 HTML 解析器会认为开启的标签永远没有结束用下面这个代码片段举个例子 my-component / !-- 我们想要在这里关闭标签... -- spanhello/span 将被解析为 my-component spanhello/span /my-component !-- 但浏览器会在这里关闭标签 -- 元素位置限制
某些 HTML 元素对于放在其中的元素类型有限制例如ul、ol、table和select相应的某些元素仅在放置于特定元素中时才会显示例如li、tr和option。 这将导致在使用带有此类限制元素的组件时出现问题。例如 table blog-post-row/blog-post-row /table 自定义的组件blog-post-row将作为无效的内容被忽略因而在最终呈现的输出中造成错误。我们可以使用特殊的is attribute 作为一种解决方案 table tr isvue:blog-post-row/tr /table 当使用在原生 HTML 元素上时is的值必须加上前缀vue:才可以被解析为一个 Vue 组件。这一点是必要的为了避免和原生的自定义内置元素相混淆。
3. 附录
vue官方学习文档
基础教程 https://v2.cn.vuejs.org/v2/guide/installation.htmlCLI服务学习 https://cli.vuejs.org/zh/guide/API学习 https://v2.cn.vuejs.org/v2/api/代码风格指南 https://v2.cn.vuejs.org/v2/style-guide
