IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> Vue _ 教程版 01 -> 正文阅读

[JavaScript知识库]Vue _ 教程版 01

目录

目标

一、Vue基础

1.1、介绍

1.2、声明式渲染和组件化

1.3、MVVM模式

二、vue基础使用

2.1、传统dom操作

2.2、使用vue实现

2.3、vue devtools工具安装

2.4、Vue实现数据绑定的原理

三、模板语法

3.1、插值表达式

3.2、指令

四、常用指令


目标

  • 在网页中实例化vue对象
  • 知道vue数据绑定原理
  • 熟练使用插值表示式
  • 掌握vue指令

一、Vue基础

1.1、介绍

官网:https://cn.vuejs.org/

Vue (读音 /vju?/,类似于?view)? , Vue.js是一套构建用户?界面?渐进式框架 。Vue 采用自底向上增量开发的设计。Vue 的核心库?只关注视图层?,它不仅易于上手,还便于与第三方库或既有项目整合。另一方面,当与?现代化的工具链?以及各种?支持类库?结合使用时,Vue 也完全能够为复杂的单页应用程序提供驱动。( spa 单页面应用,所有的显示都在一个页面当中)

渐进式:一步一步,不是说你必须一次把所有的东西都用上

自底向上设计:是一种设计程序的过程和方法,就是先编写出基础程序段,然后再逐步扩大规模、补充和升级某些功能,实际上是一种自底向上构造程序的过程。

?

Vue从设计角度来讲,虽然能够涵盖这张图上所有的东西,但是你并不需要一上手就把所有东西全用上,都是可选的。声明式渲染和组系统是Vue的核心库所包含内容,而路由、状态管理、构建工具都有专门解决方案。这些解决方案相互独立,你可以在核心的基础上任意选用其他的部件,不一定要全部整合在一起。

?

1.2、声明式渲染和组件化

  • 声明式渲染

Vue.js 的核心是一个允许采用简洁的?模板语法?来声明式的将数据渲染进 DOM 的系统

# html

<div id="app">

??<!-- 渲染 Hello Vue -->

??{{ message }}

</div>

# js

var vm = new Vue({

??el: '#app',

??// 数据源

??data: {

// 声明一下变量

????message: 'Hello Vue!'

??}

})

  • 组件化应用构建

组件系统是?Vue 的另一个重要概念,因为它是一种抽象,允许我们使用小型、独立和通常可复用的组件构建大型应用。几乎任意类型的应用界面都可以抽象为一个组件树。

1.3、MVVM模式

MVVM是Model-View-ViewModel的简写。它本质上就是MVC 的改进版。MVVM 就是将其中的View 的状态和行为抽象化,让我们将视图 UI 和业务逻辑分开。当然这些事 ViewModel 已经帮我们做了,它可以取出 Model 的数据同时帮忙处理 View 中由于需要展示内容而涉及的业务逻辑。

vue使用MVVM响应式编程模型,避免直接操作DOM , 降低DOM操作的复杂性。

?

MVVM:页面输入改变数据,数据改变影响页面数据展示与渲染

M(model):普通的 javascript 数据对象

V(view):前端展示页面

VM(ViewModel):用于双向绑定数据与页面,对于我们的课程来说,就是 vue 的实例

优点:

  • 低耦合。视图(View)可以独立于Model变化和修改,一个ViewModel可以绑定到不同的View上,当View变化的时候Model可以不变,当Model变化的时候View也可以不变。
  • 可重用性。你可以把一些视图逻辑放在一个ViewModel里面,让很多view重用这段视图逻辑。
  • 独立开发。开发人员可以专注于业务逻辑和数据的开发(ViewModel),设计人员可以专注于页面设计。
  • 可测试。界面素来是比较难于测试的,而现在测试可以针对ViewModel来写。

二、vue基础使用

2.1、传统dom操作

使用js对html页面结构中的指定的区域输出数据

传统dom操作数据显示 :?

