谷粒商城-vue-笔记四

谷粒商城-vue-笔记四

1.MVVM 思想

M: 即 Model, 模型, 包括数据和一些基本操作

V: 即 View, 视图, 页面渲染结果

VM: 即 View-Model, 模型与视图间的双向操作(无需开发人员干涉)

在 MVVM 之前, 开发人员从后端获取需要的数据模型, 然后要通过 DOM 操作 Model 渲染到 View 中。 而后当用户操作视图, 我们还需要通过 DOM 获取 View 中的数据, 然后同步到Model 中。

而 MVVM 中的 VM 要做的事情就是把 DOM 操作完全封装起来, 开发人员不用再关心 Model和 View 之间是如何互相影响的:

  • 只要我们 Model 发生了改变, View 上自然就会表现出来。
  • 当用户修改了 View, Model 中的数据也会跟着改变。
    把开发人员从繁琐的 DOM 操作中解放出来, 把关注点放在如何操作 Model 上。

image-20210930145158566

2.Vue.js是什么?

Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。另一方面,当与现代化的工具链以及各种支持类库结合使用时,Vue 也完全能够为复杂的单页应用提供驱动。

Vue官网
Vue2.x文档
Git 地址

3.入门案例

1.安装

官网文档提供了 3 中安装方式:

  1. 直接 script 引入本地 vue 文件。 需要通过官网下载 vue 文件。

    下载地址打开后文件另存为,然后本地js引入html

  2. 通过 script 引入 CDN 代理。 需要联网, 生产环境可以使用这种方式

<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<!-- 生产环境版本,优化了尺寸和速度 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
  1. 通过 npm 安装。 这种方式也是官网推荐的方式, 需要 nodejs 环境。
  • 全局安装 vue-cli 工具

npm install -g vue-cli

  • 使用命令搭建项目

vue init <模板名称> <项目名称>

$ npm install -g vue-cli // 全局安装 vue-cli

$ vue init webpack first-vue // 初始化命令

? Project name first-test-vue // 项目名称
? Project description A Vue.js project // 项目描述
? Author Nzr // 作者
? Vue build standalone  // 独立构建
? Install vue-router? Yes  // 安装路由
? Use ESLint to lint your code? No  // 安装 ESLint 代码检测工具
? Pick an ESLint preset Standard
? Setup unit tests with Karma + Mocha? Yes
? Setup e2e tests with Nightwatch? No // 端到端测试

   vue-cli · Generated "first-vue".

   To get started:

     cd first-test-vue // cd 进入 first-vue 项目
     npm install // 安装依赖
     npm run dev // 开始运行:webpack 持续运行
  • 下载依赖

npm install

  • 运行开发测试服务器

npm run dev

  • 修改npm仓库地址为淘宝源

npm config set registry https://registry.npm.taobao.org/

  • 还原配置

npm config delete registry

2.创建示例项目

1.新建文件夹 vue, 并使用 vscode 打开

2.使用 vscode 控制台, npm install -y

项目会生成 package-lock.json 文件, 类似于 maven 项目的 pom.xml 文件

3.使用 npm install vue, 给项目安装 vue;

使用 npm install vue, 给项目安装 vue;

3.HelloWorld

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <div id="app">
       <!--页面中的`h2`元素中, 我们通过{
    
    {name}}的方式, 来渲染刚刚定义的 name 属性  -->
        <h2>hello word {
   
   {name}}</h2>
    </div>
</body>
<script src="./node_modules/vue/dist/vue.js"></script>
<script>
    //首先通过 new Vue()来创建 Vue 实例
    let app = new Vue({
      
      
        //el: 是 element 的缩写, 通过 id 选中要渲染的页面元素, 本例中是一个 div
        el: "#app",
        //data: 数据, 数据是一个对象, 里面有很多属性, 都可以渲染到视图中
        data: {
      
      
            //name: 这里我们指定了一个 name 属性
            name: "lisi"
        }
    })
</script>

</html>

image-20210930153938427

当你修改 name 属性时, 页面会跟着变化:

image-20210930154140113

4.双向绑定

我们不需要关注他们为什么会建立起来关联, 以及页面如何变化, 我们只需要做好数据和视图的关联即可( MVVM)

<body>
    <div id="app">
        <input type="text" v-model="num">
        <h2>
            {
   
   {name}}, 非常帅! ! ! 有{
   
   {num}}个人为他点赞。
        </h2>
    </div>
    <script src="./node_modules/vue/dist/vue.js"></script>
    <script>
        // 创建 vue 实例
        let app = new Vue({
      
      
            el: "#app", // el 即 element, 该 vue 实例要渲染的页面元素
            data: {
      
       // 渲染页面需要的数据
                name: "张三",
                num: 5
            }
        });
    </script>
</body>

效果: 我们修改表单项, num 会发生变化。 我们修改 num, 表单项也会发生变化。 为了实时观察到这个变化, 我们将 num 输出到页面。

image-20210930173557166

5.事件处理

  • 这里用v-on指令绑定点击事件, 而不是普通的onclick, 然后直接操作 num
  • 普通 click 是无法直接操作 num 的。
<body>
    <div id="app">
        <input type="text" v-model="num">
        <button v-on:click="num++">关注</button>
        <h2>
            {
   
   {name}}, 非常帅! ! ! 有{
   
   {num}}个人为他点赞。
        </h2>
    </div>
    <script src="./node_modules/vue/dist/vue.js"></script>
    <script>
        // 创建 vue 实例
        let app = new Vue({
      
      
            el: "#app", // el 即 element, 该 vue 实例要渲染的页面元素
            data: {
      
       // 渲染页面需要的数据
                name: "张三",
                num: 5
            }
        });
    </script>
</body>

image-20210930174251208

6.简单使用总结:

使用 Vue 实例管理 DOM

DOM 与数据/事件等进行相关绑定

我们只需要关注数据, 事件等处理, 无需关心视图如何进行修改

4.指令

1.插值表达式

1.Mustache 语法{ {}}

格式: { {表达式}}

说明:

  • 该表达式支持 JS 语法, 可以调用 js 内置函数(必须有返回值)
  • 表达式必须有返回结果。 例如 1 + 1, 没有结果的表达式不允许使用, 如: let a = 1 + 1;
  • 可以直接获取 Vue 实例中定义的数据或函数

2.插值闪烁

使用{ {}}方式在网速较慢时会出现问题。 在数据未加载完成时, 页面会显示出原始的{ {}},加载完毕后才显示正确数据, 我们称为插值闪烁。

我们将网速调慢一些, 然后刷新页面, 试试看刚才的案例:

image-20210930175244525

3.v-text 和 v-html

可以使用 v-text 和 v-html 指令来替代{ {}}

  • v-text:将数据输出到元素内部, 如果输出的数据有 HTML 代码, 会作为普通文本输出
  • v-html:将数据输出到元素内部, 如果输出的数据有 HTML 代码, 会被渲染
	<div id="app">
        {
   
   {msg}}  {
   
   {1+1}}  {
   
   {hello()}}<br/><!--Mustache -->
        <span v-html="msg"></span><!--v-html -->
        <br/>
        <span v-text="msg"></span><!--v-text -->
    </div>
     <script>
            new Vue({
      
      
                el:"#app",
                data:{
      
      
                    msg:"<h1>Hello</h1>",
                    link:"http://www.baidu.com"
                },
                methods:{
      
      
                    hello(){
      
      
                        return "World"
                    }
                }
            })
        </script>

效果:

image-20210930180626830

4.v-bind

html 属性不能使用双大括号形式绑定, 我们使用 v-bind 指令给 HTML 标签属性绑定值;而且在将 v-bind 用于 classstyle 时, Vue.js 做了专门的增强。

1.绑定class v-bind:class
<div id="app"> 
        <span v-bind:class="{active:isActive,'text-danger':hasError}">你好</span>
 </div>
		<script>
        let vm = new Vue({
      
      
            el:"#app",
            data:{
      
      
                isActive:true
            }
        })
        </script>

效果:修改 isActive ,class属性消失

image-20211003101904821

image-20211003101918415

image-20211003101925905

2.绑定style v-bing:style

v-bind:style 的对象语法十分直观, 看着非常像 CSS, 但其实是一个 JavaScript 对象。 style
属性名可以用驼峰式 (camelCase) 或短横线分隔 (kebab-case, 这种方式记得用单引号括起
来) 来命名。
例如: font-size–>fontSize

<!-- 给html标签的属性绑定 -->
    <div id="app">
        <!-- class,style  {class名:加上?}-->
        <span v-bind:class="{active:isActive,'text-danger':hasError}"
          :style="{color: color1,fontSize: size}">你好</span>


    </div>

    <script src="../node_modules/vue/dist/vue.js"></script>

    <script>
        let vm = new Vue({
      
      
            el:"#app",
            data:{
      
      
                isActive:true,
                hasError:true,
                color1:'red',
                size:'36px'
            }
        })
    </script>