<div>
    <h3 id="app">abcd</h3>
    <input type="text" id="msg">
  </div>

  <script>
    var data = {
      username: '张三'
    }
    document.querySelector('#app').innerHTML = data.username
    // document.querySelector('#app').textContent = data.username
    // 查看当前dom的类型 1元素 3文本
    // console.log(document.querySelector('#app').nodeType)
    // console.log(document.querySelector('#app').firstChild.nodeType)
    document.querySelector('#msg').value = data.username
    document.querySelector('#msg').addEventListener('input', function () {
      // 让使用数据源的标签更新视图
      document.querySelector('#app').innerHTML = this.value.trim()
      // 更新数据源
      data.username = this.value.trim()
    })
  </script>

?

2.2、使用vue实现

在html页面中使用好vue需要完成如下步骤即可

  • 引入vue.js文件
  • 定义给vue.js管理的dom元素(给div定义一个ID)
  • 创建一个?Vue 的实例,并声明要渲染的数据源
  • 在给定的dom元素容器内,绑定数据源中变量名称{{变量名}}
  • Vue参数对象属性

????el:元素挂载的位置,值可以是CSS选择器或DOM元素

????data:模型数据,值是一个对象

  • 插值表达式

????将数据填充到HTML标签中

????支持基本的JavaScript计算操作,例如算术运算、字符串拼接等

?

下载vue.js

https://cn.vuejs.org/v2/guide/

?

<!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>Vue _ 数据双向绑定</title>
</head>
<body>
    <!-- 下面这是能在界面看见的部分就是 视图 部分 -->
    <!-- 被 Vue 管理 -->
    <div id="app">
        <!-- {{ 双花括号之间不能有空格 , 需要紧挨在一起 }} -->
        <h1> {{message}} </h1>
        <h2>{{name}}</h2>
    </div>
    <!-- 不被 Vue 管理 -->
    <div>{{message}}</div>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
    <script>
        /* 
        Vue 最大的特点 : 数据双向绑定
        这个双向绑定指的是谁和谁绑定的呢?? => 数据 和 视图
( 操作 数据 , DOM 也发生了变化 , input 输入框把 数据 告诉 app.message 这个属性
(由Vue 的实例 , 将上面的这一个 h1 进行了修改) )
        1. DOM 将数据传递给 Vue 实例
        2. Vue 实例的属性会传递给 DOM
        */
        // let(变量) / const(常量)
// 编程范式 : 声明式编程 ( 当我这个实例去帮我管理这个 div 的时候 , 
//你只需要告诉我这里写的什么东西就可以了 , 你只需要声明我这里需要显示什么东西就可以了 , 至于它内部如何处理的 , 无需知晓 )
        // 它的好处 : 可以真正做到数据和我们的界面完全分离 , 以后并不需要再通过代码去创建元素了
        // 创建 vue 实例
        const app = new Vue({
            // vue 实例的配置项:
            // element , vue 实例控制这一块 dom
            el: '#app', // 用于挂载要管理的元素
            // vue 实例的属性
            // data 内部的属性和属性值就是 vue 实例的属性和属性值
            // 下面 data 这一部分就是 数据
            data: { // 定义数据
                message: "hello Vue",
                name: '小灰狼'
            }
        });
        console.log(app.message);
        // 响应式: 就是当数据发生改变的时候, 界面会自动发生一些响应, 会跟着自动更改
        // 原始 js 的做法 : ( 编程范式 : 命令式编程 )
        // =>( 就是一步一步告诉你怎么做, 需要你每一步都指定的非常清除 , 他才知道怎么做 )
        // 1. 创建 div 元素 , 设置 id 属性
        // 2. 定义一个变量叫 message
        // 3. 将 message 变量放在前面的 div 元素中显示
        // 4. 修改 message 的数据: 今天下雨天气 !
        // 5. 将修改后的数据再次替换到 div 元素
    </script>
</body>
</html>

2.3、vue devtools工具安装

通过 chrome 中的谷歌插件商店安装 Vue Devtools 工具,此工具帮助我们进行 vue 数据调试所用,一定要安装。

https://chrome.google.com/webstore?utm_source=chrome-ntp-icon

https://chrome.zzzmh.cn/

?

  • 在vscode中安装插件

2.4、Vue实现数据绑定的原理

当把一个普通的JavaScript对象传给Vue实例的data选项,Vue将遍历此对象所有的属性,使用Object.defineProperty(vue2.x) , vue3.x 中使用了 Proxy 类?把这些属性全部转为 getter / setter (数据劫持)。在属性被访问和修改时通知变化。每个组件实例都有相应的?watcher 实例对象,它会在组件渲染的过程中把属性记录为依赖,之后当依赖项的 setter 被调用时,会通知 watcher 重新计算,从而致使它关联的组件得以更新。