效果:可以为标签的style属性动态绑定值

image-20211003102349024

3.绑定其他任意属性
<div id="app"> 
        <a v-bind:href="link">gobaidu</a>
</div>
<script>
        let vm = new Vue({
      
      
            el:"#app",
            data:{
      
      
                link: "http://www.baidu.com",
            }
        })
    </script>

4.v-bind 缩写 :

如:v-bind:class 可以写做:class

5.v-modle

之前的 v-text、 v-html、 v-bind 可以看做是单向绑定, 数据影响了视图渲染, 但是反过来就不行。 v-model 是双向绑定, 视图(View) 和模型(Model) 之间会互相影响。

既然是双向绑定, 一定是在视图中可以修改数据, 这样就限定了视图的元素类型。 目前v-model 的可使用元素有:

  • input
  • select
  • textarea
  • checkbox
  • radio
  • components(Vue 中的自定义组件)

基本上除了最后一项, 其它都是表单的输入项。

<!-- 表单项,自定义组件 -->
    <div id="app">

        精通的语言:
        <br/>
            <input type="checkbox" v-model="language" value="Java"> java<br/>
            <input type="checkbox" v-model="language" value="PHP"> PHP<br/>
            <input type="checkbox" v-model="language" value="Python"> Python<br/>
        选中了 {
   
   {language.join(",")}}<!--此处将数组转换为以逗号分隔的字符串 -->
    </div>
    
    <script src="../node_modules/vue/dist/vue.js"></script>

    <script>
        let vm = new Vue({
      
      
            el:"#app",
            data:{
      
      
                language: []
            }
        })
    </script>

效果:

image-20211003103716464

多个CheckBox对应一个 model 时, model 的类型是一个数组, 单个 checkbox 值默认是 boolean 类型

radio 对应的值是 input 的 value 值

texttextarea 默认对应的 model 是字符串

select单选对应字符串, 多选对应也是数组

6.v-on

1.基本用法

v-on 指令用于给页面元素绑定事件。

语法: v-on:事件名=“js 片段或函数名”

	<div id="app">
                
        <!--事件中直接写js片段-->
        <button v-on:click="num++">点赞</button>
        <!--事件指定一个回调函数,必须是Vue实例中定义的函数-->
        <button @click="cancle">取消</button>
        <!--  -->
        <h1>有{
   
   {num}}个赞</h1>
    </div>
	<script>
        new Vue({
      
      
            el:"#app",
            data:{
      
      
                num: 1
            },
            methods:{
      
      
                cancle(){
      
      
                    this.num--;
                }
            }
        })
    </script>

效果:

点击点赞按钮点赞数加一,点击取消按钮触发cancle方法点赞数减一

另外, 事件绑定可以简写, 例如v-on:click='cancle'可以简写为@click='cancle'

image-20211003105230076

2.v-on事件修饰符

在事件处理程序中调用 event.preventDefault()event.stopPropagation() 是非常常见的需求。 尽管我们可以在方法中轻松实现这点, 但更好的方式是: 方法只有纯粹的数据逻辑,而不是去处理 DOM 事件细节。
为了解决这个问题, Vue.js 为 v-on 提供了事件修饰符。 修饰符是由点开头的指令后缀来表示的。

常用的事件修饰符:

.stop : 阻止事件冒泡到父元素

个人理解:比如点击事件,子模块在父模块内部,当子模块点击事件触发时,父模块点击事件也被触发了,阻止事件冒泡就是当子模块事件触发时,只触发子模块事件,父模块对应事件不用相应

.prevent: 阻止默认事件发生
.capture: 使用事件捕获模式
.self: 只有元素自身触发事件才执行。 (冒泡或捕获的都不执行)
.once: 只执行一次

	 <!-- 事件修饰符 -->
        <!-- 大div点击事件只能触发一次 -->
        <div style="border: 1px solid red;padding: 20px;" v-on:click.once="hello">
            大div
            <!-- 小div阻止事件冒泡 -->
            <div style="border: 1px solid blue;padding: 20px;" @click.stop="hello">
                小div <br />
                <!-- 超链接阻止了默认事件并且阻止事件冒泡,点击后不会跳转至对应地址 -->
                <a href="http://www.baidu.com" @click.prevent.stop="hello">去百度</a>
            </div>
        </div>
        <script>
                new Vue({
      
      
                    el:"#app",
                    methods:{
      
      
                        hello(){
      
      
                            alert("点击了")
                        }
                    }
                })
            </script>
3.按键修饰符

在监听键盘事件时, 我们经常需要检查常见的键值。 Vue 允许为 v-on 在监听键盘事件时添加按键修饰符:

全部的按键别名:没有别名的键可以查常见的键值
.enter
.tab
.delete (捕获“删除”和“退格”键)
.esc
.space
.up
.down
.left
.right

<!-- 按键修饰符: -->
		<!-- keyup.up 当上键抬起时num+2 -->
		<!-- keyup.up 当下键抬起时num-2 -->
		<!-- click.ctrl 当按住crtl点击时num=10 -->
        <input type="text" v-model="num" v-on:keyup.up="num+=2" @keyup.down="num-=2" @click.ctrl="num=10"><br />
		 <script>
        new Vue({
      
      
            el:"#app",
            data:{
      
      
                num: 1
            }
        })
    </script>
4.组合按键

可以用如下修饰符来实现仅在按下相应按键时才触发鼠标或键盘事件的监听器

.ctrl
.alt
.shift

<!-- Alt + C -->
<input @keyup.alt.67="clear">
<!-- Ctrl + Click --><
div @click.ctrl="doSomething">Do something</div>

7.v-for

遍历数据渲染页面是非常常用的需求, Vue 中通过 v-for 指令来实现

1.遍历数组

语法: v-for="(item,index) in items "

items: 要遍历的数组, 需要在 vue 的 data 中定义好。
item: 迭代得到的当前正在遍历的元素

index: 迭代到的当前元素索引, 从 0 开始

 <div id="app">
        <ul>
            <li v-for="(user,index) in users" :key="user.name">
                <!-- 1、显示user信息:v-for="item in items" -->
               当前索引:{
   
   {index}} ==> {
   
   {user.name}}  ==>   {
   
   {user.gender}} ==>{
   
   {user.age}} <br>
        </ul>

    </div>
	<script>         
        let app = new Vue({
      
      
            el: "#app",
            data: {
      
      
                users: [{
      
       name: '柳岩', gender: '女', age: 21 },
                {
      
       name: '张三', gender: '男', age: 18 },
                {
      
       name: '范冰冰', gender: '女', age: 24 },
                {
      
       name: '刘亦菲', gender: '女', age: 18 },
                {
      
       name: '古力娜扎', gender: '女', age: 25 }],
            },
        })
    </script>

结果:

image-20211003161613586

2.遍历对象

1 个参数时, 得到的是对象的属性值
2 个参数时, 第一个是属性值, 第二个是属性名
3 个参数时, 第三个是索引, 从 0 开始

语法

v-for=“value in object”
v-for="(value,key) in object"
v-for="(value,key,index) in object"

<div id="app">
        <ul>
            <li v-for="(user,index) in users" :key="user.name" v-if="user.gender == ''">
                <!-- 1、显示user信息:v-for="item in items" -->
               当前索引:{
   
   {index}} ==> {
   
   {user.name}}  ==>   {
   
   {user.gender}} ==>{
   
   {user.age}} <br>
                <!-- 2、获取数组下标:v-for="(item,index) in items" -->
                <!-- 3、遍历对象:
                        v-for="value in object"
                        v-for="(value,key) in object"
                        v-for="(value,key,index) in object" 
                -->
                对象信息:
                <span v-for="(v,k,i) in user">{
   
   {k}}=={
   
   {v}}=={
   
   {i}};</span>
                <!-- 4、遍历的时候都加上:key来区分不同数据,提高vue渲染效率 -->
            </li>

            
        </ul>

    
    </div>
    <script src="../node_modules/vue/dist/vue.js"></script>
    <script>         
        let app = new Vue({
      
      
            el: "#app",
            data: {
      
      
                users: [{
      
       name: '柳岩', gender: '女', age: 21 },
                {
      
       name: '张三', gender: '男', age: 18 },
                {
      
       name: '范冰冰', gender: '女', age: 24 },
                {
      
       name: '刘亦菲', gender: '女', age: 18 },
                {
      
       name: '古力娜扎', gender: '女', age: 25 }],
                nums: [1,2,3,4,4]
            },
        })
    </script>

image-20211003155558197

3.Key

用来标识每一个元素的唯一特征, 这样 Vue 可以使用“就地复用” 策略有效的提高渲染的效率。

如果 items 是数组, 可以使用 index 作为每个元素的唯一标识
如果 items 是对象数组, 可以使用 item.id 作为每个元素的唯一标识