vue实现数据响应式

<!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>Vue实现数据绑定的原理</title>
</head>
<body>
  <div id="root">
    ????<h3 v-text="title"></h3>
    <hr>
    ????<input type="text" v-model='title'>
  </div>
  <script>
    // 数据劫持
    let data = {
      title: '我是一个标题',
    };
    // 观察数据
    observe(data)
    // 给input绑定事件
    document.querySelector('[v-model]').addEventListener('input', function () {
      let key = this.getAttribute('v-model')
      data[key] = this.value.trim()
    })
    function observe(target) {
      if (!isObject(target)) return;
      for (let key in target) {
        defineReactive(target, key, target[key])
      }
    }
    // 数据劫持
    function defineReactive(target, key, value) {
      Object.defineProperty(target, key, {
        get() {
          console.log('get')
          return value
        },
        set(v) {
          if (v != value) {
            value = v
            console.log('set')
            // 更新视图
            updateView(value, key)
          }
        }
      })
    }
    function updateView(value, key) {
      document.querySelectorAll('[v-text]').forEach(node => {
        let attrValue = node.getAttribute('v-text')
        if (key === attrValue) {
          if (node.nodeName === 'INPUT') {
            node.value = value;
          } else {
            node.innerHTML = value;
          }
        }
      })
    }
    function isObject(target) {
      // return target !== null && typeof target === 'object' && !(target instanceof Array)
      // return Object.prototype.toString.call(target) === '[object Object]'
      return ({}).toString.call(target) === '[object Object]'
    }
  </script>
</body>
</html>
<!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>数据劫持</title>
</head>
<body>
  <div id="app">
    <h3 v-text="msg"></h3>
    <h3 v-text="age"></h3>
    <hr>
    <input type="text" v-model="msg">
  </div>
  <script>
    var data = {
      msg: '你好mvvm',
      age: 20,
      user: { id: 1 },
      user_id: 1,
      user_name: 'aa'
    }
    
    // let target = { id: 100 }
    // 冻结对象 对象就没有办法修改了
    // target = Object.freeze(target)
    // target.id = 200
    // let target = {}

    // 数据劫持
    observe(data)
    // 模板编译
    compileRender(data)

    function observe(target) {
      // 只劫持json对象
      if (Object.prototype.toString.call(target) != '[object Object]') return;
      // 遍历
      for (let key in target) {
        defineRactive(target, key, target[key])
      }
    }

    function defineRactive(target, key, value) {
      observe(value)
      /* if (Object.prototype.toString.call(value) == '[object Object]') {
        observe(value)
        return;
      } */
      // 劫持当前的对象
      // defineProperty 它只能对对象中的属性进行劫持,不能劫持数组
      Object.defineProperty(target, key, {
        // 获取器
        get() {
          console.log('get')
          return value
        },
        // 修改器
        set(newV) {
          if (newV != value) {
            console.log('set')
            value = newV
            // 通知模板编译一下
            compileRender(target)
          }
        }
      });
    }

    function compileRender(target) {
      // 模板编译
      // 文本
      document.querySelectorAll(`[v-text]`).forEach(node => {
        // 要去数据源中查找的数据key
        let key = node.getAttribute('v-text')
        let value = target[key] || 0
        node.innerHTML = value
      })
      // 输入框
      document.querySelectorAll(`[v-model]`).forEach(node => {
        let key = node.getAttribute('v-model')
        let value = target[key] || 0
        node.value = value
        // 绑定一个事件
        node.addEventListener('input', function () {
          target[key] = this.value.trim()
        })
      })
    }
  </script>
</body>
</html>

相关知识点 :??

let target = { id: 100 }
冻结对象 , 对象就没有办法修改了
target = Object.freeze( target )
target.id = 200?


? // dom操作在内存中完成
=>?文档碎片 --> 在内存在存储,不会在界面中渲染,通过 appendChild 渲染到视图中
语法 :? document.createDocumentFragment( )?