<ul>
    <!--如果 items 是数组, 可以使用 index 作为每个元素的唯一标识-->
	<li v-for="(item,index) in items" :key=”index”></li>
</ul>
<ul>
    <!--如果 items 是对象数组, 可以使用 item.id 作为每个元素的唯一标识  -->
	<li v-for="item in items" :key=”item.id”></li>
</ul>

8.v-ifv-show

1.基本使用

v-if, 顾名思义, 条件判断。 当得到结果为 true 时, 所在的元素才会被渲染。

v-show, 当得到结果为 true 时, 所在的元素才会被显示。

语法: v-if=“布尔表达式”, v-show=“布尔表达式”,

 <!-- 
        v-if,顾名思义,条件判断。当得到结果为true时,所在的元素才会被渲染。
        v-show,当得到结果为true时,所在的元素才会被显示。 
    -->
    <div id="app">
        <button v-on:click="show = !show">点我呀</button>
        <!-- 1、使用v-if显示 -->
        <h1 v-if="show">if=看到我....</h1>
        <!-- 2、使用v-show显示 -->
        <h1 v-show="show">show=看到我</h1>
    </div>

    <script src="../node_modules/vue/dist/vue.js"></script>
        
    <script>
        let app = new Vue({
      
      
            el: "#app",
            data: {
      
      
                show: true
            }
        })
    </script>

结果:

区别:使用v-if等于false时标签不会被渲染,使用v-show等于false时标签会被渲染,但是页面不会显示

image-20211003160716823

image-20211003160726954

2.与v-for使用

当 v-if 和 v-for 出现在一起时, v-for 优先级更高。 也就是说, 会先遍历, 再判断条件

 <div id="app">
        <ul>
            <li v-for="(user,index) in users" :key="user.name" v-if="user.gender == ''">
                <!-- 1、显示user信息:v-for="item in items" -->
               当前索引:{
   
   {index}} ==> {
   
   {user.name}}  ==>   {
   
   {user.gender}} ==>{
   
   {user.age}} <br>
        </ul>

    </div>
	<script>         
        let app = new Vue({
      
      
            el: "#app",
            data: {
      
      
                users: [{
      
       name: '柳岩', gender: '女', age: 21 },
                {
      
       name: '张三', gender: '男', age: 18 },
                {
      
       name: '范冰冰', gender: '女', age: 24 },
                {
      
       name: '刘亦菲', gender: '女', age: 18 },
                {
      
       name: '古力娜扎', gender: '女', age: 25 }],
            },
        })
    </script>

结果:筛选出了性别为女的对象进行显示

image-20211003161833569

9.v-elsev-else-if

v-else 元素必须紧跟在带 v-if 或者 v-else-if 的元素的后面, 否则它将不会被识别

<div id="app">
        <button v-on:click="random=Math.random()">点我呀</button>
        <span>{
   
   {random}}</span>

        <h1 v-if="random>=0.75">
            看到我啦?! &gt;= 0.75
        </h1>

        <h1 v-else-if="random>=0.5">
            看到我啦?! &gt;= 0.5
        </h1>

        <h1 v-else-if="random>=0.2">
            看到我啦?! &gt;= 0.2
        </h1>

        <h1 v-else>
            看到我啦?! &lt; 0.2
        </h1>

    </div>
    <script src="../node_modules/vue/dist/vue.js"></script>
        
    <script>         
        let app = new Vue({
      
      
            el: "#app",
            data: {
      
       random: 1 }
        })     
    </script>

结果:

image-20211003162135688

5.计算属性和侦听器

1.计算属性(computed)

某些结果是基于之前数据实时计算出来的, 我们可以利用计算属性。

	<div id="app">
        <!-- 某些结果是基于之前数据实时计算出来的,我们可以利用计算属性。来完成 -->
        <ul>
            <li>西游记; 价格:{
   
   {xyjPrice}},数量:<input type="number" v-model="xyjNum"> </li>
            <li>水浒传; 价格:{
   
   {shzPrice}},数量:<input type="number" v-model="shzNum"> </li>
            <li>总价:{
   
   {totalPrice}}</li>
            {
   
   {msg}}
        </ul>
    </div>
    <script src="../node_modules/vue/dist/vue.js"></script>

    <script>
        new Vue({
      
      
            el: "#app",
            data: {
      
      
            },
            computed: {
      
      
                totalPrice(){
      
      
                    return this.xyjPrice*this.xyjNum + this.shzPrice*this.shzNum
                }
            },
            //watch可以让我们监控一个值的变化。从而做出相应的反应。
            watch: {
      
      
                xyjNum(newVal,oldVal){
      
      
                    if(newVal>=3){
      
      
                        this.msg = "库存超出限制";
                        this.xyjNum = 3
                    }else{
      
      
                        this.msg = "";
                    }
                }
            },
        })
    </script>

image-20211003162728405

2.过滤器(filters)

过滤器不改变真正的data, 而只是改变渲染的结果, 并返回过滤后的版本。 在很多不同的情况下, 过滤器都是有用的, 比如尽可能保持 API 响应的干净, 并在前端处理数据的格式。

| 管道符号: 表示使用后面的过滤器处理前面的数据

{ {user.gender | genderFilter}}

过滤器常用来处理文本格式化的操作。过滤器可以用在两个地方:双花括号插值和 v-bind 表达式

 <!-- 过滤器常用来处理文本格式化的操作。过滤器可以用在两个地方:双花括号插值和 v-bind 表达式 -->
    <div id="app">
        <ul>
            <li v-for="user in userList">
                {
   
   {user.id}} ==> {
   
   {user.name}} ==> {
   
   {user.gender == 1?"男":"女"}} ==>
                {
   
   {user.gender | genderFilter}} ==> {
   
   {user.gender | gFilter}}
            </li>
        </ul>
    </div>
    <script src="../node_modules/vue/dist/vue.js"></script>

    <script>
		//全局过滤器
        //任何 vue 实例都可以使用
        Vue.filter("gFilter", function (val) {
      
      
            if (val == 1) {
      
      
                return "男~~~";
            } else {
      
      
                return "女~~~";
            }
        })

        let vm = new Vue({
      
      
            el: "#app",
            data: {
      
      
                userList: [
                    {
      
       id: 1, name: 'jacky', gender: 1 },
                    {
      
       id: 2, name: 'peter', gender: 0 }
                ]
            },
            filters: {
      
      
                 filters 定义局部过滤器,只可以在当前vue实例中使用
                //注册在当前 vue 实例中, 只有当前实例能用
                genderFilter(val) {
      
      
                    if (val == 1) {
      
      
                        return "男";
                    } else {
      
      
                        return "女";
                    }
                }
            }
        })
    </script>

此处将gender由0/1通过filters转换为男/女,使用三元运算符,局部过滤器,全局过滤器效果一致

image-20211003163417833

6.组件化

在大型应用开发的时候, 页面可以划分成很多部分。 往往不同的页面, 也会有相同的部分。例如可能会有相同的头部导航。
但是如果每个页面都独自开发, 这无疑增加了我们开发的成本。 所以我们会把页面的不同部分拆分成独立的组件, 然后在不同页面就可以共享这些组件, 避免重复开发。

  • 组件其实也是一个 Vue 实例, 因此它在定义时也会接收: data、 methods、 生命周期函数等
  • 不同的是组件不会与页面的元素绑定, 否则就无法复用了, 因此没有 el 属性。
  • 但是组件渲染需要 html 模板, 所以增加了 template 属性, 值就是 HTML 模板
  • 全局组件定义完毕, 任何 vue 实例都可以直接在 HTML 中通过组件名称来使用组件了
  • data 必须是一个函数, 不再是一个对象。

[官方示例](https://cn.vuejs.org/v2/guide/components.html#data-%E5%BF%85%E9%A1%BB%E6%98%AF%E4
%B8%80%E4%B8%AA%E5%87%BD%E6%95%B0)

因为组件的复用,如果是一个对象,那么其中一个组件的data发生改变时其他组件的data都会改变,使用函数的原因是利用js函数的作用域来解决此问题

	<div id="app">
        <button v-on:click="count++">我被点击了 {
   
   {count}} 次</button>

        <counter></counter>
        <counter></counter>
        <counter></counter>
        <counter></counter>
        <counter></counter>

        <button-counter></button-counter>
    </div>
    <script src="../node_modules/vue/dist/vue.js"></script>


    <script>
        //1、全局声明注册一个组件
        Vue.component("counter", {
      
      
            template: `<button v-on:click="count++">我被点击了 {
       
       {count}} 次</button>`,
            data() {
      
      
                return {
      
      
                    count: 1
                }
            }
        });

        //2、局部声明一个组件
        const buttonCounter = {
      
      
            template: `<button v-on:click="count++">我被点击了 {
       
       {count}} 次~~~</button>`,
            data() {
      
      
                return {
      
      
                    count: 1
                }
            }
        };

        new Vue({
      
      
            el: "#app",
            data: {
      
      
                count: 1
            },
            components: {
      
      
                'button-counter': buttonCounter
            }
        })
    </script>