作用 : 可以承载节点 , 当把文档碎片插入页面时 , 文档碎片不进入页面 , 只有文档碎片里面承载的内容进入页面 ( 往内存里写入东西比往页面里写入东西会更快 )?


( 1 ) 数据劫持-跳转链接? :??数据劫持 _ 简述版

( 2 ) 观察者模式 : 设计模式


自己来实现一个 _ MVVM :?

<!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>实现一个 _ MVVM</title>
  <script src="./js/myVue.js"></script>
</head>
<body>
  <div id="app">
    <h3>{{ title }}</h3>
    <input type="text" v-model='title'>
  </div>
  <script>
    const vm = new Vue({
      el: '#app',
      data: {
        title: '你好MVVM'
      }
    })
  </script>
</body>
</html>
class Vue {
  constructor(options) {
    // 挂载点的 dom
    this.$el = document.querySelector(options.el)
    // 数据
    this.$data = options.data
    // 数据劫持
    observe(this.$data)
    //模板编译
    compileTemplate(this.$el, this)
  }
}

// 观察仓库
class Dep {
  constructor() {
    // 观察者队列
    this.subscribes = []
  }
  // 添加观察者
  addSub(watcher) {
    this.subscribes.push(watcher)
  }
  // 通知更新
  notify() {
    this.subscribes.forEach(watcher => watcher.update())
  }
}
// 观察者
class Watcher {
  constructor(vm, key, node) {
    // 仓库对象的静态属性来保存当前watcher实例对象
    Dep.target = this;
    this.$vm = vm;
    this.$key = key;
    this.$node = node;
    // 触发数据劫持中的get方法,此时Dep.target的值为当前对象
    this.getValue();
    // 设置为null,为下次new Watcher准备
    Dep.target = null;
  }
  getValue() {
    // 触发get
    this.$value = this.$vm.$data[this.$key]
  }
  update() {
    // 获取一下最新数据
    this.getValue();
    if (this.$node.nodeType === 1) {
      if (this.$node.nodeName == 'INPUT') {
        this.$node.value = this.$value
      } else {
        this.$node.innerHTML = this.$value
      }
    } else if (this.$node.nodeType === 3) {
      this.$node.textContent = this.$value
    }
  }
}

// 模板编译
function compileTemplate(el, vm) {
  // dom操作在内存中完成
  // 文档碎片 --> 在内存在存储,不会在界面中渲染,通过appendChild渲染到视图中
  let fragment = document.createDocumentFragment()
  let childNode;
  while (childNode = el.firstChild) {
    // 渲染模板
    compileRender(childNode, vm)
    // 把得到的dom对象放到fragment中,此时dom会删除
    fragment.appendChild(childNode)
  }
  // 处理完成后,放到视图中
  el.appendChild(fragment)
}
// 编译视图显示
function compileRender(node, vm) {
  // 判断当前节点的类型 1元素,3文本
  if (node.nodeType === 1) {
    // 得到元素所有的属性集合
    // [...node.attributes].forEach(attrObj => {
    // console.log(attrObj.name, attrObj.value);
    [...node.attributes].forEach(({ name, value }) => {
      // 只关心v-开头属性
      if (/^v-/.test(name)) {
        if (name === 'v-model') { // 针对于input输入框
          node.value = vm.$data[value]
          // 观察者
          new Watcher(vm, value, node)
          // 绑定事件
          node.addEventListener('input', function () {
            vm.$data[value] = this.value.trim()
          });
        } else {
          // 观察者
          new Watcher(vm, value, node)
          node.innerHTML = vm.$data[value]
        }
      }
    });
    // 问一下有没有子元素了
    node.childNodes.forEach(child => compileRender(child, vm))
  } else if (node.nodeType === 3) { // 文本节点
    // 内容
    let cnt = node.textContent
    // 匹配只有{{}}才进行处理
    let preg = /\{\{\s*(\w+)\s*\}\}/
    // 替换
    cnt = cnt.replace(preg, (a0, a1) => {
      // 观察者
      new Watcher(vm, a1, node)
      return vm.$data[a1]
    })
    node.textContent = cnt
  }
}