7.生命周期钩子函数

每个 Vue 实例在被创建时都要经过一系列的初始化过程 : 创建实例, 装载模板, 渲染模板等等。 Vue 为生命周期中的每个状态都设置了钩子函数(监听函数) 。 每当 Vue 实例处于不同的生命周期时, 对应的函数就会被触发调用。
生命周期: 你不需要立马弄明白所有的东西。

1.生命周期图示

img

2.钩子函数

beforeCreated: 我们在用 Vue 时都要进行实例化, 因此, 该函数就是在 Vue 实例化时调用, 也可以将他理解为初始化函数比较方便一点, 在 Vue1.0 时, 这个函数的名字就是init。

created: 在创建实例之后进行调用。

beforeMount: 页面加载完成, 没有渲染。 如: 此时页面还是{ {name}}

mounted: 我们可以将他理解为原生 js 中的 window.οnlοad=function({.,.}),或许大家也在用 jquery, 所以也可以理解为 jquery 中的$(document).ready(function(){….}), 他的功能就是: 在 dom 文档渲染完毕之后将要执行的函数, 该函数在 Vue1.0 版本中名字为compiled。 此时页面中的{ {name}}已被渲染成张三

beforeDestroy: 该函数将在销毁实例前进行调用 。

destroyed: 改函数将在销毁实例时进行调用。

beforeUpdate: 组件更新之前。

updated: 组件更新之后。

<div id="app">
        <span id="num">{
   
   {num}}</span>
        <button @click="num++">赞!</button>
        <h2>{
   
   {name}},有{
   
   {num}}个人点赞</h2>
    </div>

    <script src="../node_modules/vue/dist/vue.js"></script>
    
    <script>
        let app = new Vue({
      
      
            el: "#app",
            data: {
      
      
                name: "张三",
                num: 100
            },
            methods: {
      
      
                show() {
      
      
                    return this.name;
                },
                add() {
      
      
                    this.num++;
                }
            },
            beforeCreate() {
      
      
                console.log("=========beforeCreate=============");
                console.log("数据模型未加载:" + this.name, this.num);
                console.log("方法未加载:" + this.show());
                console.log("html模板未加载:" + document.getElementById("num"));
            },
            created: function () {
      
      
                console.log("=========created=============");
                console.log("数据模型已加载:" + this.name, this.num);
                console.log("方法已加载:" + this.show());
                console.log("html模板已加载:" + document.getElementById("num"));
                console.log("html模板未渲染:" + document.getElementById("num").innerText);
            },
            beforeMount() {
      
      
                console.log("=========beforeMount=============");
                console.log("html模板未渲染:" + document.getElementById("num").innerText);
            },
            mounted() {
      
      
                console.log("=========mounted=============");
                console.log("html模板已渲染:" + document.getElementById("num").innerText);
            },
            beforeUpdate() {
      
      
                console.log("=========beforeUpdate=============");
                console.log("数据模型已更新:" + this.num);
                console.log("html模板未更新:" + document.getElementById("num").innerText);
            },
            updated() {
      
      
                console.log("=========updated=============");
                console.log("数据模型已更新:" + this.num);
                console.log("html模板已更新:" + document.getElementById("num").innerText);
            }
        });
    </script>

页面刷新完成时:

image-20211003170012544

点击一次点赞按钮:

image-20211003170226351

8.vue模块化开发

1、 npm install webpack -g

全局安装 webpack

2、 npm install -g @vue/cli-init

全局安装 vue 脚手架

3、 初始化 vue 项目;

vue init webpack appname: vue 脚手架使用 webpack 模板初始化一个 appname 项目

4、 启动 vue 项目;

项目的 package.json 中有 scripts, 代表我们能运行的命令
npm start = npm run dev: 启动项目
npm run build: 将项目打包

5、 模块化开发

1、 项目结构

image-20211003170735562

运行流程

进入页面首先加载 index.html 和 main.js 文件。

main.js 导入了一些模块【vue、 app、 router】 , 并且创建 vue 实例, 关联 index.html页面的

元素。 使用了 router, 导入了 App 组件。 并且使用标签引用了这个组件

第一次默认显示 App 组件。 App 组件有个图片和, 所以显示了图片。但是由于代表路由的视图, 默认是访问/#/路径(router 路径默认使用HASH 模式) 。 在 router 中配置的/是显示 HelloWorld 组件。

所以第一次访问, 显示图片和 HelloWorld 组件。

我们尝试自己写一个组件, 并且加入路由。 点击跳转。 需要使用<router-linkto="/foo">Go to Foo标签

2、 Vue 单文件组件

Vue 单文件组件模板有三个部分;

Template: 编写模板

Script: vue 实例配置

Script: vue 实例配置

<template>
 
</template>

<script>
export default {
  name: 'HelloWorld',
  data () {
    return {
      msg: 'Welcome to Your Vue.js App~~~~'
    }
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>

</style>

3.vscode 添加用户代码片段(快速生成 vue 模板)

文件–>首选项–>用户代码片段–>点击新建代码片段–取名 vue.json 确定

{
    
    
	"生成 vue 模板": {
    
    
		"prefix": "vue",
		"body": [
			"<template>",
			"<div></div>",
			"</template>",
			"",
			"<script>",
	"//这里可以导入其他文件(比如: 组件, 工具 js, 第三方插件 js, json文件, 图片文件等等) ",
	"//例如: import 《组件名称》 from '《组件路径》 ';",
			"",
			"export default {",
			"//import 引入的组件需要注入到对象中才能使用",
			"components: {},",
			"props: {},",
			"data() {",
			"//这里存放数据",
			"return {",
			"",
			"};",
			"},",
			"//计算属性 类似于 data 概念",
			"computed: {},",
			"//监控 data 中的数据变化",
			"watch: {},",
			"//方法集合",
			"methods: {",
			"",
			"},",
			"//生命周期 - 创建完成(可以访问当前 this 实例) ",
			"created() {",
			"",
			"},",
			"//生命周期 - 挂载完成(可以访问 DOM 元素) ",
			"mounted() {",
			"",
			"},",
			"beforeCreate() {}, //生命周期 - 创建之前",
			"beforeMount() {}, //生命周期 - 挂载之前",
			"beforeUpdate() {}, //生命周期 - 更新之前",
			"updated() {}, //生命周期 - 更新之后",
			"beforeDestroy() {}, //生命周期 - 销毁之前",
			"destroyed() {}, //生命周期 - 销毁完成",
	"activated() {}, //如果页面有 keep-alive 缓存功能, 这个函数会触发",
	"}",
			"</script>",
			"<style lang='scss' scoped>",
			"//@import url($3); 引入公共 css 类",
			"$4",
			"</style>"
		],
		"description": "生成 vue 模板"
	}
}
4.生成模板
<template>
  <div></div>
</template>

<script>
//这里可以导入其他文件(比如: 组件, 工具 js, 第三方插件 js, json文件, 图片文件等等)
//例如: import 《组件名称》 from '《组件路径》 ';

export default {
  //import 引入的组件需要注入到对象中才能使用
  components: {},
  props: {},
  data() {
    //这里存放数据
    return {};
  },
  //计算属性 类似于 data 概念
  computed: {},
  //监控 data 中的数据变化
  watch: {},
  //方法集合
  methods: {},
  //生命周期 - 创建完成(可以访问当前 this 实例)
  created() {},
  //生命周期 - 挂载完成(可以访问 DOM 元素)
  mounted() {},
  beforeCreate() {}, //生命周期 - 创建之前
  beforeMount() {}, //生命周期 - 挂载之前
  beforeUpdate() {}, //生命周期 - 更新之前
  updated() {}, //生命周期 - 更新之后
  beforeDestroy() {}, //生命周期 - 销毁之前
  destroyed() {}, //生命周期 - 销毁完成
  activated() {}, //如果页面有 keep-alive 缓存功能, 这个函数会触发
};
</script>
<style lang='scss' scoped>
//@import url(); 引入公共 css 类
</style>
4、 导入 element-ui 快速开发
1、 安装 element-ui: npm i element-ui
2、 在 main.js 中引入 element-ui 就可以全局使用了。
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
Vue.use(ElementUI)
3、 将 App.vue 改为 element-ui 中的后台布局
4、 添加测试路由、 组件, 测试跳转逻辑

(1) 、 参照文档 el-menu 添加 router 属性
(2) 、 参照文档 el-menu-item 指定 index 需要跳转的地址

猜你喜欢

转载自blog.csdn.net/qq_31745863/article/details/120601435