// ------------------- 数据劫持
// 监听数据源
function observe(target) {
  // 只劫持json对象
  if (Object.prototype.toString.call(target) != '[object Object]') return;
  // 遍历
  for (let key in target) {
    defineRactive(target, key, target[key])
  }
}
// 实现劫持
function defineRactive(target, key, value) {
  observe(value)
  let dep = new Dep()
  Object.defineProperty(target, key, {
    // 获取器
    get() {
      if (Dep.target) {
        // 添加了观察者到通知队列中
        dep.addSub(Dep.target)
      }
      return value
    },
    // 修改器
    set(newV) {
      if (newV != value) {
        value = newV
        dep.notify()
      }
    }
  });
}

三、模板语法

3.1、插值表达式

插值表达式是vue框架提供的一种在html模板中绑定数据的方式,使用{{变量名}}方式绑定Vue实例中data中的数据变量。会将绑定的数据实时的显示出来。

# 支持写法

{{ 变量js 表达式、三目运算符、方法调用 等 }}

<div id="app">

<h3>{{ name }}</h3>

<h3>{{ name + '--好的' }}</h3>

<h3>{{ 1 + 1 }}</h3>

<!-- 使用函数 -->

<h3>{{ title.substr(0,6) }}</h3>

<!-- 三目运算 -->

<h3>{{ age>22 ? '成年':'未成年' }}</h3>

</div>

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

<script>

??new Vue({

????el: '#app',

????data: {

??????title: '我是一个标题,你们看到没有',

??????name: '张三',

??????age: 20

????}

??})

</script>

注:{{ }}括起来的区域,就是一个就是 js 语法区域,在里面可以写部份的 js 语法。不能写?var a = 10; 分支语句 循环语句

<!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>Vue的使用</title>
  <!-- 引入vue.js类库 -->
  <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
  <!-- 指定vue要去解析的模板挂载点 -->
  <div id="app">
    <div>{{ msg }}</div>
    <div>{{ msg+'123' }}</div>
    <div>{{ 1 + 2 }}</div>
    <div>{{ msg.substr(0,2) }}</div>
    <div>{{ fn() }}</div>
    <div>{{ age<18?'儿童':'成年' }}</div>
    <!-- 这样不可以,不能赋值,只能使用 -->
    <!-- <div>{{ var a=10 }}</div> -->
  </div>
  <script>
    // 实例化Vue
    const vm = new Vue({
      el: '#app',
      data: {
        msg: '你好Vue',
        age: 18
        /* fn() {
          return 'hello fn'
        } */
      },
      // vue专门用来给写方法所用配置
      methods: {
        /* fn() {
          return 'hello fn'
        }  */
        // 在vue中的methods方法,定义时不能使用箭头函数,使用后this指向就会不对
        // 方法里面定义函数建议使用箭头函数,保持this指向
        fn: function () {
          // return 'hello fn@' + this.$data.msg
          setTimeout(() => {
            console.log(this)
          }, 3000);
          return 'hello fn@' + this.msg
        }
        // fn: () => {
        //   // this undefined => 现在没有开启强制模式
        //   // 在vue.js引入的方案中它是window
        //   // console.log(this)
        //   return 'hello fn@' + this.msg
        // }
      }
    })
  </script>
</body>
</html>

?

3.2、指令

指令(Directives)就是vue给html标签提供的一些自定义属性,这样属性都是带有?v-?前缀的特殊属性。指令特性的值预期是单个JS表达式(v-for是例外情况)。指令的职责是,当表达式的值改变时,将其产生的连带影响,响应式地作用于DOM。

指令作用:

  • 操作dom
  • 权限限制
  • 表单验证

v-html 解析html指令 ?注:尽量避免使用,容易造成危险?(XSS跨站脚本攻击)

v-text 输出文本信息

-----------------------------------------------------

<div id="app">

<!-- 转义html -->

<h3>{{html}}</h3>

<!-- 解析 html -->

<div v-html="html"></div>

<!-- 转义html -->

<div v-text="html"></div>

</div>

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

<script>

??new Vue({

????el: '#app',

????data: {

??????html:'<a href="http://www.baidu.com/">百度一下</a>'

????}

??})

</script>


四、常用指令

指令扩展了html标签的功能、大部分的指令的值是js的表达式,取代了DOM操作。

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2021-08-26 12:02:06  更:2021-08-26 12:02:13 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 13:03:34-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码